diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml
new file mode 100644
index 0000000000..27ec1b2828
--- /dev/null
+++ b/.github/workflows/coding-style.yml
@@ -0,0 +1,17 @@
+name: Coding Style
+
+on: [push, pull_request]
+
+jobs:
+    nette_cc:
+        name: Nette Code Checker
+        runs-on: ubuntu-latest
+        steps:
+            - uses: actions/checkout@v3
+            - uses: shivammathur/setup-php@v2
+              with:
+                  php-version: 8.3
+                  coverage: none
+
+            - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress
+            - run: php temp/code-checker/code-checker --no-progress
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 550b89053d..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: php
-
-script:
-    - php code-checker/src/code-checker.php
-
-before_script:
-    - travis_retry composer create-project nette/code-checker code-checker ~2.5 --no-interaction
-
-sudo: false
-
-cache:
-    directories:
-        - $HOME/.composer/cache
diff --git a/application/bg/@home.texy b/application/bg/@home.texy
index e01b54f4ee..341c43ef6e 100644
--- a/application/bg/@home.texy
+++ b/application/bg/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | версия на пакета | съвместима версия на PHP
 |-----------------------|-----------------------
-| Nette Application 4.0 | PHP 8.0 - 8.1
-| Nette Application 3.1 | PHP 7.2 - 8.1
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/bg/ajax.texy b/application/bg/ajax.texy
index 1bcf75bc98..04cc36448d 100644
--- a/application/bg/ajax.texy
+++ b/application/bg/ajax.texy
@@ -3,10 +3,10 @@ AJAX и фрагменти
 
 <div class=perex>
 
-Съвременните уеб приложения днес се изпълняват наполовина на сървъра и наполовина в браузъра. AJAX е важен обединяващ фактор. Каква поддръжка предлага рамката Nette?
-- Подаване на фрагменти (наречени *фрагменти*)
-- прехвърляне на променливи между PHP и JavaScript
-- отстраняване на грешки в приложенията AJAX
+В ерата на съвременните уеб приложения, където функционалността често се разпростира между сървъра и браузъра, AJAX е важен свързващ елемент. Какви възможности предлага Nette Framework в тази област?
+- Изпращане на части от шаблона, т.нар. фрагменти
+- предаване на променливи между PHP и JavaScript
+- инструменти за отстраняване на грешки при AJAX заявките
 
 </div>
 
@@ -14,29 +14,32 @@ AJAX и фрагменти
 Заявка AJAX .[#toc-ajax-request]
 ================================
 
-Заявката AJAX не се различава от класическата заявка - водещият се извиква с определен изглед и параметри. От водещия също зависи как да отговори на нея: той може да използва своя собствена процедура, която връща фрагмент от HTML код (HTML snippet), XML документ, JSON обект или JavaScript код.
+Заявката AJAX не се различава съществено от класическата HTTP заявка. Извиква се презентатор с определени параметри. От водещия зависи как да отговори на заявката - той може да върне данни във формат JSON, да изпрати част от HTML код, XML документ и т.н.
 
-От страна на сървъра AJAX заявката може да бъде открита с помощта на метода на услугата, [капсулиращ HTTP заявката |http:request] `$httpRequest->isAjax()` (открива се въз основа на HTTP заглавието `X-Requested-With`). Вътре в презентатора е наличен пряк път под формата на метода `$this->isAjax()`.
+От страна на браузъра инициираме AJAX заявка, като използваме функцията `fetch()`:
 
-Съществува предварително обработен обект `payload`, предназначен за изпращане на данни към браузъра във формат JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Успешно';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// обработка на отговора
+});
 ```
 
-За да имате пълен контрол върху извеждането на JSON, използвайте метода `sendJson` в презентатора. Това веднага ще прекъсне презентатора и ще се справите без шаблона:
+От страна на сървъра AJAX заявката се разпознава чрез метода `$httpRequest->isAjax()` на услугата, която [капсулира HTTP заявката |http:request]. Той използва HTTP заглавието `X-Requested-With`, така че е от съществено значение да го изпратите. В рамките на презентатора можете да използвате метода `$this->isAjax()`.
+
+Ако искате да изпратите данни във формат JSON, използвайте метода [`sendJson()` |presenters#Sending a response] метод. Методът също така прекратява дейността на презентатора.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Ако искаме да изпращаме HTML, можем да създадем специален шаблон за AJAX заявки:
+Ако планирате да отговорите със специален шаблон, предназначен за AJAX, можете да го направите по следния начин:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Извадки .[#toc-snippets]
+========================
+
+Най-мощният инструмент, предлаган от Nette за свързване на сървъра с клиента, са фрагментите. С тях можете да превърнете едно обикновено приложение в AJAX приложение с минимални усилия и няколко реда код. Примерът Fifteen демонстрира как работи всичко това, а кодът му може да бъде намерен в [GitHub |https://github.com/nette-examples/fifteen].
+
+Извадките или изрезките ви позволяват да актуализирате само части от страницата, вместо да презареждате цялата страница. Това е по-бързо и по-ефективно, а също така осигурява по-удобно потребителско изживяване. Snippets може да ви напомнят за Hotwire за Ruby on Rails или Symfony UX Turbo. Интересното е, че Nette въвежда фрагментите 14 години по-рано.
+
+Как работят отрязъците? Когато страницата се зарежда за първи път (заявка, която не е свързана с AJAX), се зарежда цялата страница, включително всички фрагменти. Когато потребителят взаимодейства със страницата (напр. щракне върху бутон, изпрати формуляр и т.н.), вместо да се зареди цялата страница, се прави AJAX заявка. Кодът в презентатора извършва действието и решава кои фрагменти се нуждаят от актуализиране. Nette визуализира тези фрагменти и ги изпраща под формата на JSON масив. След това кодът за обработка в браузъра вмъква получените фрагменти обратно в страницата. Следователно се прехвърля само кодът на променените фрагменти, което спестява честотна лента и ускорява зареждането в сравнение с прехвърлянето на цялото съдържание на страницата.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-[Библиотеката Naja |https://naja.js.org] се използва за обработка на AJAX заявки от страна на браузъра. [Инсталирайте |https://naja.js.org/#/guide/01-install-setup-naja] го като пакет за node.js (за използване с Webpack, Rollup, Vite, Parcel и други):
+За обработка на фрагменти от страна на браузъра се използва [библиотеката Naja |https://naja.js.org]. [Инсталирайте я |https://naja.js.org/#/guide/01-install-setup-naja] като пакет за node.js (за използване с приложения като Webpack, Rollup, Vite, Parcel и други):
 
 ```shell
 npm install naja
 ```
 
-...или да вмъкнете директно в шаблон на страница:
+... или я вмъкнете директно в шаблона на страницата:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-За да създадете AJAX заявка от обикновена връзка (сигнал) или подаване на формуляр, просто маркирайте съответната връзка, формуляр или бутон с класа `ajax`:
+Първо трябва да [инициализирате |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] библиотеката:
+
+```js
+naja.initialize();
+```
+
+За да превърнете обикновена връзка (сигнал) или подаване на форма в AJAX заявка, просто маркирайте съответната връзка, форма или бутон с класа `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ npm install naja
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Извадки .[#toc-snippety]
-========================
-
-Има обаче много по-мощен инструмент за вградена поддръжка на AJAX - фрагменти. Използването им ви позволява да превърнете обикновено приложение в AJAX приложение само с няколко реда код. Как работи всичко това, е показано в примера Fifteen, чийто код също е наличен в компилацията или в [GitHub |https://github.com/nette-examples/fifteen].
-
-Принципът на фрагментите е, че цялата страница се прехвърля по време на първоначалната (т.е. не-AJAX) заявка и след това при всяка AJAX [подзаявка |components#Signal] (заявка на същия изглед от същия водещ) само кодът на променените части се прехвърля в хранилището `payload`, споменато по-рано.
-
-Извадките може да ви напомнят за Hotwire за Ruby on Rails или Symfony UX Turbo, но Nette ги изобретява четиринадесет години по-рано.
-
+Прерисуване на фрагменти .[#toc-redrawing-snippets]
+---------------------------------------------------
 
-Инвалидизация .[#toc-invalidation-of-snippets]
-==============================================
-
-Всеки наследник на класа [Control |components] (какъвто е Presenter) може да запомни дали по време на заявката е имало промени, които изискват повторно картографиране. Съществуват няколко начина за справяне с това: `redrawControl()` и `isControlInvalid()`. Пример:
+Всеки обект от класа [Control |components] (включително самият Presenter) запазва запис дали са настъпили промени, които налагат прерисуването му. За тази цел се използва методът `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Обектът трябва да бъде показан отново, след като потребителят е влязъл в системата
+	// след като влезете в системата, е необходимо да прерисувате съответната част
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette обаче осигурява още по-фина разделителна способност от целите компоненти. Изброените методи приемат името на така наречения "фрагмент" като незадължителен параметър. "Фрагмент" по същество е елемент от вашия шаблон, маркиран с макрос Latte за тази цел, за който ще стане дума по-късно. По този начин можете да поискате от компонент да прерисува само *част* от шаблона. Ако целият компонент е невалиден, всички негови фрагменти се прерисуват. Компонент е "невалиден", ако някой от неговите подкомпоненти е невалиден.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // обезсилване на фрагмента с име 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, поне един фрагмент е невалиден
+Nette също така позволява по-фино управление на това, което трябва да се прерисува. Гореспоменатият метод може да приема името на фрагмента като аргумент. По този начин е възможно да се обезсили (което означава: да се наложи прерисуване) на ниво част от шаблона. Ако целият компонент бъде обезсилен, всеки фрагмент от него също ще бъде прерисуван:
 
-$this->redrawControl(); // обезсилва целия компонент, всеки фрагмент
-$this->isControlInvalid('footer'); // -> true
+```php
+// обезсилва фрагмента 'header'
+$this->redrawControl('header');
 ```
 
-Компонент, който е получил сигнал, автоматично се маркира за прерисуване.
-
-Чрез преначертаване на срезовете знаем точно кои части от кои елементи трябва да бъдат преначертани.
-
-
-Етикет `{snippet} … {/snippet}` .{toc: Tag snippet}
-===================================================
-
-Страницата се визуализира по същия начин, както при обикновена заявка: зареждат се същите шаблони и т.н. Най-важното обаче е да се предотвратят онези части, които не трябва да се извеждат; останалите части трябва да се свържат с идентификатор и да се изпратят на потребителя във формат, който обработващият JavaScript може да разбере.
-
 
-Синтаксис .[#toc-sintaksis]
----------------------------
+Извадки в Latte .[#toc-snippets-in-latte]
+-----------------------------------------
 
-Ако в шаблона има контролен елемент или фрагмент, трябва да го обгърнем с помощта на сдвоения таг `{snippet} ... {/snippet}` - визуализираният фрагмент ще бъде "изрязан" и изпратен на браузъра. Освен това той ще го обгърне със спомагателен таг `<div>` (можете да използвате друга). Следващият пример дефинира фрагмент с име `header`. Той може да представлява и шаблон на компонент:
+Използването на фрагменти в Latte е изключително лесно. За да определите част от шаблона като фрагмент, просто я обвийте в тагове `{snippet}` и `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ $this->isControlInvalid('footer'); // -> true
 {/snippet}
 ```
 
-Ако искате да създадете фрагмент със съдържащ елемент, различен от `<div>`, или да добавите потребителски атрибути към елемента, можете да използвате следното определение:
+Извадката създава елемент `<div>` в HTML страницата със специално генериран `id`. При прерисуване на фрагмент съдържанието на този елемент се актуализира. Следователно при първоначалното визуализиране на страницата трябва да се визуализират и всички фрагменти, дори ако първоначално те могат да бъдат празни.
+
+Можете също така да създадете фрагмент с елемент, различен от `<div>` като използвате атрибут n::
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ $this->isControlInvalid('footer'); // -> true
 ```
 
 
-Динамични фрагменти .[#toc-dinamiceskie-snippety]
-=================================================
+Области на извадките .[#toc-snippet-areas]
+------------------------------------------
 
-В Nette можете също така да дефинирате фрагменти с динамично име въз основа на параметър по време на изпълнение. Това е най-подходящо за различни списъци, в които трябва да променим само един ред, но не искаме да преместим целия списък заедно с него. Пример за това е:
+Имената на фрагментите могат да бъдат и изрази:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Съществува един статичен фрагмент `itemsContainer`, който съдържа няколко динамични фрагмента: `пункт-0`, `пункт-1` и т.н.
+По този начин ще получим няколко фрагмента като `item-0`, `item-1` и т.н. Ако директно обезсилим динамичен фрагмент (например `item-1`), нищо няма да бъде прерисувано. Причината е, че фрагментите функционират като истински откъси и само те самите се визуализират директно. В шаблона обаче технически няма фрагмент с име `item-1`. Той се появява само при изпълнение на заобикалящия го код на фрагмента, в този случай цикъла foreach. Следователно ще маркираме частта от шаблона, която трябва да се изпълни, с тага `{snippetArea}`:
 
-Не можете да прерисувате динамичния фрагмент директно (прерисуването на `item-1` няма ефект), а трябва да прерисувате родителския фрагмент ( `itemsContainer` в този пример). При това се изпълнява кодът на родителския фрагмент, но на браузъра се предават само неговите вложени фрагменти. Ако искате да предадете само един от вложените фрагменти, трябва да промените входа за родителския фрагмент, за да избегнете генерирането на други вложени фрагменти.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-В горния пример трябва да се уверите, че само един елемент ще бъде добавен към масива `$list`, когато бъде направена заявката AJAX, така че цикълът `foreach` ще изведе само един динамичен фрагмент.
+И ще прерисуваме както отделния фрагмент, така и цялата обща област:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * Этот метод возвращает данные для списка.
-	 * Обычно это просто запрос данных из модели.
-	 * Для целей этого примера данные жёстко закодированы.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Също така е важно да се гарантира, че масивът `$items` съдържа само елементите, които трябва да бъдат прерисувани.
 
-Извадки в активирания шаблон .[#toc-snippety-vo-vklyucennom-sablone]
-====================================================================
-
-Възможно е даден фрагмент да се намира в шаблон, който е включен от друг шаблон. В този случай е необходимо да се обгърне кодът за разрешаване във втория шаблон с макроса `snippetArea`, след което да се прерисуват както областта snippetArea, така и самият фрагмент.
-
-Макросът `snippetArea` гарантира, че кодът в него ще бъде изпълнен, но само действителният фрагмент от включения шаблон ще бъде изпратен на браузъра.
+При вмъкване на друг шаблон в основния с помощта на тага `{include}`, който има фрагменти, е необходимо отново да се обвие включеният шаблон в `snippetArea` и да се обезсилят заедно и фрагментът, и областта:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Можете също така да го комбинирате с динамични фрагменти.
 
+Извадки в компонентите .[#toc-snippets-in-components]
+-----------------------------------------------------
 
-Добавяне и премахване .[#toc-dobavlenie-i-udalenie]
-===================================================
-
-Ако добавите нов елемент в списъка и отмените `itemsContainer`, заявката AJAX ще върне фрагменти, включващи новия елемент, но обработващият javascript няма да може да го визуализира. Това е така, защото няма HTML елемент с новосъздадения ID.
-
-В този случай най-лесният начин е да обвиете целия списък в друг фрагмент и да го обезсилите:
+Можете да създавате фрагменти в [компонентите |components] и Nette автоматично ще ги прерисува. Има обаче специфично ограничение: за да прерисува отрязъци, той извиква метода `render()` без никакви параметри. По този начин подаването на параметри в шаблона няма да работи:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Добавить</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Изпращане на потребителски данни .[#toc-sending-user-data]
+----------------------------------------------------------
+
+Заедно с фрагментите можете да изпращате всякакви допълнителни данни на клиента. Просто ги запишете в обекта `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Същото важи и за изтриване на елемент. Може да се подаде празен фрагмент, но обикновено списъците могат да бъдат странирани и би било трудно да се приложи премахването на един елемент и зареждането на друг (който преди това е бил на друга страница на странирания списък).
 
+Изпращане на параметри .[#toc-sending-parameters]
+=================================================
 
-Изпращане на параметри към компонент .[#toc-otpravka-parametrov-komponentu]
-===========================================================================
-
-Когато изпращаме параметри към компонент чрез заявка AJAX, независимо дали става въпрос за сигнални или постоянни параметри, трябва да предоставим тяхното глобално име, което съдържа и името на компонента. Пълното име на параметъра се връща от метода `getParameterId()`.
+Когато изпращаме параметри към компонента чрез AJAX заявка, независимо дали става въпрос за сигнални или постоянни параметри, трябва да предоставим тяхното глобално име, което съдържа и името на компонента. Пълното име на параметъра се връща от метода `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-И обработете метода със съответните параметри в компонента.
+Метод за обработка със съответните параметри в компонента:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/bg/bootstrap.texy b/application/bg/bootstrap.texy
index 8d0b3dc5c4..2ac3dc2e99 100644
--- a/application/bg/bootstrap.texy
+++ b/application/bg/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Конфигураторът отговаря за настройката на средата на приложението и услугите.
+		$this->configurator = new Configurator;
+		// Задайте директорията за временни файлове, генерирани от Nette (напр. компилирани шаблони)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette е интелигентен и режимът за разработка се включва автоматично,
+		// или можете да го включите за определен IP адрес, като разкоментирате следния ред:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Активира Tracy: най-добрият инструмент за отстраняване на грешки "швейцарско ножче".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: автоматично зарежда всички класове в дадената директория
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Зареждане на конфигурационни файлове
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-В случая на уеб приложения началният файл е `index.php`, който се намира в публичната директория `www/`. Той позволява на класа `Bootstrap` да инициализира средата и връща `$configurator`, който създава контейнера DI. След това тя извлича услугата `Application`, която стартира уеб приложението:
+Началният файл за уеб приложенията е `index.php`, разположен в публичната директория `www/`. Той използва класа `Bootstrap` за инициализиране на средата и създаване на контейнер DI. След това получава услугата `Application` от контейнера, която стартира уеб приложението:
 
 ```php
-// инициализиране на средата + получаване на обект Configurator
-$configurator = App\Bootstrap::boot();
-// създаване на DI-контейнер
-$container = $configurator->createContainer();
-// DI-контейнерът ще създаде обект Nette\Application\Application
+$bootstrap = new App\Bootstrap;
+// Иницииране на средата + създаване на контейнер DI
+$container = $bootstrap->bootWebApplication();
+// Контейнерът DI създава обект Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-//стартиране на приложението Nette
+// Стартирайте приложението Nette и обработете входящата заявка
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Nette прави разграничение между два основни р
 Ако искате да активирате режима за разработка в други случаи, например за програмисти, които имат достъп от определен IP адрес, можете да използвате `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // един или повече IP адреси
+$this->configurator->setDebugMode('23.75.345.200'); // един или повече IP адреси
 ```
 
 Определено препоръчваме да комбинирате IP адреса с "бисквитка". Ще съхраним тайния токен в "бисквитката" `nette-debug', например, `secret1234`, а режимът за разработка ще бъде активиран за програмистите с тази комбинация от IP и "бисквитка".
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Можете да деактивирате напълно режима за разработчици, дори за localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Обърнете внимание, че стойността `true` активира плътно режима за разработчици, което никога не трябва да се случва на производствен сървър.
@@ -90,7 +115,7 @@ $configurator->setDebugMode(false);
 За да улесним дебъгването, ще включим чудесния инструмент [Tracy |tracy:]. В режим за разработчици той визуализира грешките, а в производствен режим записва грешките в определена директория:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ $configurator->enableTracy($appDir . '/log');
 Nette използва кеш за DI-контейнер, RobotLoader, шаблони и др. Затова е необходимо да се зададе пътят до директорията, в която се съхранява кешът:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 В Linux или macOS задайте [разрешения за запис |nette:troubleshooting#Setting-Directory-Permissions] за директориите `log/` и `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Обикновено искаме да заредим класовете автоматично с помощта на [RobotLoader |robot-loader:], така че трябва да го стартираме и да му позволим да зареди класовете от директорията, в която се намира `Bootstrap.php` (т.е. `__DIR__`) и всички негови поддиректории:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ $configurator->createRobotLoader()
 Конфигураторът ви позволява да зададете часовата зона за вашето приложение.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ $configurator->setTimeZone('Europe/Prague');
 Файловете за конфигурация се зареждат с помощта на `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Методът `addConfig()` може да се извика няколко пъти, за да се добавят няколко файла.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ if (PHP_SAPI === 'cli') {
 Параметрите, използвани в конфигурационните файлове, могат да бъдат дефинирани [в раздела `parameters` |dependency-injection:configuration#parameters] и да бъдат взети (или презаписани) от метода `addStaticParameters()` (той има псевдоним `addParameters()`). Важно е, че различните стойности на параметрите водят до генериране на допълнителни DI-контейнери, т.е. допълнителни класове.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ $configurator->addStaticParameters([
 Възможно е също така да се добавят динамични параметри към контейнер. Различните им стойности, за разлика от статичните параметри, не генерират нови контейнери DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Достъпът до променливите на средата е лесен с помощта на динамични параметри. Достъпът до тях се осъществява чрез `%env.variable%` в конфигурационните файлове.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ $configurator->addDynamicParameters([
 - `%wwwDir%` е абсолютният път до директорията, съдържаща входния файл `index.php`
 - `%tempDir%` е абсолютният път до директорията за временни файлове
 - `%vendorDir%` е абсолютният път до директорията, в която Composer инсталира библиотеки
+- `%rootDir%` е абсолютният път до главната директория на проекта
 - `%debugMode%` показва дали приложението е в режим на отстраняване на грешки
 - `%consoleMode%` показва дали заявката е постъпила от командния ред
 
@@ -225,7 +252,7 @@ services:
 Създайте нов екземпляр и го вмъкнете в Bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Различни среди .[#toc-different-environments]
 =============================================
 
-Не се колебайте да персонализирате класа `Bootstrap` според нуждите си. Можете да добавите параметри към метода `boot()`, за да разделите уеб проектите, или да добавите други методи, като например `bootForTests()`, който инициализира средата за тестове на единици, `bootForCli()` за скриптове, извикани от командния ред, и т.н.
+Не се колебайте да персонализирате класа `Bootstrap` според нуждите си. Можете да добавите параметри към метода `bootWebApplication()`, за да разграничите отделните уеб проекти. Като алтернатива можете да добавите и други методи, например `bootTestEnvironment()` за инициализиране на средата за unit тестове, `bootConsoleApplication()` за скриптове, извикани от командния ред, и т.н.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Инициализация на Nette Tester
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Инициализация Nette Tester
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/bg/components.texy b/application/bg/components.texy
index 3bd9a2ebf9..ab5c216e1c 100644
--- a/application/bg/components.texy
+++ b/application/bg/components.texy
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // пренасочване
 ```
 
 
+Пренасочване след сигнал .[#toc-redirection-after-a-signal]
+===========================================================
+
+След обработката на сигнал от компонент често следва пренасочване. Тази ситуация е подобна на формулярите - след изпращане на формуляр също пренасочваме, за да предотвратим повторното изпращане на данни, когато страницата се опреснява в браузъра.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Тъй като компонентът е елемент за многократна употреба и обикновено не трябва да има пряка зависимост от конкретни презентатори, методите `redirect()` и `link()` автоматично интерпретират параметъра като сигнал за компонент:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Ако трябва да пренасочите към друг презентатор или действие, можете да го направите чрез презентатора:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Постоянни параметри .[#toc-persistent-parameters]
 =================================================
 
@@ -347,7 +369,7 @@ services:
 Накрая ще използваме тази фабрика в нашия презентатор:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ interface PollControlFactory
 Компонентите в Nette Application са части за многократна употреба на уеб приложение, които вграждаме в страници, което е предмет на тази глава. Какви са възможностите на такъв компонент?
 
 1) може да се показва в шаблон
-2) той знае каква част от себе си да покаже по време на [заявката AJAX |ajax#invalidation] (фрагменти)
+2) знае [коя част от себе си |ajax#snippets] да визуализира по време на заявка AJAX (фрагменти).
 3) има възможност да съхранява състоянието си в URL (постоянни параметри).
 4) има възможност да реагира на действията (сигналите) на потребителя.
 5) създава йерархична структура (където коренът е главният).
diff --git a/application/bg/configuration.texy b/application/bg/configuration.texy
index c017613f9c..0e2aeb11b1 100644
--- a/application/bg/configuration.texy
+++ b/application/bg/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# показва раздела "Nette Application" на синия екран на Tracy?
 	debugger: ...           # (bool) по подразбиране е true
 
-	# ще бъде ли извикан презентаторът на грешки в случай на грешка?
-	catchExceptions: ...    # (bool) по подразбиране е true на "battle" сървър
+	# Ще се извика ли error-presenter при грешка?
+	# има ефект само в режим за разработчици
+	catchExceptions: ...    # (bool) по подразбиране е true
 
 	# име на водещ на грешка
-	errorPresenter: Error   # (string) по подразбиране е 'Nette:Error'
+	errorPresenter: Error   # (string|array) по подразбиране е 'Nette:Error'
+
+	# дефинира псевдоними за водещи и събития
+	aliases: ...
 
 	# дефинира правила за съпоставяне на името на водещия с клас
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) по подразбиране е false
 ```
 
-Тъй като в режим на разработка презентаторите на грешки не се извикват по подразбиране, а грешките се показват от Tracy, промяната на стойността на `catchExceptions` на `true` помага да се провери дали презентаторите на грешки работят правилно по време на разработката.
+От версия 3.2 на `nette/application` е възможно да се дефинира двойка представящи грешки:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # за Nette\Application\BadRequestException
+		5xx: Error5xx   # за други изключения
+```
 
 Опцията `silentLinks` определя как Nette да се държи в режим на разработчик, когато генерирането на връзки е неуспешно (например поради липса на презентатор и т.н.). Стойността по подразбиране `false` означава, че Nette работи `E_USER_WARNING`. Задаването на `true` потиска това съобщение за грешка. В производствена среда винаги се извиква `E_USER_WARNING`. Можем също така да повлияем на това поведение, като зададем променливата на водещия [$invalidLinkMode |creating-links#Invalid-Links].
 
+[Псевдонимите опростяват препратките към |creating-links#aliases] често използвани презентатори.
+
 Съпоставянето [определя правилата, по които |modules#Mapping] името на класа се извежда от основното име.
 
 
@@ -82,6 +95,9 @@ latte:
 	# позволява [проверка на генерирания код |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) по подразбиране е null
 
+	# задава локала
+	locale: cs_CZ        # (string) по подразбиране е null
+
 	# клас $this->template
 	templateClass: App\MyTemplateClass # по подразбиране Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ latte:
 ```neon
 latte:
 	расширения:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/bg/creating-links.texy b/application/bg/creating-links.texy
index 659326e6fe..ebdffa92c5 100644
--- a/application/bg/creating-links.texy
+++ b/application/bg/creating-links.texy
@@ -38,7 +38,7 @@
 <a n:href="Product:show $product->id, lang: en">подробнее</a>
 ```
 
-Ако методът `ProductPresenter::renderShow()` няма `$lang` в сигнатурата си, той може да прочете стойността на параметъра, като използва `$lang = $this->getParameter('lang')`.
+Ако методът `ProductPresenter::renderShow()` няма `$lang` в сигнатурата си, той може да извлече стойността на параметъра, като използва `$lang = $this->getParameter('lang')` или от [свойството |presenters#Request Parameters].
 
 Ако параметрите се съхраняват в масив, те могат да бъдат разширени с помощта на оператора `(expand)` (нещо като `...` в PHP, но работи с асоциативни масиви):
 
@@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 <a n:href="this">обновить</a>
 ```
 
-Това ще предаде всички параметри, посочени в сигнатурата на метода. `render<View>()` или `action<Action>()`. Така че, ако сме на `Product:show` и `id:123`, връзката към `this` също ще предаде този параметър.
+В същото време всички параметри, посочени в сигнатурата на `action<Action>()` или `render<View>()` ако методът `action<Action>()` не са дефинирани, се прехвърлят. Така че, ако се намираме на страниците `Product:show` и `id:123`, връзката към `this` също ще предаде този параметър.
 
 Разбира се, можете да зададете параметрите и директно:
 
@@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 Ако искаме да направим препратка към презентаторите в шаблона на компонента, използваме тага `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">главная страница</a>
+<a href={plink Home:default}>главная страница</a>
 ```
 
 или в кода
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Псевдоними .[#toc-aliases]{data-version:v3.2.2}
+===============================================
+
+Понякога е полезно да зададете лесно запомнящ се псевдоним на двойка презентатор:действие. Например, можете да наречете началната страница `Front:Home:default` просто `home` или `Admin:Dashboard:default` - `admin`.
+
+Псевдонимите се дефинират в [конфигурацията |configuration] под ключа `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+Във връзките те се записват с помощта на символа at, например:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Те се поддържат във всички методи, които работят с връзки, като например `redirect()` и други подобни.
+
+
 Невалидни връзки .[#toc-invalid-links]
 ======================================
 
diff --git a/application/bg/how-it-works.texy b/application/bg/how-it-works.texy
index 4325c76dd5..5ca8332a47 100644
--- a/application/bg/how-it-works.texy
+++ b/application/bg/how-it-works.texy
@@ -22,18 +22,18 @@
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← каталог с приложением
-│   ├── <b>Presenters/</b>           ← классы презентеров
-│   │   ├── <b>HomePresenter.php</b>  ← Класс презентера главной страницы
-│   │   └── <b>templates/</b>        ← директория шаблонов
-│   │       ├── <b>@layout.latte</b> ← шаблон общего макета
-│   │       └── <b>Home/</b>         ← шаблоны презентера главной страницы
-│   │           └── <b>default.latte</b>  ← шаблон действия `default`
-│   ├── <b>Router/</b>               ← конфигурация URL-адресов
+│   ├── <b>Основни/</b>              ← основни необходими класове
+│   │   └── <b>RouterFactory.php</b> ← конфигуриране на URL адреси
+│   ├── <b>UI/</b>                   ← презентатори, шаблони и др.
+│   │   ├── <b>@layout.latte</b>     ← шаблон на споделено оформление
+│   │   └── <b>Home/</b>             ← Директория за водещи
+│   │       ├── <b>HomePresenter.php</b> ← Клас на Home Presenter
+│   │       └── <b>default.latte</b> ← шаблон за действие default
 │   └── <b>Bootstrap.php</b>         ← загрузочный класс Bootstrap
 ├── <b>bin/</b>                      ← скрипты командной строки
 ├── <b>config/</b>                   ← файлы конфигурации
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← журналы ошибок
 ├── <b>temp/</b>                     ← временные файлы, кэш, …
 ├── <b>vendor/</b>                   ← библиотеки, установленные через Composer
@@ -91,7 +91,7 @@ Nette е наставник, който ви напътства да пишет
 
 Приложението започва с искане към т.нар. маршрутизатор да реши на кой от презентаторите да изпрати текущата заявка за обработка. Маршрутизаторът решава чия е отговорността. Той разглежда входния URL адрес `https://example.com/product/123`, който иска продукт `показать` с `id: 123` като действие. Добър навик е да записвате двойките водещ + действие, разделени с двоеточие: `Продукт:показать`.
 
-Следователно маршрутизаторът е преобразувал URL адреса в двойка `Presenter:action` + параметри, в нашия случай `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Router/RouterFactory.php`, и ще го опишем подробно в главата [Маршрутизация |routing].
+Следователно маршрутизаторът е преобразувал URL адреса в двойка `Presenter:action` + параметри, в нашия случай `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Core/RouterFactory.php`, и ще го опишем подробно в главата [Маршрутизация |routing].
 
 Да продължим. Приложението вече знае името на водещия и може да продължи. Чрез създаване на обект `ProductPresenter`, който е кодът на предентера `Product`. По-точно, той иска от контейнера DI да създаде презентатора, тъй като създаването на обекти е негова работа.
 
@@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 След това водещият връща отговор. Това може да бъде HTML страница, изображение, XML документ, файл, изпратен от диска, JSON или пренасочване към друга страница. Важно е да се отбележи, че ако не посочим изрично как да се отговори (какъвто е случаят с `ProductPresenter`), отговорът ще бъде шаблон, показващ HTML страница. Защо? Ами защото в 99% от случаите искаме да покажем шаблон, водещият приема това поведение по подразбиране и иска да улесни работата ни. Това е гледната точка на Нете.
 
-Дори не е необходимо да указваме кой шаблон да се покаже, той сам извежда пътя до него според проста логика. В случая с водещия `Product` и действието `show`, той се опитва да провери дали някой от тези файлове с шаблони съществува спрямо директорията, в която се намира класът `ProductPresenter`:
+Дори не е необходимо да посочваме кой шаблон да се визуализира; рамката сама ще определи пътя. В случая с действието `show` тя просто се опитва да зареди шаблона `show.latte` в директорията с класа `ProductPresenter`. Тя също така се опитва да намери оформлението във файла `@layout.latte` (повече за [търсенето на шаблони |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-След това се показва шаблонът. Задачата на водещия и на цялото приложение вече е изпълнена. Ако шаблонът не съществува, ще бъде върната страница за грешка 404. Можете да прочетете повече за водещите на страницата [Водещи |presenters].
+Впоследствие шаблоните се визуализират. С това задачата на презентатора и на цялото приложение е изпълнена и работата е приключила. Ако шаблонът не съществува, ще бъде върната страница с грешка 404. Можете да прочетете повече за презентаторите на страницата [Презентатори |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 3) маршрутизаторът декодира URL адреса като двойка `Home:default`
 4) обектът е създаден `HomePresenter`
 5) извиква се методът `renderDefault()` (ако съществува)
-6) шаблонът `templates/Home/default.latte` с оформлението `templates/@layout.latte` се визуализира
+6) шаблонът `default.latte` с оформлението `@layout.latte` се визуализира
 
 
 Може би сега ще се сблъскате с много нови концепции, но ние смятаме, че те имат смисъл. Създаването на приложения в Nette е лесно.
diff --git a/application/bg/modules.texy b/application/bg/modules.texy
index 622fd48b2e..b675e91dd1 100644
--- a/application/bg/modules.texy
+++ b/application/bg/modules.texy
@@ -2,29 +2,31 @@
 ******
 
 .[perex]
-В Nette модулите са логическите единици, от които се състои едно приложение. Те включват главни модули, шаблони, евентуално компоненти и класове модели.
+Модулите внасят яснота в приложенията на Nette, като улесняват лесното им разделяне на логически единици.
 
-Един компонент за презентатори и един за шаблони няма да са достатъчни за реални проекти. Натрупването на десетки файлове в една папка е меко казано неорганизирано. Как да излезем от тази ситуация? Просто ги разделяме на поддиректории на диска и на пространства от имена в кода. Точно това правят модулите Nette.
-
-Така че нека забравим за една папка за презентатори и шаблони и вместо това да създадем модули като `Admin` и `Front`.
+Подобно на организирането на файловете в папки на твърдия диск, в Nette можем да разделим презентатори, шаблони и други спомагателни класове на модули. Как работи това на практика? Просто чрез включване на нови поддиректории в структурата. Ето един пример за структура с два модула - Front и Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← директория с модулями
-│   ├── <b>Admin/</b>            ← модуль Admin
-│   │   ├── <b>Presenters/</b>   ← его презентеры
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← модуль Front
-│       └── <b>Presenters/</b>   ← его презентеры
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Тази структура на директориите ще бъде отразена в пространствата за имена на класовете, така че например `DashboardPresenter` ще бъде в пространството `App\Modules\Admin\Presenters`:
+Тази структура на директориите е отразена в пространствата от имена на класовете, така че например `DashboardPresenter` се намира в пространството от имена `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Главното устройство `Dashboard` в модула `Admin` се обозначава в приложението с помощта на запис с двойна точка като `Admin:Dashboard`, а неговото действие `default` се обозначава като `Admin:Dashboard:default`.
-И откъде Nette знае, че `Admin:Dashboard` представлява класа `App\Modules\Admin\Presenters\DashboardPresenter`? Говорим за това, като използваме [картографирането |#Mapping] в конфигурацията.
-Така че дадената структура не е фиксирана и можете да я променяте по свое усмотрение.
+В приложението се позоваваме на презентатора `Dashboard` в рамките на модула `Admin`, като използваме запис с двоеточие като `Admin:Dashboard`. За неговото действие `default` го наричаме `Admin:Dashboard:default`.
+
+Представената структура не е твърда; в конфигурацията можете [напълно |#mapping] да [я адаптирате към вашите нужди |#mapping]. .[tip]
 
-Модулите, разбира се, могат да съдържат всички други части, освен презентатори и шаблони, като компоненти, класове модели и др.
+Модулите могат да включват всички други файлове, като компоненти и спомагателни класове, в допълнение към презентаторите и шаблоните. Ако обмисляте къде да ги поставите, помислете за използването на папка `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Вложени модули .[#toc-nested-modules]
 -------------------------------------
 
-Модулите не трябва да образуват само плоска структура, можете да създавате и подмодули, например:
+Модулите могат да имат няколко нива на влагане, подобно на структурата на директориите на диска:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← директория с модулями
-│   ├── <b>Blog/</b>             ← модуль Blog
-│   │   ├── <b>Admin/</b>        ← подмодуль Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← подмодуль Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← модуль Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Така модулът `Blog` се разделя на подмодули `Admin` и `Front`. Това отново ще бъде отразено в пространствата от имена, които ще бъдат `App\Modules\Blog\Admin\Presenters` и т.н. Главният модул `Dashboard` в рамките на подмодула се нарича `Blog:Admin:Dashboard`.
+Модулът `Blog` е разделен на подмодули `Admin` и `Front`. Това е отразено и в пространствата от имена, които след това се появяват като `App\UI\Blog\Admin` и по подобен начин. За да се позовем на презентатора `Dashboard` в рамките на подмодула `Admin`, го наричаме `Blog:Admin:Dashboard`.
+
+Влагането може да бъде толкова дълбоко, колкото е необходимо, като позволява създаването на подмодули.
 
-Разклоненията могат да бъдат толкова дълбоки, колкото искате, така че можете да създавате подмодули.
+Например, ако в администрацията имате много презентатори, свързани с управлението на поръчки, като `OrderDetail`, `OrderEdit`, `OrderDispatch` и т.н., може да създадете модул `Order`, в който ще бъдат организирани презентатори като `Detail`, `Edit`, `Dispatch` и други.
 
 
 Създаване на връзки .[#toc-creating-links]
@@ -102,47 +118,66 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 Картографиране .[#toc-mapping]
 ------------------------------
 
-Определя правилата, по които името на класа се извежда от главното име. Записваме ги в [конфигурацията |configuration] под ключа `application › mapping`.
+Съпоставянето определя правилата за извеждане на името на класа от името на водещия. Тези правила се посочват в [конфигурацията |configuration] под ключа `application › mapping`.
 
-Нека започнем с пример, при който не се използват модули. Искаме само главните класове да имат пространството от имена `App\Presenters`. Това означава, че искаме главното име, например `Home`, да се съпостави с класа `App\Presenters\HomePresenter`. Това може да се постигне със следната конфигурация:
+Структурите на директориите, споменати по-рано на тази страница, се основават на следното съпоставяне:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Името на водещия се заменя със звездичка и резултатът е името на класа. Лесно!
+Как работи картографирането? За по-добро разбиране нека първо си представим приложение без модули. Искаме класовете на презентаторите да попадат в пространството от имена `App\UI`, така че презентаторът `Home` да се съпостави с класа `App\UI\HomePresenter`. Това може да се постигне с тази конфигурация:
 
-Ако разделим презентаторите на модули, можем да използваме различни карти за всеки модул:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Това съпоставяне се извършва чрез замяна на звездичката в маската `App\UI\*Presenter` с името на презентатора `Home`, в резултат на което се получава крайното име на класа `App\UI\HomePresenter`. Просто!
+
+Въпреки това, както можете да видите в примерите в тази и други глави, ние поставяме класовете на водещите в едноименни поддиректории, например водещият `Home` е картографиран към клас `App\UI\Home\HomePresenter`. Това се постига чрез удвояване на звездичката (изисква Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Сега нека преминем към картографиране на презентатори в модули. Можем да дефинираме специфични съпоставки за всеки модул:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Сега водещият `Front:Home` е определен от класа `App\Modules\Front\HomePresenter`, а презентер `Admin:Dashboard` - `App\AdminModule\DashboardPresenter`.
+Според тази конфигурация презентаторът `Front:Home` се съотнася към класа `App\UI\Front\Home\HomePresenter`, а презентаторът `Api:OAuth` се съотнася към класа `App\Api\OAuthPresenter`.
 
-Би било по-удобно да се създаде общо правило (звездичка), което да замени първите две правила, и да се добави допълнителна звездичка само за модула:
+Тъй като модулите `Front` и `Admin` имат сходен подход на картографиране и вероятно има повече такива модули, е възможно да се създаде общо правило, което да ги замени. Към маската на класа се добавя нова звездичка за модула:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Но какво става, ако използваме няколко вложени модула и имаме например главен модул `Admin:User:Edit`? В този случай сегментът със звездичка, представляващ модула за всяко ниво, просто ще се повтори и резултатът ще бъде класът `App\Modules\Admin\User\Presenters\EditPresenter`.
+За вложени модули на няколко нива, като например водещия `Admin:User:Edit`, сегментът със звездичка се повтаря за всяко ниво, в резултат на което се получава клас `App\UI\Admin\User\Edit\EditPresenter`.
 
-Алтернативен начин за записване е използването на масив от три сегмента вместо низ. Този запис е еквивалентен на предишния:
+Алтернативен запис е да се използва масив, съставен от три сегмента, вместо низ. Този запис е еквивалентен на предишния:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Стойността по подразбиране е `*: *Module\*Presenter`.
+Ако имаме само едно правило в конфигурацията, общото, можем да го напишем накратко:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/bg/presenters.texy b/application/bg/presenters.texy
index 53606e891f..bf2aeb04fc 100644
--- a/application/bg/presenters.texy
+++ b/application/bg/presenters.texy
@@ -60,7 +60,7 @@ class ArticlePresenter extends Nette\Application\UI\Presenter
 
 Важното е, че `action<Action>()` се извиква преди `render<View>()`, така че в него можем евентуално да променим следващия жизнен цикъл, т.е. да променим шаблона за визуализиране и метода `render<View>()`която ще бъде извикана с помощта на `setView('otherView')`.
 
-Параметрите от заявката се предават на метода. Възможно и препоръчително е да се посочат типове за параметрите, например `actionShow(int $id, string $slug = null)` - ако параметърът `id` липсва или ако не е цяло число, презентаторът ще върне [грешка 404 |#Error-404-etc] и ще прекрати операцията.
+Параметрите от заявката се предават на метода. Възможно и препоръчително е да се посочат типове за параметрите, например `actionShow(int $id, ?string $slug = null)` - ако параметърът `id` липсва или ако не е цяло число, презентаторът ще върне [грешка 404 |#Error-404-etc] и ще прекрати операцията.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */);
 Грешка 404 и т.н. .[#toc-error-404-etc]
 =======================================
 
-Когато не можем да изпълним дадена заявка, защото например статията, която искаме да покажем, не съществува в базата данни, ще хвърлим грешка 404, като използваме метода `error(string $message = null, int $httpCode = 404)`, който представлява HTTP грешка 404:
+Когато не можем да изпълним дадена заявка, защото например статията, която искаме да покажем, не съществува в базата данни, ще хвърлим грешка 404, като използваме метода `error(?string $message = null, int $httpCode = 404)`, който представлява HTTP грешка 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Параметри на заявката .[#toc-request-parameters]
+================================================
+
+Презентаторът, както и всеки компонент, получава своите параметри от HTTP заявката. Стойностите им могат да бъдат извлечени с помощта на метода `getParameter($name)` или `getParameters()`. Стойностите са низове или масиви от низове, по същество сурови данни, получени директно от URL адреса.
+
+За по-голямо удобство препоръчваме да направите параметрите достъпни чрез свойства. Просто ги анотирайте с `#[Parameter]` атрибут:
+
+```php
+use Nette\Application\Attributes\Parameter;  // този ред е важен
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // трябва да е публичен
+}
+```
+
+За свойствата предлагаме да посочите типа данни (например `string`). След това Nette автоматично ще определи стойността въз основа на него. Стойностите на параметрите също могат да бъдат [валидирани |#Validation of Parameters].
+
+Когато създавате връзка, можете директно да зададете стойност за параметрите:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Постоянни параметри .[#toc-persistent-parameters]
 =================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Ако `$this->lang` има стойност като `'en'`, то връзките, създадени с помощта на `link()` или `n:href`, ще съдържат и параметъра `lang=en`. И когато върху връзката се щракне, тя отново ще бъде `$this->lang = 'en'`.
 
-За свойствата препоръчваме да включите типа данни (например `string`), а също така можете да включите стойност по подразбиране. Стойностите на параметрите могат да бъдат [валидирани |#Validation of Persistent Parameters].
+За свойствата препоръчваме да включите типа на данните (например `string`), като можете да включите и стойност по подразбиране. Стойностите на параметрите могат да бъдат [валидирани |#Validation of Parameters].
 
 Постоянните параметри се предават между всички действия на даден презентатор по подразбиране. За да ги предадете между няколко водещи, трябва да ги дефинирате или:
 
@@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Това, което показахме досега в тази глава, вероятно ще бъде достатъчно. Следващите редове са за тези, които се интересуват от презентаторите обстойно и искат да знаят всичко.
 
 
-Изисквания и параметри .[#toc-requirement-and-parameters]
----------------------------------------------------------
+Утвърждаване на параметрите .[#toc-validation-of-parameters]
+------------------------------------------------------------
 
-Заявката, която се обработва от водещия, е обектът [api:Nette\Application\Request] и се връща от метода на водещия `getRequest()`. Тя включва масив от параметри и всеки от тях принадлежи или на някой от компонентите, или директно на водещия (който всъщност също е компонент, макар и специален). Затова Nette преразпределя параметрите и преминава между отделните компоненти (и водещия), като извиква метода `loadState(array $params)`. Параметрите могат да бъдат получени чрез метода `getParameters(): array`, а поотделно чрез `getParameter($name)`. Стойностите на параметрите са низове или масиви от низове, те по същество са необработени данни, получени директно от URL адреса.
+Стойностите на [параметрите на заявката |#request parameters] и [постоянните параметри, |#persistent parameters] получени от URL адреси, се записват в свойствата чрез метода `loadState()`. Той също така проверява дали типът данни, посочен в свойството, съвпада, в противен случай ще отговори с грешка 404 и страницата няма да бъде показана.
 
-
-Утвърждаване на постоянни параметри .[#toc-validation-of-persistent-parameters]
--------------------------------------------------------------------------------
-
-Стойностите на [постоянните параметри, |#persistent parameters] получени от URL адреси, се записват в свойствата чрез метода `loadState()`. Той също така проверява дали типът данни, посочен в свойството, съвпада, в противен случай ще отговори с грешка 404 и страницата няма да бъде показана.
-
-Никога не се доверявайте сляпо на постоянните параметри, тъй като те лесно могат да бъдат пренаписани от потребителя в URL адреса. Например, така проверяваме дали `$this->lang` е сред поддържаните езици. Добър начин да направите това е да пренастроите метода `loadState()`, споменат по-горе:
+Никога не се доверявайте сляпо на параметрите, тъй като те лесно могат да бъдат пренаписани от потребителя в URL адреса. Например, така проверяваме дали `$this->lang` е сред поддържаните езици. Добър начин да направите това е да презапишете метода `loadState()`, споменат по-горе:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Запазване и възстановяване на заявка .[#toc-save-and-restore-the-request]
 -------------------------------------------------------------------------
 
-Можете да запазите текущата заявка в сесия или да я възстановите от сесия и да позволите на водещия да я изпълни отново. Това е полезно, например когато потребителят попълни формуляр и срокът му на влизане изтече. За да избегнем загубата на данни, преди да пренасочим към страницата за регистрация, запазваме текущата заявка в сесията с функцията `$reqId = $this->storeRequest()`, която връща идентификатора като кратък низ и го предава като параметър на водещия за регистрация.
+Заявката, която се обработва от водещия, е обект [api:Nette\Application\Request] и се връща от метода на водещия `getRequest()`.
+
+Можете да запазите текущата заявка в сесия или да я възстановите от сесия и да позволите на водещия да я изпълни отново. Това е полезно, например, когато потребител попълни формуляр и срокът на неговото влизане в системата изтече. За да не загубим данни, преди да пренасочим към страницата за вписване, запазваме текущата заявка в сесия с помощта на `$reqId = $this->storeRequest()`, която връща идентификатор под формата на кратък низ и го предава като параметър на презентатора за вписване.
 
 След като влезем в системата, извикваме метода `$this->restoreRequest($reqId)`, който извлича заявката от сесията и я препраща към нея. Методът проверява дали заявката е създадена от същия потребител, който в момента е влязъл в системата. Ако е влязъл друг потребител или ключът е невалиден, не се прави нищо и програмата продължава.
 
@@ -362,7 +384,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Можете също така да извикате канонизацията ръчно с метода `canonicalize()`, който, както и методът `link()`, приема като аргументи водещия, действията и параметрите. Тя създава връзка и я сравнява с текущия URL адрес. Ако те са различни, се пренасочва към генерираната връзка.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// пренасочва, ако $slug е различен от $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Ограничаване на достъпа с помощта на `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+----------------------------------------------------------------------------------------------------------------
+
+В `#[Requires]` предоставя разширени опции за ограничаване на достъпа до презентаторите и техните методи. Той може да се използва за определяне на HTTP методи, изискване на AJAX заявки, ограничаване на достъпа до същия произход и ограничаване на достъпа само до препращане. Атрибутът може да се прилага към класове на презентатори, както и към отделни методи, като например `action<Action>()`, `render<View>()`, `handle<Signal>()`, и `createComponent<Name>()`.
+
+Можете да зададете тези ограничения:
+- на HTTP методите: `#[Requires(methods: ['GET', 'POST'])]`
+- изискващи AJAX заявка: `#[Requires(ajax: true)]`
+- достъп само от един и същ произход: `#[Requires(sameOrigin: true)]`
+- достъп само чрез препращане: `#[Requires(forward: true)]`
+- ограничения за конкретни действия: `#[Requires(actions: 'default')]`
+
+За подробности вижте [Как да използвате Requires атрибут |best-practices:attribute-requires].
+
+
+Проверка на метода HTTP .[#toc-http-method-check]
+-------------------------------------------------
+
+В Nette презентаторите автоматично проверяват HTTP метода на всяка входяща заявка главно от съображения за сигурност. По подразбиране са разрешени методите `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Ако искате да разрешите допълнителни методи, като например `OPTIONS`, можете да използвате `#[Requires]` атрибут (от Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Във версия 3.1 проверката се извършва в `checkHttpMethod()`, който проверява дали методът, посочен в заявката, е включен в масива `$presenter->allowedMethods`. Добавете метод по следния начин:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Изключително важно е да се подчертае, че ако разрешите метода `OPTIONS`, трябва също така да го обработвате правилно в рамките на вашия презентатор. Този метод често се използва като така наречената preflight заявка, която браузърите автоматично изпращат преди действителната заявка, когато е необходимо да се определи дали заявката е разрешена от гледна точка на политиката CORS (Cross-Origin Resource Sharing). Ако разрешите този метод, но не приложите подходящ отговор, това може да доведе до несъответствия и потенциални проблеми със сигурността.
+
+
 Допълнително четене .[#toc-further-reading]
 ===========================================
 
diff --git a/application/bg/routing.texy b/application/bg/routing.texy
index 300a7755e2..26abc2fb5d 100644
--- a/application/bg/routing.texy
+++ b/application/bg/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Разширена нотация .[#toc-advanced-notation]
 -------------------------------------------
 
-Вторият параметър на маршрута, който често записваме под формата на `Presenter:action`, е съкращение, което можем да запишем и като поле, в което директно посочваме стойностите (по подразбиране) на отделните параметри:
+Целта на маршрута, обикновено записана под формата на `Presenter:action`, може да бъде изразена и с помощта на масив, който определя отделните параметри и техните стойности по подразбиране:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Или можем да използваме тази форма, като отбележим пренаписването на израза за регулярна проверка:
+За по-подробна спецификация може да се използва още по-разширена форма, в която освен стойностите по подразбиране могат да се задават и други свойства на параметъра, например регулярен израз за валидиране (вж. параметъра `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Тези по-подробни формати са полезни за добавяне на повече метаданни.
+Важно е да се отбележи, че ако параметрите, дефинирани в масива, не са включени в маската на пътя, техните стойности не могат да бъдат променени, дори и чрез използване на параметри на заявката, зададени след въпросителен знак в URL адреса.
 
 
 Филтри и преводи .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Интеграция .[#toc-integration]
 ==============================
 
-За да свържем маршрутизатора си с приложението, трябва да информираме за това контейнера DI. Най-лесният начин е да се подготви фабрика, която ще създаде обект маршрутизатор, и да се каже на конфигурацията на контейнера да го използва. Да предположим, че напишем метод за това, `App\Router\RouterFactory::createRouter()`:
+За да свържем маршрутизатора си с приложението, трябва да информираме за това контейнера DI. Най-лесният начин е да се подготви фабрика, която ще създаде обект маршрутизатор, и да се каже на конфигурацията на контейнера да го използва. Да предположим, че напишем метод за това, `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ class RouterFactory
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Всички зависимости, като например връзки към бази данни и т.н., се предават на метода на фабриката като параметри, като се използва [автоматично свързване |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ $router->addRoute(/* ... */);
 Затова отново ще добавим метод, който ще създаде например маршрутизатор:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Или ще създадем обектите директно:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/bg/templates.texy b/application/bg/templates.texy
index 850d3e2ecd..0be4f81857 100644
--- a/application/bg/templates.texy
+++ b/application/bg/templates.texy
@@ -34,35 +34,81 @@ Nette използва системата за шаблони [Latte |latte:]. L
 Той дефинира блок `content`, който се вмъква вместо `{include content}` в оформлението, и замества блока `title`, който презаписва `{block title}` в оформлението. Опитайте се да си представите резултата.
 
 
-Търсене на шаблони .[#toc-search-for-templates]
------------------------------------------------
+Търсене на шаблони .[#toc-template-lookup]
+------------------------------------------
+
+В презентаторите не е необходимо да посочвате кой шаблон трябва да бъде визуализиран; рамката автоматично ще определи пътя, което ще ви улесни при кодирането.
+
+Ако използвате структура от директории, в която всеки презентатор има своя собствена директория, просто поставете шаблона в тази директория под името на действието (т.е. изглед). Например, за действието `default` използвайте шаблона `default.latte`:
 
-Пътят към шаблоните се определя от главния модул с помощта на проста логика. Той ще се опита да провери дали има някой от тези файлове, разположен спрямо главната директория на класа, където `<Presenter>` е името на текущия главен модул, а `<view>` е името на текущото събитие:
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Ако използвате структура, в която презентаторите са заедно в една директория, а шаблоните - в папка `templates`, запишете я или във файл `<Presenter>.<view>.latte` или `<Presenter>/<view>.latte`:
 
-Ако шаблонът не бъде намерен, ще се опита да търси в директорията `templates` едно ниво по-нагоре, т.е. на същото ниво като директорията с класа на водещия.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
 
-Ако шаблонът не бъде намерен и там, отговорът ще бъде [грешка 404 |presenters#Error 404 etc.].
+Директорията `templates` може да бъде поставена и едно ниво по-нагоре, на същото ниво като директорията с класовете на водещите.
 
-Можете също така да промените изгледа с помощта на `$this->setView('jineView')`. Или вместо да търсите директно, посочете името на файла с шаблона, като използвате `$this->template->setFile('/path/to/template.latte')`.
+Ако шаблонът не бъде намерен, презентаторът отговаря с [грешка 404 - страница не е намерена |presenters#Error 404 etc].
+
+Можете да промените изгледа, като използвате `$this->setView('anotherView')`. Възможно е също така директно да посочите файла с шаблона с помощта на `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Файловете, които се търсят за шаблони, могат да се променят чрез наслагване на метода [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], който връща масив от възможни имена на файлове.
+Файловете, в които се търсят шаблони, могат да се променят чрез надграждане на метода [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], който връща масив от възможни имена на файлове.
+
+
+Търсене на шаблони за оформление .[#toc-layout-template-lookup]
+---------------------------------------------------------------
+
+Nette също така автоматично търси файла с оформлението.
+
+Ако използвате структура на директориите, в която всеки водещ има своя собствена директория, поставете макета или в папката с водещия, ако е специфичен само за него, или на по-високо ниво, ако е общ за няколко водещи:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Ако използвате структура, в която презентаторите са групирани в една директория, а шаблоните са в папка `templates`, макетът ще се очаква на следните места:
 
-В тези файлове се очаква оформление:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` Разположение, общо за няколко високоговорителя
+Ако презентаторът е в [модул |modules], той ще търси и по-нагоре в дървото на директориите според вложеността на модула.
 
-Къде: `<Presenter>` е името на текущия водещ, а `<layout>` е името на оформлението, което по подразбиране е `'layout'`. Името може да бъде променено с помощта на `$this->setLayout('jinyLayout')`, така че ще бъдат изпробвани файлове `@jinyLayout.latte`.
+Името на макета може да бъде променено с помощта на `$this->setLayout('layoutAdmin')` и тогава то ще бъде очаквано във файла `@layoutAdmin.latte`. Можете също така директно да посочите файла с шаблона на оформлението, като използвате `$this->setLayout('/path/to/template.latte')`.
 
-Можете също така директно да посочите името на файла на шаблона за оформление, като използвате `$this->setLayout('/path/to/template.latte')`. Използването на `$this->setLayout(false)` деактивира проследяването на оформлението.
+Използването на `$this->setLayout(false)` или на тага `{layout none}` вътре в шаблона деактивира търсенето на оформление.
 
 .[note]
-Файловете, в които се търсят шаблоните за оформление, могат да се променят чрез наслагване на метода [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], който връща масив от възможни имена на файлове.
+Файловете, в които се търсят шаблони за оформление, могат да бъдат променяни чрез надграждане на метода [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], който връща масив от възможни имена на файлове.
 
 
 Променливи в шаблона .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
 Можете също така да си позволите лукса да шепнете в шаблоните, просто инсталирайте плъгина Latte в PhpStorm и поставете името на класа в началото на шаблона, за повече информация вижте статията "Latte: как да въведем системата":https://blog.nette.org/bg/latte-kak-da-izpolzvame-sistemata-ot-tipove:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Версия 3 на Latte предлага по-усъвършенстван начин за създаване на [разширение за |latte:creating-extension] всеки уеб проект. Ето кратък пример за такъв клас:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ protected function beforeRender(): void
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 След това транслаторът може да се използва например като филтър `|translate`, като на метода `translate()` се предават допълнителни параметри (вж. `foo, bar`):
diff --git a/application/cs/@home.texy b/application/cs/@home.texy
index 833406fcbd..57c24db0a2 100644
--- a/application/cs/@home.texy
+++ b/application/cs/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | verze     | kompatibilní s PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 – 8.2
-| Nette Application 3.1 | PHP 7.2 – 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 – 8.0
 | Nette Application 2.4 | PHP 5.6 – 8.0
 
diff --git a/application/cs/ajax.texy b/application/cs/ajax.texy
index e4d30f762a..327977ea19 100644
--- a/application/cs/ajax.texy
+++ b/application/cs/ajax.texy
@@ -3,10 +3,10 @@ AJAX & snippety
 
 <div class=perex>
 
-Moderní webové aplikace dnes běží napůl na serveru, napůl v prohlížeči. AJAX je tím klíčovým spojovacím prvkem. Jakou podporu nabízí Nette Framework?
-- posílání výřezů šablony (tzv. snippety)
+V éře moderních webových aplikací, kde se často rozkládá funkcionalita mezi serverem a prohlížečem, je AJAX nezbytným spojovacím prvkem. Jaké možnosti nám v této oblasti nabízí Nette Framework?
+- odesílání částí šablony, tzv. snippetů
 - předávání proměnných mezi PHP a JavaScriptem
-- debugování AJAXových aplikací
+- nástroje pro debugování AJAXových požadavků
 
 </div>
 
@@ -14,29 +14,32 @@ Moderní webové aplikace dnes běží napůl na serveru, napůl v prohlížeči
 AJAXový požadavek
 =================
 
-AJAXový požadavek se nijak neliší od klasického požadavku - je zavolán presenter s určitým view a parametry. Je také věcí presenteru, jak bude na něj reagovat: může použít vlastní rutinu, která vrátí nějaký fragment HTML kódu (HTML snippet), XML dokument, JSON objekt nebo kód v JavaScriptu.
+AJAXový požadavek se v zásadě neliší od klasického HTTP požadavku. Zavolá se presenter s určitými parametry. A je na presenteru, jakým způsobem bude na požadavek reagovat - může vrátit data ve formátu JSON, odeslat část HTML kódu, XML dokument, atd.
 
-Na straně serveru lze AJAXový požadavek detekovat metodou služby [zapouzdřující HTTP požadavek |http:request] `$httpRequest->isAjax()` (detekuje podle HTTP hlavičky `X-Requested-With`). Uvnitř presenteru je k dispozici "zkratka" v podobě metody `$this->isAjax()`.
+Na straně prohlížeče inicializujeme AJAXový požadavek pomocí funkce `fetch()`:
 
-Pro odesílání dat prohlížeči ve formátu JSON lze využít předpřipravený objekt `payload`:
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// zpracování odpovědi
+});
 ```
 
-Pokud potřebujete plnou kontrolu nad odeslaným JSONem, použijte metodu `sendJson` v presenteru. Tím ihned ukončíte činnost presenteru a obejdete se i bez šablony:
+Na straně serveru rozpoznáme AJAXový požadavek metodou `$httpRequest->isAjax()` služby [zapouzdřující HTTP požadavek |http:request]. K detekci používá HTTP hlavičku `X-Requested-With`, proto je důležité ji odesílat. V rámci presenteru lze použít metodu `$this->isAjax()`.
+
+Chcete-li odeslat data ve formátu JSON, použijte metodu [`sendJson()` |presenters#Odeslání odpovědi]. Metoda rovněž ukončí činnost presenteru.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Když chceme odeslat HTML, můžeme jednak zvolit speciální šablonu pro AJAX:
+Máte-li v plánu odpovědět pomocí speciální šablony určené pro AJAX, můžete to udělat následovně:
 
 ```php
 public function handleClick($param): void
@@ -49,10 +52,20 @@ public function handleClick($param): void
 ```
 
 
+Snippety
+========
+
+Nejsilnější prostředek, který nabízí Nette pro propojení serveru s klientem, představují snippety. Díky nim můžete z obyčejné aplikace udělat AJAXovou jen s minimálním úsilím a několika řádky kódu. Jak to celé funguje demonstruje příklad Fifteen, jehož kód najdete na [GitHubu |https://github.com/nette-examples/fifteen].
+
+Snippety, nebo-li výstřižky, umožnují aktualizovat jen části stránky, místo toho, aby se celá stránka znovunačítala. Jednak je to rychlejší a efektivnější, ale poskytuje to také komfortnější uživatelský zážitek. Snippety vám mohou připomínat Hotwire pro Ruby on Rails nebo Symfony UX Turbo. Zajímavé je, že Nette představilo snippety již o 14 let dříve.
+
+Jak snippety fungují? Při prvním načtení stránky (ne-AJAXovém požadavku) se načte celá stránka včetně všech snippetů. Když uživatel interaguje se stránkou (např. klikne na tlačítko, odešle formulář, atd.), místo načtení celé stránky se vyvolá AJAXový požadavek. Kód v presenteru provede akci a rozhodne, které snippety je třeba aktualizovat. Nette tyto snippety vykreslí a odešle ve formě pole ve formátu JSON. Obslužný kód v prohlížeči získané snippety vloží zpět do stránky. Přenáší se tedy jen kód změněných snippetů, což šetří šířku pásma a zrychluje načítání oproti přenášení obsahu celé stránky.
+
+
 Naja
-====
+----
 
-K obsluze AJAXových požadavků na straně prohlížeče slouží [knihovna Naja |https://naja.js.org]. Tu [nainstalujte |https://naja.js.org/#/guide/01-install-setup-naja] jako node.js balíček (pro použití s aplikacemi Webpack, Rollup, Vite, Parcel a dalšími):
+K obsluze snippetů na straně prohlížeče slouží [knihovna Naja |https://naja.js.org]. Tu [nainstalujte |https://naja.js.org/#/guide/01-install-setup-naja] jako node.js balíček (pro použití s aplikacemi Webpack, Rollup, Vite, Parcel a dalšími):
 
 ```shell
 npm install naja
@@ -64,6 +77,12 @@ npm install naja
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
+Nejprve je potřeba knihovnu [inicializovat |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization]:
+
+```js
+naja.initialize();
+```
+
 Aby se z obyčejného odkazu (signálu) nebo odeslání formuláře vytvořil AJAXový požadavek, stačí označit příslušný odkaz, formulář nebo tlačítko třídou `ajax`:
 
 ```html
@@ -74,64 +93,39 @@ Aby se z obyčejného odkazu (signálu) nebo odeslání formuláře vytvořil AJ
 </form>
 
 nebo
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippety
-========
-
-Daleko silnější nástroj představuje vestavěná podpora AJAXových snippetů. Díky ní lze udělat z obyčejné aplikace AJAXovou prakticky několika řádky kódu. Jak to celé funguje, demonstruje příklad Fifteen, jehož kód najdete na [GitHubu |https://github.com/nette-examples/fifteen].
-
-Snippety fungují tak, že při prvotním (tedy neAJAXovém) požadavku se přenese celá stránka a poté se při každém již AJAXovém [subrequestu |components#Signál] (= požadavku na stejný presenter a view) přenáší pouze kód změněných částí ve zmíněném úložišti `payload`. K tomu slouží dva mechanismy: invalidace a renderování snippetů.
+Překreslení snippetů
+--------------------
 
-Snippety vám mohou připomínat Hotwire pro Ruby on Rails nebo Symfony UX Turbo, nicméně Nette s nimi přišlo už o čtrnáct let dříve.
-
-
-Invalidace snippetů
-===================
-
-Každý objekt třídy [Control |components] (což je i samotný Presenter) si umí zapamatovat, jestli při signálu došlo ke změnám, které si vyžadují jej překreslit. K tomu slouží dvojice metod `redrawControl()` a  `isControlInvalid()`. Příklad:
+Každý objekt třídy [Control |components] (včetně samotného Presenteru) eviduje, zda došlo ke změnám vyžadujícím jeho překreslení. K tomu slouží metoda `redrawControl()`:
 
 ```php
 public function handleLogin(string $user): void
 {
-	// po přihlášení uživatele se musí objekt překreslit
+	// po přihlášení je potřeba překreslit relevantní část
 	$this->redrawControl();
 	// ...
 }
 ```
-Nette však nabízí ještě jemnější rozlišení, než na úrovni komponent. Uvedené metody mohou totiž jako argument přijímat název tzv. "snippetu", nebo-li výstřižku. Lze tedy invalidovat (rozuměj: vynutit překreslení) na úrovni těchto snippetů (každý objekt může mít libovolné množství snippetů). Pokud se invaliduje celá komponenta, tak se i každý snippet překreslí. Komponenta je "invalidní" i tehdy, pokud je invalidní některá její subkomponenta.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // invaliduje snippet 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, alespoň jeden snippet je invalid
+Nette umožňuje ještě jemnější kontrolu toho, co se má překreslit. Uvedená metoda totiž může jako argument přijímat název snippetu. Lze tedy invalidovat (rozuměj: vynutit překreslení) na úrovni částí šablony. Pokud se invaliduje celá komponenta, tak se překreslí i každý její snippet:
 
-$this->redrawControl(); // invaliduje celou komponentu, každý snippet
-$this->isControlInvalid('footer'); // -> true
+```php
+// invaliduje snippet 'header'
+$this->redrawControl('header');
 ```
 
-Komponenta, která přijímá signál, je automaticky označena za invalidní.
-
-Díky invalidaci snippetů přesně víme, které části kterých prvků bude potřeba překreslit.
-
-
-Tagy `{snippet} … {/snippet}` .{toc: Tag snippet}
-=================================================
 
-Vykreslování stránky probíhá velmi podobně jako při běžném požadavku: načtou se stejné šablony atd. Podstatné však je vynechání částí, které se nemají dostat na výstup; ostatní části se přiřadí k identifikátoru a pošlou se uživateli ve formátu srozumitelném pro obslužný program JavaScriptu.
+Snippety v Latte
+----------------
 
-
-Syntaxe
--------
-
-Pokud se uvnitř šablony nachází control nebo snippet, musíme jej obalit párovou značkou `{snippet} ... {/snippet}` - ty totiž zajistí, že se vykreslený snippet vystřihne a pošle do prohlížeče. Také jej obalí pomocnou značkou `<div>` s vygenerovaným `id`. V uvedeném příkladě je snippet pojmenován jako `header` a může představovat i například šablonu controlu:
+Používání snippetů v Latte je nesmírně snadné. Chcete-li definovat část šablony jako snippet, obalte ji jednoduše značkami `{snippet}` a `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Pokud se uvnitř šablony nachází control nebo snippet, musíme jej obalit pá
 {/snippet}
 ```
 
-Snippetu jiného typu než `<div>` nebo snippetu s dalšími HTML atributy docílíme použitím atributové varianty:
+Snippet vytvoří v HTML stránce element `<div>` se speciálním vygenerovaným `id`. Při překreslení snippetu se pak aktulizuje obsah tohoto elementu. Proto je nutné, aby při prvotním vykreslení stránky se vykreslily také všechny snippety, byť mohou být třeba na začátku prázdné.
+
+Můžete vytvořit i snippet s jiným elementem než `<div>` pomocí n:attributu:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Snippetu jiného typu než `<div>` nebo snippetu s dalšími HTML atributy docí
 ```
 
 
-Dynamické snippety
-==================
+Oblasti snippetů
+----------------
 
-Nette také umožňuje používání snippetů, jejichž název se vytvoří až za běhu - tj. dynamicky. Hodí se to pro různé seznamy, kde při změně jednoho řádku nechceme přenášet AJAXem celý seznam, ale stačí onen samotný řádek. Příklad:
+Názvy snippetů mohou být také výrazy:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Zde máme statický snippet `itemsContainer`, obsahující několik dynamických snippetů `item-0`, `item-1` atd.
+Takto nám vznikne několik snippetů `item-0`, `item-1` atd. Pokud bychom přímo invalidovali dynamický snippet (například `item-1`), nepřekreslilo by se nic. Důvod je ten, že snippety opravdu fungují jako výstřižky a vykreslují se jen přímo ony samotné. Jenže v šabloně fakticky žádný snippet pojmenovaný `item-1` není. Ten vznikne až vykonáváním kódu v okolí snippetu, tedy cyklu foreach. Označíme proto část šablony, která se má vykonat pomocí značky `{snippetArea}`:
 
-Dynamické snippety nelze invalidovat přímo (invalidace `item-1` neudělá vůbec nic), musíte invalidovat jim nadřazený statický snippet (zde snippet `itemsContainer`). Potom dojde k tomu, že se provede celý kód toho kontejneru, ale prohlížeči se pošlou jenom jeho sub-snippety. Pokud chcete, aby prohlížeč dostal pouze jediný z nich, musíte upravit vstup toho kontejneru tak, aby ostatní negeneroval.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-V příkladu výše zkrátka musíte zajistit, aby při ajaxovém požadavku byla v proměnné `$list` pouze jedna položka a tedy aby ten cyklus `foreach` naplnil pouze jeden dynamický snippet:
+A necháme překreslit jak samotný snippet, tak i celou nadřazenou oblast:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * Tato metoda vrací data pro seznam.
-	 * Obvykle se jedná pouze o vyžádání dat z modelu.
-	 * Pro účely tohoto příkladu jsou data zadána natvrdo.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'První',
-			'Druhý',
-			'Třetí',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Zároveň je vhodné zajistit, aby pole `$items` obsahovalo jen ty položky, které se mají překreslit.
 
-Snippety v includované šabloně
-==============================
-
-Může se stát, že máme snippet v šabloně, kterou teprve includujeme do jiné šablony. V takovém případě je nutné vkládání této šablony obalit značkami `snippetArea`, které pak invalidujeme spolu se samotnym snippetem.
-
-Tagy `snippetArea` zaručí, že se daný kód, který vkládá šablonu, provede, do prohlížeče se však odešle pouze snippet v includované šabloně.
+Pokud do šablony vkládáme pomocí značky `{include}` jinou šablonu, která obsahuje snippety, je nutné vložení šablony opět zahrnout do `snippetArea` a tu invalidovat společně se snippetem:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Tento přístup se nechá použít i v kombinaci s dynamickými snippety.
 
+Snippety v komponentách
+-----------------------
 
-Přidávání a mazání
-==================
-
-Pokud přidáte novou položku a invalidujete `itemsContainer`, pak vám AJAXový požadavek sice vrátí i nový snippet, ale obslužný javascript ho neumí nikam přiřadit. Na stránce totiž zatím není žádný HTML prvek s takovým ID.
-
-V takovém případě je nejjednodušší celý ten seznam obalit ještě jedním snippetem a invalidovat to celé:
+Snippety můžete vytvářet i v [komponentách|components] a Nette je bude automaticky překreslovat. Ale platí tu určité omezení: pro překreslení snippetů volá metodu `render()` bez parametrů. Tedy nebude fungovat předávání parametrů v šabloně:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+nebude fungovat:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Posílání uživatelských dat
+--------------------------
+
+Společně se snippety můžete klientovi poslat libovolná další data. Stačí je zapsat do objektu `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	// ...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Totéž platí i pro mazání. Sice by se dal nějak poslat prázdný snippet, jenže v praxi jsou většinou seznamy stránkované a řešit úsporněji smazání jednoho plus případné načtení jiného (který se předtím nevešel) by bylo příliš složité.
-
 
-Posílání parametrů do komponenty
-================================
+Předávání parametrů
+===================
 
 Pokud komponentě pomocí AJAXového požadavku odesíláme parametry, ať už parametry signálu nebo persistentní parametry, musíme u požadavku uvést jejich globální název, který obsahuje i jméno komponenty. Celý název parametru vrací metoda `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-A handle metoda s odpovídajícími parametry v komponentě.
+A handle metoda s odpovídajícími parametry v komponentě:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/cs/bootstrap.texy b/application/cs/bootstrap.texy
index 55fbbfc0f5..6357fe0d4d 100644
--- a/application/cs/bootstrap.texy
+++ b/application/cs/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Konfigurátor je zodpovědný za nastavení prostředí aplikace a služeb.
+		$this->configurator = new Configurator;
+		// Nastaví adresář pro dočasné soubory generované Nette (např. zkompilované šablony)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette je chytré a vývojový režim se zapíná automaticky,
+		// nebo jej můžete povolit pro konkrétní IP adresu odkomentováním následujícího řádku:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Aktivuje Tracy: ultimátní "švýcarský nůž" pro ladění.
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: automaticky načítá všechny třídy ve zvoleném adresáři
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Načte konfigurační soubory
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php
 =========
 
-Prvotní soubor je v případě webových aplikací `index.php`, který se nachází ve veřejném adresáři `www/`. Ten si nechá od třídy Bootstrap inicializovat prostředí a vrátit `$configurator` a následně vyrobí DI kontejner. Poté z něj získá službu `Application`, kterou spustí webovou aplikaci:
+Prvotní soubor je v případě webových aplikací `index.php`, který se nachází ve veřejném adresáři `www/`. Ten si nechá od třídy Bootstrap inicializovat prostředí a vyrobit DI kontejner. Poté z něj získá službu `Application`, která spustí webovou aplikaci:
 
 ```php
-// inicializace prostředí + získání objektu Configurator
-$configurator = App\Bootstrap::boot();
-// vytvoření DI kontejneru
-$container = $configurator->createContainer();
+$bootstrap = new App\Bootstrap;
+// Inicializace prostředí + vytvoření DI kontejneru
+$container = $bootstrap->bootWebApplication();
 // DI kontejner vytvoří objekt Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// spuštění Nette aplikace
+// Spuštění aplikace Nette a zpracování příchozího požadavku
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Volba režimu se provádí autodetekcí, takže obvykle není potřeba nic konfi
 Pokud chceme vývojářský režim povolit i v dalších případech, například programátorům přistupujícím z konkrétní IP adresy, použijeme `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // lze uvést i pole IP adres
+$this->configurator->setDebugMode('23.75.345.200'); // lze uvést i pole IP adres
 ```
 
 Rozhodně doporučujeme kombinovat IP adresu s cookie. Do cookie `nette-debug` uložíme tajný token, např. `secret1234`, a tímto způsobem aktivujeme vývojářský režim pro programátory přistupující z konkrétní IP adresy a zároveň mající v cookie zmíněný token:
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Vývojářský režim můžeme také vypnout úplně, i pro localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Pozor, hodnota `true` zapne vývojářský režim natvrdo, což se nikdy nesmí stát na produkčním serveru.
@@ -90,7 +115,7 @@ Debugovací nástroj Tracy
 Pro snadné debugování ještě zapneme skvělý nástroj [Tracy |tracy:]. Ve vývojářském režimu chyby vizualizuje a v produkčním režimu chyby loguje do uvedeného adresáře:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Dočasné soubory
 Nette využívá cache pro DI kontejner, RobotLoader, šablony atd. Proto je nutné nastavit cestu k adresáři, kam se bude cache ukládat:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Na Linuxu nebo macOS nastavte adresářům `log/` a `temp/` [práva pro zápis |nette:troubleshooting#Nastavení práv adresářů].
@@ -112,7 +137,7 @@ RobotLoader
 Zpravidla budeme chtít automaticky načítat třídy pomocí [RobotLoaderu |robot-loader:], musíme ho tedy nastartovat a necháme jej načítat třídy z adresáře, kde je umístěný `Bootstrap.php` (tj. `__DIR__`), a všech podadresářů:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Timezone
 Přes konfigurátor můžete nastavit výchozí časovou zónu.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ Ve vývojářském režimu se kontejner automaticky aktualizuje při každé zm
 Konfigurační soubory načteme pomocí `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Pokud chceme přidat více konfiguračních souborů, můžeme funkci `addConfig()` zavolat vícekrát.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Statické parametry
 Parametry používané v konfiguračních souborech můžeme definovat [v sekci `parameters`|dependency-injection:configuration#parametry] a také je předávat (či přepisovat) metodou `addStaticParameters()` (má alias `addParameters()`). Důležité je, že různé hodnoty parametrů způsobí vygenerování dalších DI kontejnerů, tedy dalších tříd.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Dynamické parametry
 Do kontejneru můžeme přidat i dynamické parametry, jejichž různé hodnoty na rozdíl od statických parameterů nezpůsobí generování nových DI kontejnerů.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Jednoduše tak můžeme přidat např. environmentální proměnné, na které se pak lze v konfiguraci odkázat zápisem `%env.variable%`.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ V konfiguračních souborech můžete využít tyto statické parametry:
 - `%wwwDir%` je absolutní cesta k adresáři se vstupním souborem `index.php`
 - `%tempDir%` je absolutní cesta k adresáři pro dočasné soubory
 - `%vendorDir%` je absolutní cesta k adresáři, kam Composer instaluje knihovny
+- `%rootDir%` je absolutní cesta ke kořenovému adresáři projektu
 - `%debugMode%` udává, zda je aplikace v debugovacím režimu
 - `%consoleMode%` udává, zda request přišel přes příkazovou řádku
 
@@ -225,7 +252,7 @@ services:
 A v bootstrapu do kontejneru vložíme objekt:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Odlišné prostředí
 =================
 
-Nebojte se upravit třídu Bootstrap podle svých potřeb. Metodě `boot()` můžete přidat parametry pro rozlišení webových projektů nebo doplnit další metody, například `bootForTests()`, která inicializuje prostředí pro jednotkové testy, `bootForCli()` pro skripty volané z příkazové řádky atd.
+Nebojte se upravit třídu Bootstrap podle svých potřeb. Metodě `bootWebApplication()` můžete přidat parametry pro rozlišení webových projektů. Nebo můžeme doplnit další metody, například `bootTestEnvironment()`, která inicializuje prostředí pro jednotkové testy, `bootConsoleApplication()` pro skripty volané z příkazové řádky atd.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
 {
-	$configurator = self::boot();
 	Tester\Environment::setup(); // inicializace Nette Testeru
-	return $configurator;
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
+{
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/cs/components.texy b/application/cs/components.texy
index c7ca3c65ef..db86af248c 100644
--- a/application/cs/components.texy
+++ b/application/cs/components.texy
@@ -198,7 +198,7 @@ Odkaz, který zavolá signál, vytvoříme obvyklým způsobem, tedy v šabloně
 <a n:href="click! $x, $y">click here</a>
 ```
 
-Signál se vždy volá na aktuálním presenteru a view, tudíž není možné jej vyvolat na jiném presenteru nebo view.
+Signál se vždy volá na aktuálním presenteru a action, není možné jej vyvolat na jiném presenteru nebo jiné action.
 
 Signál tedy způsobí znovunačtení stránky úplně stejně jako při původním požadavku, jen navíc zavolá obslužnou metodu signálu s příslušnými parametry. Pokud metoda neexistuje, vyhodí se výjimka [api:Nette\Application\UI\BadSignalException], která se uživateli zobrazí jako chybová stránka 403 Forbidden.
 
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // a přesměrujeme
 ```
 
 
+Přesměrování po signálu
+=======================
+
+Po zpracování signálu komponenty často následuje přesměrování. Je to podobná situace jako u formulářů - po jejich odeslání také přesměrováváme, aby při obnovení stránky v prohlížeči nedošlo k opětovnému odeslání dat.
+
+```php
+$this->redirect('this') // přesměruje na aktuální presenter a action
+```
+
+Protože komponenta je znovupoužitelný prvek a obvykle by neměla mít přímou vazbu na konkrétní presentery, metody `redirect()` a `link()` automaticky interpretují parametr jako signál komponenty:
+
+```php
+$this->redirect('click') // přesměruje na signál 'click' téže komponenty
+```
+
+Pokud potřebujete přesměrovat na jiný presenter či akci, můžete to udělat prostřednictvím presenteru:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // přesměruje na jiný presenter/action
+```
+
+
 Persistentní parametry
 ======================
 
@@ -347,7 +369,7 @@ services:
 a nakonec ji použijeme v našem presenteru:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Komponenty do hloubky
 Komponenty v Nette Application představují znovupoužitelné součásti webové aplikace, které vkládáme do stránek a kterým se ostatně věnuje celá tato kapitola. Jaké přesně schopnosti taková komponenta má?
 
 1) je vykreslitelná v šabloně
-2) ví, kterou svou část má vykreslit při [AJAXovém požadavku |ajax#invalidace] (snippety)
+2) ví, [kterou svou část|ajax#snippety] má vykreslit při AJAXovém požadavku (snippety)
 3) má schopnost ukládat svůj stav do URL (persistentní parametry)
 4) má schopnost reagovat na uživatelské akce (signály)
 5) vytváří hierarchickou strukturu (kde kořenem je presenter)
@@ -430,7 +452,7 @@ class PaginatingControl extends Control
 }
 ```
 
-Opačný proces, tedy sesbírání hodnot z persistentních properites, má na starosti metoda `saveState()`.
+Opačný proces, tedy sesbírání hodnot z persistentních properties, má na starosti metoda `saveState()`.
 
 
 Signály do hloubky
@@ -444,7 +466,7 @@ Signál může přijímat jakákoliv komponenta, presenter nebo objekt, který i
 
 Mezi hlavní příjemce signálů budou patřit `Presentery` a vizuální komponenty dědící od `Control`. Signál má sloužit jako znamení pro objekt, že má něco udělat – anketa si má započítat hlas od uživatele, blok s novinkami se má rozbalit a zobrazit dvakrát tolik novinek, formulář byl odeslán a má zpracovat data a podobně.
 
-URL pro signál vytváříme pomocí metody [Component::link() |api:Nette\Application\UI\Component::link()]. Jako parametr `$destination` předáme řetězec `{signal}!` a jako `$args` pole argumentů, které chceme signálu předat. Signál se vždy volá na aktuální view s aktuálními parametry, parametry signálu se jen přidají. Navíc se přidává hned na začátku **parametr `?do`, který určuje signál**.
+URL pro signál vytváříme pomocí metody [Component::link() |api:Nette\Application\UI\Component::link()]. Jako parametr `$destination` předáme řetězec `{signal}!` a jako `$args` pole argumentů, které chceme signálu předat. Signál se vždy volá na aktuálním presenteru a action s aktuálními parametry, parametry signálu se jen přidají. Navíc se přidává hned na začátku **parametr `?do`, který určuje signál**.
 
 Jeho formát je buď `{signal}`, nebo `{signalReceiver}-{signal}`. `{signalReceiver}` je název komponenty v presenteru. Proto nemůže být v názvu komponenty pomlčka – používá se k oddělení názvu komponenty a signálu, je ovšem možné takto zanořit několik komponent.
 
diff --git a/application/cs/configuration.texy b/application/cs/configuration.texy
index 6f258ecc63..84954e2e59 100644
--- a/application/cs/configuration.texy
+++ b/application/cs/configuration.texy
@@ -14,10 +14,14 @@ application:
 	debugger: ...           # (bool) výchozí je true
 
 	# bude se při chybě volat error-presenter?
-	catchExceptions: ...    # (bool) výchozí je true v produkčním režimu
+	# má efekt pouze ve vývojářském režimu
+	catchExceptions: ...    # (bool) výchozí je true
 
 	# název error-presenteru
-	errorPresenter: Error   # (string) výchozí je 'Nette:Error'
+	errorPresenter: Error   # (string|array) výchozí je 'Nette:Error'
+
+	# definuje aliasy pro presentery a akce
+	aliases: ...
 
 	# definuje pravidla pro překlad názvu presenteru na třídu
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) výchozí je false
 ```
 
-Protože ve vývojovém režimu se error-presentery standardně nevolají a chybu zobrazí až Tracy, změnou hodnoty `catchExceptions` na `true` můžeme při vývoji ověřit jejich správnou funkčnost.
+Od `nette/application` verze 3.2 lze definovat dvojici error-presenterů:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # pro výjimku Nette\Application\BadRequestException
+		5xx: Error5xx   # pro ostatní výjimky
+```
 
 Volba `silentLinks` určuje, jak se Nette zachová ve vývojářském režimu, když selže generování odkazu (třeba proto, že neexistuje presenter, atd). Výchozí hodnota `false` znamená, že Nette vyhodí `E_USER_WARNING` chybu. Nastavením na `true` dojde k potlačení této chybové hlášky. V produkčním prostředí se `E_USER_WARNING` vyvolá vždy. Toto chování můžeme také ovlivnit nastavením proměnné presenteru [$invalidLinkMode|creating-links#neplatne-odkazy].
 
+[Aliasy zjednodušují odkazování |creating-links#aliasy] na často používané presentery.
+
 [Mapování definuje pravidla |modules#mapování], podle kterých se z názvu presenteru odvodí název třídy.
 
 
@@ -82,6 +95,9 @@ latte:
 	# aktivuje [kontrolu vygenerovaného kódu |latte:develop#Kontrola vygenerovaného kódu]
 	phpLinter: ...       # (string) výchozí je null
 
+	# nastaví locale
+	locale: cs_CZ        # (string) výchozí je null
+
 	# třída objektu $this->template
 	templateClass: App\MyTemplateClass # výchozí je Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Pokud používáte Latte verze 3, můžete přidávat nové [rozšíření |latt
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Pokud používáte Latte verze 2, můžete registrovat nové tagy (makra) buď uvedením jména třídy, nebo referencí na službu. Jako výchozí je zavolána metoda `install()`, ale to lze změnit tím, že uvedeme jméno jiné metody:
diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy
index a21c986098..25a1f8d240 100644
--- a/application/cs/creating-links.texy
+++ b/application/cs/creating-links.texy
@@ -38,7 +38,7 @@ Je možné předávat i pojmenované parametry. Následující odkaz předává
 <a n:href="Product:show $product->id, lang: cs">detail produktu</a>
 ```
 
-Pokud metoda `ProductPresenter::renderShow()` nemá `$lang` ve své signatuře, může si hodnotu parametru zjistit pomocí `$lang = $this->getParameter('lang')`.
+Pokud metoda `ProductPresenter::renderShow()` nemá `$lang` ve své signatuře, může si hodnotu parametru zjistit pomocí `$lang = $this->getParameter('lang')` nebo z [property |presenters#Parametry požadavku].
 
 Pokud jsou parametry uložené v poli, lze je rozvinout operátorem `...` (v Latte 2.x operátorem `(expand)`):
 
@@ -140,7 +140,7 @@ Cíl `this` vytvoří odkaz na aktuální stránku:
 <a n:href="this">refresh</a>
 ```
 
-Zároveň se přenáší i všechny parametry uvedené v signatuře `render<View>()` nebo `action<Action>()` metody. Takže pokud jsme na stránce `Product:show` a `id: 123`, odkaz na `this` předá i tento parameter.
+Zároveň se přenáší i všechny parametry uvedené v signatuře metody `action<Action>()` nebo `render<View>()`, pokud není `action<Action>()` definovaná. Takže pokud jsme na stránce `Product:show` a `id: 123`, odkaz na `this` předá i tento parameter.
 
 Samozřejmě je možné parametry specifikovat přímo:
 
@@ -213,7 +213,7 @@ Protože [komponenty|components] jsou samostatné znovupoužitelné celky, kter
 Pokud bychom chtěli v šabloně komponenty odkazovat na presentery, použijeme k tomu značku `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">úvod</a>
+<a href={plink Home:default}>úvod</a>
 ```
 
 nebo v kódu
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Aliasy .{data-version:v3.2.2}
+=============================
+
+Občas se může hodit přiřadit dvojici Presenter:akce snadno zapamatovatelný alias. Například úvodní stránku `Front:Home:default` pojmenovat jednoduše jako `home` nebo `Admin:Dashboard:default` jako `admin`.
+
+Aliasy se definují v [konfiguraci|configuration] pod klíčem `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+V odkazech se pak zapisují pomocí zavináče, například:
+
+```latte
+<a n:href="@admin">administrace</a>
+```
+
+Podporované jsou i ve všech metodách pracujících s odkazy, jako je `redirect()` a podobně.
+
+
 Neplatné odkazy
 ===============
 
diff --git a/application/cs/how-it-works.texy b/application/cs/how-it-works.texy
index 978e29c388..d58cd6c833 100644
--- a/application/cs/how-it-works.texy
+++ b/application/cs/how-it-works.texy
@@ -22,18 +22,18 @@ Adresářová struktura vypadá nějak takto:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← adresář s aplikací
-│   ├── <b>Presenters/</b>           ← presentery a šablony
-│   │   ├── <b>HomePresenter.php</b> ← třída presenteru Home
-│   │   └── <b>templates/</b>        ← adresář se šablonami
-│   │       ├── <b>@layout.latte</b> ← šablona layoutu
-│   │       └── <b>Home/</b>         ← šablony presenteru Home
-│   │           └── <b>default.latte</b>  ← šablona akce 'default'
-│   ├── <b>Router/</b>               ← konfigurace URL adres
+│   ├── <b>Core/</b>                 ← základní třídy nutné pro chod
+│   │   └── <b>RouterFactory.php</b> ← konfigurace URL adres
+│   ├── <b>UI/</b>                   ← presentery, šablony & spol.
+│   │   ├── <b>@layout.latte</b>     ← šablona layoutu
+│   │   └── <b>Home/</b>             ← adresář presenteru Home
+│   │       ├── <b>HomePresenter.php</b> ← třída presenteru Home
+│   │       └── <b>default.latte</b> ← šablona akce default
 │   └── <b>Bootstrap.php</b>         ← zaváděcí třída Bootstrap
 ├── <b>bin/</b>                      ← skripty spouštěné z příkazové řádky
 ├── <b>config/</b>                   ← konfigurační soubory
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← logované chyby
 ├── <b>temp/</b>                     ← dočasné soubory, cache, …
 ├── <b>vendor/</b>                   ← knihovny instalované Composerem
@@ -91,7 +91,7 @@ Aplikace psané v Nette se člení do spousty tzv. presenterů (v jiných framew
 
 Application začne tím, že požádá tzv. router, aby rozhodl, kterému z presenterů předat aktuální požadavek k vyřízení. Router rozhodne, čí je to zodpovědnost. Podívá se na vstupní URL `https://example.com/product/123` a na základě toho, jak je nastavený, rozhodne, že tohle je práce např. pro **presenter** `Product`, po kterém bude chtít jako **akci** zobrazení (`show`) produktu s `id: 123`. Dvojici presenter + akce je dobrým zvykem zapisovat oddělené dvojtečkou jako `Product:show`.
 
-Tedy router transformoval URL na dvojici `Presenter:action` + parametry, v našem případě `Product:show` + `id: 123`. Jak takový router vypadá se můžete podívat v souboru `app/Router/RouterFactory.php` a podrobně ho popisujeme v kapitole [Routing].
+Tedy router transformoval URL na dvojici `Presenter:action` + parametry, v našem případě `Product:show` + `id: 123`. Jak takový router vypadá se můžete podívat v souboru `app/Core/RouterFactory.php` a podrobně ho popisujeme v kapitole [Routing].
 
 Pojďme dál. Application už zná jméno presenteru a může pokračovat dál. Tím že vyrobí objekt třídy `ProductPresenter`, což je kód presenteru `Product`. Přesněji řečeno, požádá DI kontejner, aby presenter vyrobil, protože od vyrábění je tu on.
 
@@ -121,12 +121,9 @@ Takže, zavolala se metoda `renderShow(123)`, jejíž kód je sice smyšlený p
 
 Následně presenter vrátí odpověď. Tou může být HTML stránka, obrázek, XML dokument, odeslání souboru z disku, JSON nebo třeba přesměrování na jinou stránku. Důležité je, že pokud explicitně neřekneme, jak má odpovědět (což je případ `ProductPresenter`), bude odpovědí vykreslení šablony s HTML stránkou. Proč? Protože v 99 % případů chceme vykreslit šablonu, tudíž presenter tohle chování bere jako výchozí a chce nám ulehčit práci. To je smyslem Nette.
 
-Nemusíme ani uvádět, jakou šablonu vykreslit, cestu k ní si odvodí podle jednoduché logiky. V případě presenteru `Product` a akce `show` zkusí, zda existuje jeden z těchto souborů se šablonou uložených relativně od adresáře s třídou `ProductPresenter`:
+Nemusíme ani uvádět, jakou šablonu vykreslit, cestu k ní si odvodí sám. V případě akce `show` jednodušše zkusí načíst šablonu `show.latte` v adresáři s třídou `ProductPresenter`. Taktéž se pokusí dohledat layout v souboru `@layout.latte` (podrobněji o [dohledávání šablon|templates#hledani-sablon]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Taktéž se pokusí dohledat layout v souboru `@layout.latte` a následně šablonu vykreslí. Tím je úkol presenteru i celé aplikace dokonán a dílo jest završeno. Pokud by šablona neexistovala, vrátí se stránka s chybou 404. Více se o presenterech dočtete na stránce [Presentery|presenters].
+A následně šablony vykreslí. Tím je úkol presenteru i celé aplikace dokonán a dílo jest završeno. Pokud by šablona neexistovala, vrátí se stránka s chybou 404. Více se o presenterech dočtete na stránce [Presentery|presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Pro jistotu, zkusme si zrekapitulovat celý proces s trošku jinou URL:
 3) router URL dekóduje jako dvojici `Home:default`
 4) vytvoří se objekt třídy `HomePresenter`
 5) zavolá se metoda `renderDefault()` (pokud existuje)
-6) vykreslí se šablona např. `templates/Home/default.latte` s layoutem např. `templates/@layout.latte`
+6) vykreslí se šablona např. `default.latte` s layoutem např. `@layout.latte`
 
 
 Možná jste se teď setkali s velkou spoustou nových pojmů, ale věříme, že dávají smysl. Tvorba aplikací v Nette je ohromná pohodička.
diff --git a/application/cs/modules.texy b/application/cs/modules.texy
index 2cb3e42719..f215baec63 100644
--- a/application/cs/modules.texy
+++ b/application/cs/modules.texy
@@ -2,29 +2,31 @@ Moduly
 ******
 
 .[perex]
-Moduly představují v Nette logické celky, ze kterých se aplikace skládá. Jejich součástí jsou presentery, šablony, případně i komponenty a modelové třídy.
+Moduly vnášejí do Nette aplikací přehlednost díky snadnému členění do logických celků.
 
-S jednou složkou pro presentery a jednou pro šablony bychom si u reálných projektů nevystačili. Mít v jedné složce desítky souborů je minimálně nepřehledné. Jak z toho ven? Jednoduše je na disku rozdělíme do podadresářů a v kódu do jmenných prostorů. A přesně to jsou v Nette moduly.
-
-Zapomeňme tedy na jednu složku pro presentery a šablony a místo toho vytvoříme moduly, například `Admin` a `Front`.
+Podobně jako na pevném disku organizujeme soubory do jednotlivých složek, tak i v Nette můžeme presentery, šablony a další pomocné třídy rozdělovat do modulů. Jak to funguje v praxi? Jednoduše začleníme do struktury nové podadresáře. Příklad takové struktury se dvěma moduly Front a Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← adresář s moduly
+app/
+├── UI/
 │   ├── <b>Admin/</b>            ← modul Admin
-│   │   ├── <b>Presenters/</b>   ← jeho presentery
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← modul Front
-│       └── <b>Presenters/</b>   ← jeho presentery
-│           └── ...
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← modul Front
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Tuto adresářovou strukturu budou reflektovat jmenné prostory tříd, takže třeba `DashboardPresenter` bude v prostoru `App\Modules\Admin\Presenters`:
+Tato adresářová struktura se odráží ve jmenných prostorech tříd, takže například `DashboardPresenter` se nachází ve jmenném prostoru `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Na presenter `Dashboard` uvnitř modulu `Admin` se v rámci aplikace odkazujeme pomocí dvojtečkové notace jako na `Admin:Dashboard`, na jeho akci `default` potom jako na `Admin:Dashboard:default`.
-A jak Nette vlastní ví, že `Admin:Dashboard` představuje třídu `App\Modules\Admin\Presenters\DashboardPresenter`? To mu řekneme pomocí [#mapování] v konfiguraci.
-Tedy uvedená struktura není pevná a můžete si ji upravit podle potřeb.
+Na presenter `Dashboard` uvnitř modulu `Admin` odkazujeme v aplikaci pomocí dvojtečkové notace jako na `Admin:Dashboard`. Na jeho akci `default` potom jako na `Admin:Dashboard:default`.
+
+Představená struktura není pevná; můžete si ji zcela [přizpůsobit dle svých potřeb|#mapování] v konfiguraci. .[tip]
 
-Moduly mohou kromě presenterů a šablon samozřejmě obsahovat všechny další součásti, jako jsou třeba komponenty, modelové třídy, atd.
+Moduly mohou kromě presenterů a šablon samozřejmě zahrnovat všechny ostatní soubory, jako jsou například komponenty a pomocné třídy. Pokud uvažujete, kam je zařadit, zvažte využití složky `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Vnořené moduly
 --------------
 
-Moduly nemusí tvořit jen plochou strukturu, lze vytvářet i submoduly, například:
+Moduly mohou mít více úrovní zanoření, podobně jako adresářová struktura na disku:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← adresář s moduly
+app/
+├── UI/
 │   ├── <b>Blog/</b>             ← modul Blog
 │   │   ├── <b>Admin/</b>        ← submodul Admin
-│   │   │   ├── <b>Presenters/</b>
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← submodul Front
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodul Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
 │   ├── <b>Forum/</b>            ← modul Forum
 │   │   └── ...
 \--
 
-Tedy modul `Blog` je rozdělen do submodulů `Admin` a `Front`. A opět se to odrazí na jmenných prostorech, které budou `App\Modules\Blog\Admin\Presenters` apod. Na presenter `Dashboard` uvnitř submodulu se odkazujeme jako `Blog:Admin:Dashboard`.
+Modul `Blog` je rozdělen na submoduly `Admin` a `Front`. To se projeví i ve jmenných prostorech, které pak budou vypadat jako `App\UI\Blog\Admin` a podobně. Na presenter `Dashboard` v rámci submodulu odkazujeme jako na `Blog:Admin:Dashboard`.
+
+Zanoření může být libovolně hluboké, což umožňuje vytvářet sub-submoduly.
 
-Zanořování může pokračovat libovolně hluboko, lze tedy vytvářet sub-submoduly.
+Pokud například v administraci máte mnoho presenterů týkajících se správy objednávek, jako jsou `OrderDetail`, `OrderEdit`, `OrderDispatch` atd., můžete pro lepší organizovanost vytvořit modul `Order`, ve kterém budou presentery `Detail`, `Edit`, `Dispatch` a další.
 
 
 Vytváření odkazů
@@ -102,47 +118,66 @@ Viz [kapitola o routování |routing#Moduly].
 Mapování
 --------
 
-Definuje pravidla, podle kterých se z názvu presenteru odvodí název třídy. Zapisujeme je v [konfiguraci|configuration] pod klíčem `application › mapping`.
+Mapování definuje pravidla pro odvozování názvu třídy z názvu presenteru. Specifikujeme je v [konfiguraci|configuration] pod klíčem `application › mapping`.
 
-Začněme ukázkou, která moduly nepoužívá. Budeme jen chtít, aby třídy presenterů měly jmenný prostor `App\Presenters`. Tedy aby se presenter například `Home` mapoval na třídu `App\Presenters\HomePresenter`. Toho lze docílit následující konfigurací:
+Adresářové struktury uváděné výše na této stránce vycházejí z tohoto mapování:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Název presenteru se nahradí za hvezdičku v masce třídy a výsledkem je název třídy. Snadné!
+Jak mapování funguje? Pro lepší pochopení si nejprve představme aplikaci bez modulů. Chceme, aby třídy presenterů spadaly do jmenného prostoru `App\UI`, aby se presenter `Home` mapoval na třídu `App\UI\HomePresenter`. Což dosáhneme touto konfigurací:
 
-Pokud presentery členíme do modulů, můžeme pro každý modul mít vlastní mapování:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Mapování funguje tak, že název presenteru `Home` nahradí hvězdičku v masce `App\UI\*Presenter`, čímž získáme výsledný název třídy `App\UI\HomePresenter`. Jednoduché!
+
+Jak ale vidíte v ukázkách v této a dalších kapitolách, třídy presenterů umisťujeme do eponymních podadresářů, například presenter `Home` se mapuje na třídu `App\UI\Home\HomePresenter`. Toho dosáhneme zdvojením dvojtečky (vyžaduje Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Nyní přistoupíme k mapování presenterů do modulů. Pro každý modul můžeme definovat specifické mapování:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Nyní se presenter `Front:Home` mapuje na třídu `App\Modules\Front\Presenters\HomePresenter` a presenter `Admin:Dashboard` na třídu `App\Modules\Admin\Presenters\DashboardPresenter`.
+Podle této konfigurace se presenter `Front:Home` mapuje na třídu `App\UI\Front\Home\HomePresenter`, zatímco presenter `Api:OAuth` na třídu `App\Api\OAuthPresenter`.
 
-Praktičtější bude vytvořit obecné (hvězdičkové) pravidlo, které první dvě nahradí. V masce třídy přibude hvezdička navíc právě pro modul:
+Protože moduly `Front` i `Admin` mají podobný způsob mapování a takových modulů bude nejspíš více, je možné vytvořit obecné pravidlo, které je nahradí. Do masky třídy tak přibude nová hvězdička pro modul:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Ale co když používáme vícenásobně zanořené moduly a máme třeba presenter `Admin:User:Edit`? V takovém případě se segment s hvězdičkou představující modul pro každou úroveň jednoduše zopakuje a výsledkem bude třída `App\Modules\Admin\User\Presenters\EditPresenter`.
+Pro vícenásobně zanořené moduly, jako je například presenter `Admin:User:Edit`, se segment s hvězdičkou opakuje pro každou úroveň a výsledkem je třída `App\UI\Admin\User\Edit\EditPresenter`.
 
 Alternativním zápisem je místo řetězce použít pole skládající se ze tří segmentů. Tento zápis je ekvivaletní s předchozím:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Výchozí hodnotou je `*: *Module\*Presenter`.
+Pokud bychom měli v konfiguraci jen jediné pravidlo, ono obecné, můžeme zkráceně zapsat:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/cs/presenters.texy b/application/cs/presenters.texy
index 41be48834b..06ff5d50b1 100644
--- a/application/cs/presenters.texy
+++ b/application/cs/presenters.texy
@@ -60,7 +60,7 @@ Obdoba metody `render<View>()`. Zatímco `render<View>()` je určená k tomu, ab
 
 Důležité je, že `action<Action>()` se volá dříve než `render<View>()`, takže v ní můžeme případně změnit další běh dějin, tj. změnit šablonu, která se bude kreslit, a také metodu `render<View>()`, která se bude volat. A to pomocí `setView('jineView')`.
 
-Metodě se předávají parametry z požadavku. Je možné a doporučené uvést parametrům typy, např. `actionShow(int $id, string $slug = null)` - pokud bude parametr `id` chybět nebo pokud nebude integer, presenter vrátí [chybu 404|#Chyba 404 a spol.] a ukončí činnost.
+Metodě se předávají parametry z požadavku. Je možné a doporučené uvést parametrům typy, např. `actionShow(int $id, ?string $slug = null)` - pokud bude parametr `id` chybět nebo pokud nebude integer, presenter vrátí [chybu 404|#Chyba 404 a spol.] a ukončí činnost.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */); // a přesměrujeme
 Chyba 404 a spol.
 =================
 
-Pokud nelze splnit požadavek, třeba z důvodu, že článek který chceme zobrazit neexistuje v databázi, vyhodíme chybu 404 metodou `error(string $message = null, int $httpCode = 404)`.
+Pokud nelze splnit požadavek, třeba z důvodu, že článek který chceme zobrazit neexistuje v databázi, vyhodíme chybu 404 metodou `error(?string $message = null, int $httpCode = 404)`.
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parametry požadavku .{data-version:3.1.14}
+==========================================
+
+Presenter a také každá komponenta získává z HTTP požadavku své parametry. Jejich hodnotu zjistíte metodou `getParameter($name)` nebo `getParameters()`. Hodnoty jsou řetězce či pole řetězců, jde v podstatě o surové data získané přímo z URL.
+
+Pro větší pohodlí doporučujeme parametry zpřístupnit přes property. Stačí je označit atributem `#[Parameter]`:
+
+```php
+use Nette\Application\Attributes\Parameter;  // tento řádek je důležitý
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // musí být public
+}
+```
+
+U property doporučujeme uvádět i datový typ (např. `string`) a Nette podle něj hodnotu automaticky přetypuje. Hodnoty parametrů lze také [validovat |#Validace parametrů].
+
+Při vytváření odkazu lze parametrům hodnotu přímo nastavit:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Persistentní parametry
 ======================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Pokud bude `$this->lang` mít hodnotu například `'en'`, tak i odkazy vytvořené pomocí `link()` nebo `n:href` budou obsahovat parameter `lang=en`. A po kliknutí na odkaz bude opět `$this->lang = 'en'`.
 
-U property doporučujeme uvádět i datový typ (např. `string`) a můžete uvést i výchozí hodnotu. Hodnoty parametrů lze [validovat |#Validace persistentních parametrů].
+U property doporučujeme uvádět i datový typ (např. `string`) a můžete uvést i výchozí hodnotu. Hodnoty parametrů lze [validovat |#Validace parametrů].
 
 Persistentní parametry se standardně přenášejí mezi všemi akcemi daného presenteru. Aby se přenášely i mezi více presentery, je potřeba je definovat buď:
 
@@ -307,18 +333,12 @@ Jdeme do hloubky
 S tím, co jsme si dosud v této kapitole ukázali, si nejspíš úplně vystačíte. Následující řádky jsou určeny těm, kdo se zajímají o presentery do hloubky a chtějí vědět úplně všechno.
 
 
-Požadavek a parametry
----------------------
+Validace parametrů
+------------------
 
-Požadavek, který vyřizuje presenter, je objekt [api:Nette\Application\Request] a vrací ho metoda presenteru `getRequest()`. Jeho součástí je pole parametrů a každý z nich patří buď některé z komponent, nebo přímo presenteru (což je vlastně také komponenta, byť speciální). Nette tedy parametry přerozdělí a předá mezi jednotlivé komponenty (a presenter) zavoláním metody `loadState(array $params)`. Získat parametry lze metodu `getParameters(): array`, jednotlivě pomocí `getParameter($name)`. Hodnoty parametrů jsou řetězce či pole řetězců, jde v podstatě o surové data získané přímo z URL.
+Hodnoty [parametrů požadavku |#Parametry požadavku] a [persistentních parametrů |#Persistentní parametry] přijatých z URL zapisuje do properties metoda `loadState()`. Ta také kontroluje, zda odpovídá datový typ uvedený u property, jinak odpoví chybou 404 a stránka se nezobrazí.
 
-
-Validace persistentních parametrů
----------------------------------
-
-Hodnoty [persistentních parametrů |#Persistentní parametry] přijatých z URL zapisuje do properties metoda `loadState()`. Ta také kontroluje, zda odpovídá datový typ uvedený u property, jinak odpoví chybou 404 a stránka se nezobrazí.
-
-Nikdy slepě nevěřte persistentním parametrům, protože mohou být snadno uživatelem přepsány v URL. Takto například ověříme, zda je jazyk `$this->lang` mezi podporovanými. Vhodnou cestou je přepsat zmíněnou metodu `loadState()`:
+Nikdy slepě nevěřte parametrům, protože mohou být snadno uživatelem přepsány v URL. Takto například ověříme, zda je jazyk `$this->lang` mezi podporovanými. Vhodnou cestou je přepsat zmíněnou metodu `loadState()`:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,6 +361,8 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Uložení a obnovení požadavku
 ----------------------------
 
+Požadavek, který vyřizuje presenter, je objekt [api:Nette\Application\Request] a vrací ho metoda presenteru `getRequest()`.
+
 Aktuální požadavek lze uložit do session nebo naopak z ní obnovit a nechat jej presenter znovu vykonat. To se hodí například v situaci, když uživatel vyplňuje formulář a vyprší mu přihlášení. Aby o data nepřišel, před přesměrováním na přihlašovací stránku aktuální požadavek uložíme do session pomocí `$reqId = $this->storeRequest()`, které vrátí jeho identifikátor v podobě krátkého řetězce a ten předáme jako parameter přihlašovacímu presenteru.
 
 Po přihlášení zavoláme metodu `$this->restoreRequest($reqId)`, která požadavek vyzvedne ze session a forwarduje na něj. Metoda přitom ověří, že požadavek vytvořil stejný uživatel, jako se nyní přihlásil. Pokud by se přihlásil jiný uživatel nebo klíč byl neplatný, neudělá nic a program pokračuje dál.
@@ -362,7 +384,7 @@ K přesměrování nedojde při AJAXovém nebo POST požadavku, protože by doš
 Kanonizaci můžete vyvolat i manuálně pomocí metody `canonicalize()`, které se podobně jako metodě `link()` předá presenter, akce a parametry. Vyrobí odkaz a porovná ho s aktuální URL adresou. Pokud se liší, tak přesměruje na vygenerovaný odkaz.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// přesměruje, pokud $slug se liší od $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Omezení přístupu pomocí `#[Requires]` .{data-version:3.2.2}
+-----------------------------------------------------------
+
+Atribut `#[Requires]` poskytuje pokročilé možnosti pro omezení přístupu k presenterům a jejich metodám. Lze jej použít pro specifikaci HTTP metod, vyžadování AJAXového požadavku, omezení na stejný původ (same origin), a přístup pouze přes forwardování. Atribut lze aplikovat jak na třídy presenterů, tak na jednotlivé metody `action<Action>()`, `render<View>()`, `handle<Signal>()` a `createComponent<Name>()`.
+
+Můžete určit tyto omezení:
+- na HTTP metody: `#[Requires(methods: ['GET', 'POST'])]`
+- vyžadování AJAXového požadavku: `#[Requires(ajax: true)]`
+- přístup pouze ze stejného původu: `#[Requires(sameOrigin: true)]`
+- přístup pouze přes forward: `#[Requires(forward: true)]`
+- omezení na konkrétní akce: `#[Requires(actions: 'default')]`
+
+Podrobnosti najdete v návodu [Jak používat atribut Requires |best-practices:attribute-requires].
+
+
+Kontrola HTTP metody
+--------------------
+
+Presentery v Nette automaticky ověřují HTTP metodu každého příchozího požadavku. Důvodem pro tuto kontrolu je především bezpečnost. Standardně jsou povoleny metody `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Chcete-li povolit navíc například metodu `OPTIONS`, použijte k tomu atribut `#[Requires]` (od Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Ve verzi 3.1 se ověření provádí v `checkHttpMethod()`, která zjišťuje, zda je metoda specifikovaná v požadavku obsažena v poli `$presenter->allowedMethods`. Přidání metody udělejte takto:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Je důležité zdůraznit, že pokud povolíte metodu `OPTIONS`, musíte ji následně také patřičně obsloužit v rámci svého presenteru. Metoda je často používána jako tzv. preflight request, který prohlížeč automaticky odesílá před skutečným požadavkem, když je potřeba zjistit, zda je požadavek povolený z hlediska CORS (Cross-Origin Resource Sharing) politiky. Pokud metodu povolíte, ale neimplementujete správnou odpověď, může to vést k nekonzistencím a potenciálním bezpečnostním problémům.
+
+
 Další četba
 ===========
 
diff --git a/application/cs/routing.texy b/application/cs/routing.texy
index 3f58166681..ac3cc3aa7a 100644
--- a/application/cs/routing.texy
+++ b/application/cs/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Rozšířený zápis
 ---------------
 
-Druhý parametr routy, který často zapisujeme ve formátu `Presenter:action`, je zkratkou, kterou můžeme zapsat také ve formě pole, kde přímo uvádíme (výchozí) hodnoty jednotlivých parametrů:
+Cíl routy obvykle zapisovaný ve tvaru `Presenter:action` může být také zapsát pomocí pole, které definuje jednotlivé parametry a jejich výchozí hodnoty:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Nebo můžeme použít tuto formu, všimněte si přepisu validačního regulárního výrazu:
+Pro detailnější specifikaci lze použít ještě rozšířenější formu, kde kromě výchozích hodnot můžeme nastavit i další vlastnosti parametrů, jako třeba validační regulární výraz (viz parametr `id`):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Tyto upovídanější formáty se hodí pro doplnění dalších metadat.
+Je důležité poznamenat, že pokud parametry definované v poli nejsou uvedeny v masce cesty, jejich hodnoty nelze změnit, ani pomocí query parametrů uvedených za otazníkem v URL.
 
 
 Filtry a překlady
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Začlenění do aplikace
 =====================
 
-Abychom vytvořený router zapojili do aplikace, musíme o něm říci DI kontejneru. Nejsnazší cesta je připravit továrnu, která objekt routeru vyrobí, a sdělit v konfiguraci kontejneru, že ji má použít. Dejme tomu, že k tomu účelu napíšeme metodu `App\Router\RouterFactory::createRouter()`:
+Abychom vytvořený router zapojili do aplikace, musíme o něm říci DI kontejneru. Nejsnazší cesta je připravit továrnu, která objekt routeru vyrobí, a sdělit v konfiguraci kontejneru, že ji má použít. Dejme tomu, že k tomu účelu napíšeme metodu `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Do [konfigurace |dependency-injection:services] pak zapíšeme:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Jakékoliv závislosti, třeba na databázi atd, se předají tovární metodě jako její parametry pomocí [autowiringu|dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Samostatným použitím myslíme využití schopností routeru v aplikaci, kter
 Takže opět si vytvoříme metodu, která nám sestaví router, např.:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Anebo objekty přímo vyrobíme:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/cs/templates.texy b/application/cs/templates.texy
index 5d0de8dc1a..470c68748b 100644
--- a/application/cs/templates.texy
+++ b/application/cs/templates.texy
@@ -37,29 +37,75 @@ Ta definuje blok `content`, který se vloží na místo `{include content}` v la
 Hledání šablon
 --------------
 
-Cestu k šablonám odvodí presenter podle jednoduché logiky. Zkusí, zda existuje jeden z těchto souborů umístěných relativně od adresáře s třídou presenteru, kde `<Presenter>` je název aktuálního presenteru a `<view>` je název aktuální akce:
+Nemusíte v presenterech uvádět, jaká šablona se má vykreslit, framework cestu odvodí sám a ušetří vám psaní.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Pokud používáte adresářovou strukturu, kde každý presenter má vlastní adresář, jednodušše umístěte šablonu do tohoto adresáře pod jménem akce (resp. view), tj. pro akci `default` použijte šablonu `default.latte`:
 
-Pokud šablonu nenajde, zkusí hledat ještě v adresáři `templates` o úroveň výš, tj. na stejné úrovni, jako je adresář s třídou presenteru.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Pokud ani tam šablonu nenajde, je odpovědí [chyba 404|presenters#Chyba 404 a spol.].
+Pokud používáte strukturu, kde jsou společně presentery v jednom adresáři a šablony ve složce `templates`, uložte ji buď do souboru `<Presenter>.<view>.latte` nebo `<Presenter>/<view>.latte`:
 
-Můžete také změnit view pomocí `$this->setView('jineView')`. Nebo místo dohledávání přímo určit jméno souboru se šablonou pomocí `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1. varianta
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2. varianta
+\--
+
+Adresář `templates` může být umístěn také o úroveň výš, tj. na stejné úrovni, jako je adresář s třídami presenterů.
+
+Pokud se šablona nenajde, presenter odpoví [chybou 404 - page not found|presenters#Chyba 404 a spol].
+
+View změníte pomocí `$this->setView('jineView')`. Také lze přímo určit soubor se šablonou pomocí `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
 Soubory, kde se dohledávají šablony, lze změnit překrytím metody [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], která vrací pole možných názvů souborů.
 
-Layout se očekává v těchto souborech:
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` layout společný pro více presenterů
+Hledání šablony layoutu
+-----------------------
+
+Nette také automaticky dohledává soubor s layoutem.
+
+Pokud používáte adresářovou strukturu, kde každý presenter má vlastní adresář, umístěte layout buď do složky s presenterem, pokud je specifický jen pro něj, nebo o úroveň výš, pokud je společný pro více presenterů:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← společný layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← jen pro presenter Home
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Pokud používáte strukturu, kde jsou společně presentery v jednom adresáři a šablony ve složce `templates`, bude se layout očekávat na těchto místech:
+
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← společný layout
+        ├── <b>Home.@layout.latte</b>  ← jen pro Home, 1. varianta
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← jen pro Home, 2. varianta
+\--
+
+Pokud se presenter nachází v [modulu|modules], bude se dohledávat i o další adresářové úrovně výš, podle zanoření modulu.
 
-Kde `<Presenter>` je název aktuálního presenteru a `<layout>` je název layoutu, což je standardně `'layout'`. Název lze změnit pomocí `$this->setLayout('jinyLayout')`, takže se budou zkoušet soubory `@jinyLayout.latte`.
+Název layoutu lze změnit pomocí `$this->setLayout('layoutAdmin')` a pak se bude očekávat v souboru `@layoutAdmin.latte`. Také lze přímo určit soubor se šablonou layoutu pomocí `$this->setLayout('/path/to/template.latte')`.
 
-Můžete také přímo určit jméno souboru se šablonou layoutu pomocí `$this->setLayout('/path/to/template.latte')`. Pomocí `$this->setLayout(false)` se dohledávání layoutu vypne.
+Pomocí `$this->setLayout(false)` nebo značky `{layout none}` uvnitř šablony se dohledávání layoutu vypne.
 
 .[note]
 Soubory, kde se dohledávají šablony layoutu, lze změnit překrytím metody [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], která vrací pole možných názvů souborů.
@@ -104,7 +150,7 @@ Anotace `@property-read` je určená pro IDE a statickou analýzu, díky ní bud
 Luxusu našeptávání si můžete dopřát i v šablonách, stačí do PhpStorm nainstalovat plugin pro Latte a uvést na začátek šablony název třídy, více v článku "Latte: jak na typový systém":https://blog.nette.org/cs/latte-jak-na-typovy-system:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte ve verzi 3 nabízí pokročilejší způsob a to vytvoření si [extension |latte:creating-extension] pro každý webový projekt. Kusý příklad takové třídy:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ Zaregistrujeme ji pomocí [konfigurace |configuration#Šablony Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Translator je alternativně možné nastavit pomocí [konfigurace |configuration
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Poté lze překladač používat například jako filtr `|translate`, a to včetně doplňujících parametrů, které se předají metodě `translate()` (viz `foo, bar`):
diff --git a/application/de/@home.texy b/application/de/@home.texy
index 91906d2888..078fe84ca4 100644
--- a/application/de/@home.texy
+++ b/application/de/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | Version | kompatibel mit PHP
 |-----------|-------------------
-| Nette-Anwendung 4.0 | PHP 8.0 - 8.2
-| Nette Anwendung 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Anwendung 3.0 | PHP 7.1 - 8.0
 | Nette-Anwendung 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/de/ajax.texy b/application/de/ajax.texy
index 63922c5732..fe36f40a83 100644
--- a/application/de/ajax.texy
+++ b/application/de/ajax.texy
@@ -3,10 +3,10 @@ AJAX & Schnipsel
 
 <div class=perex>
 
-Moderne Webanwendungen laufen heute zur Hälfte auf einem Server und zur Hälfte in einem Browser. AJAX ist ein wichtiger verbindender Faktor. Welche Unterstützung bietet das Nette Framework?
-- Senden von Template-Fragmenten (sogenannte *snippets*)
+Im Zeitalter moderner Webanwendungen, bei denen sich die Funktionalität oft zwischen Server und Browser erstreckt, ist AJAX ein wesentliches Verbindungselement. Welche Möglichkeiten bietet das Nette Framework in diesem Bereich?
+- Senden von Teilen des Templates, sogenannte Snippets
 - Übergabe von Variablen zwischen PHP und JavaScript
-- Debugging von AJAX-Anwendungen
+- Werkzeuge zur Fehlersuche bei AJAX-Anfragen
 
 </div>
 
@@ -14,29 +14,32 @@ Moderne Webanwendungen laufen heute zur Hälfte auf einem Server und zur Hälfte
 AJAX-Anfrage .[#toc-ajax-request]
 =================================
 
-Eine AJAX-Anfrage unterscheidet sich nicht von einer klassischen Anfrage - der Presenter wird mit einer bestimmten Ansicht und Parametern aufgerufen. Es liegt auch am Präsentator, wie er darauf reagiert: Er kann seine eigene Routine verwenden, die ein HTML-Codefragment (HTML-Snippet), ein XML-Dokument, ein JSON-Objekt oder JavaScript-Code zurückgibt.
+Eine AJAX-Anfrage unterscheidet sich im Grunde nicht von einer klassischen HTTP-Anfrage. Ein Presenter wird mit bestimmten Parametern aufgerufen. Es liegt am Präsentator, wie er auf die Anfrage antwortet - er kann Daten im JSON-Format zurückgeben, einen Teil des HTML-Codes, ein XML-Dokument usw. senden.
 
-Auf der Serverseite kann eine AJAX-Anfrage mit Hilfe der Servicemethode erkannt werden [, die die HTTP-Anfrage kapselt |http:request] `$httpRequest->isAjax()` (erkennt auf der Grundlage des HTTP-Headers `X-Requested-With`). Innerhalb des Presenters ist eine Abkürzung in Form der Methode `$this->isAjax()` verfügbar.
+Auf der Browserseite initiieren wir eine AJAX-Anfrage mit der Funktion `fetch()`:
 
-Es gibt ein vorverarbeitetes Objekt namens `payload`, das für das Senden von Daten in JSON an den Browser bestimmt ist.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Erfolg';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// Bearbeitung der Antwort
+});
 ```
 
-Um die volle Kontrolle über Ihre JSON-Ausgabe zu haben, verwenden Sie die Methode `sendJson` in Ihrem Presenter. Sie beendet den Presenter sofort und Sie können auf eine Vorlage verzichten:
+Auf der Serverseite wird eine AJAX-Anfrage durch die Methode `$httpRequest->isAjax()` des Dienstes erkannt [, der die HTTP-Anfrage kapselt |http:request]. Sie verwendet den HTTP-Header `X-Requested-With` und muss daher unbedingt gesendet werden. Innerhalb des Presenters können Sie die Methode `$this->isAjax()` verwenden.
+
+Wenn Sie Daten im JSON-Format senden möchten, verwenden Sie die [`sendJson()` |presenters#Sending a response] Methode. Die Methode beendet auch die Aktivität des Presenters.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Wenn wir HTML senden wollen, können wir entweder eine spezielle Vorlage für AJAX-Anfragen festlegen:
+Wenn Sie vorhaben, mit einer speziellen Vorlage für AJAX zu antworten, können Sie dies wie folgt tun:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Schnipsel .[#toc-snippets]
+==========================
+
+Das mächtigste Werkzeug, das Nette für die Verbindung zwischen Server und Client bietet, sind Snippets. Mit ihnen lässt sich eine gewöhnliche Anwendung mit minimalem Aufwand und ein paar Zeilen Code in eine AJAX-Anwendung verwandeln. Das Fifteen-Beispiel zeigt, wie das Ganze funktioniert, und der Code ist auf [GitHub |https://github.com/nette-examples/fifteen] zu finden.
+
+Mit Snippets oder Clippings können Sie nur Teile der Seite aktualisieren, anstatt die gesamte Seite neu zu laden. Das ist schneller und effizienter und bietet zudem eine komfortablere Benutzererfahrung. Snippets erinnern Sie vielleicht an Hotwire für Ruby on Rails oder Symfony UX Turbo. Interessanterweise hat Nette Snippets schon 14 Jahre früher eingeführt.
+
+Wie funktionieren Snippets? Wenn die Seite zum ersten Mal geladen wird (eine Nicht-AJAX-Anfrage), wird die gesamte Seite, einschließlich aller Snippets, geladen. Wenn der Benutzer mit der Seite interagiert (z. B. auf eine Schaltfläche klickt, ein Formular ausfüllt usw.), wird nicht die gesamte Seite geladen, sondern eine AJAX-Anfrage gestellt. Der Code im Presenter führt die Aktion aus und entscheidet, welche Snippets aktualisiert werden müssen. Nette rendert diese Schnipsel und sendet sie in Form eines JSON-Arrays. Der Verarbeitungscode im Browser fügt dann die empfangenen Snippets wieder in die Seite ein. Es wird also nur der Code der geänderten Snippets übertragen, was im Vergleich zur Übertragung des gesamten Seiteninhalts Bandbreite spart und das Laden beschleunigt.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-Die [Naja-Bibliothek |https://naja.js.org] wird verwendet, um AJAX-Anfragen auf der Browserseite zu verarbeiten. [Installieren |https://naja.js.org/#/guide/01-install-setup-naja] Sie sie als node.js-Paket (zur Verwendung mit Webpack, Rollup, Vite, Parcel und mehr):
+Um Snippets auf der Browserseite zu verarbeiten, wird die [Naja-Bibliothek |https://naja.js.org] verwendet. [Installieren Sie sie |https://naja.js.org/#/guide/01-install-setup-naja] als node.js-Paket (zur Verwendung mit Anwendungen wie Webpack, Rollup, Vite, Parcel und anderen):
 
 ```shell
 npm install naja
 ```
 
-...oder fügen Sie sie direkt in die Seitenvorlage ein:
+... oder fügen Sie sie direkt in die Seitenvorlage ein:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Um eine AJAX-Anfrage aus einem regulären Link (Signal) oder einer Formularübermittlung zu erzeugen, markieren Sie einfach den entsprechenden Link, das Formular oder die Schaltfläche mit der Klasse `ajax`:
+Zunächst müssen Sie die Bibliothek [initialisieren |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization]:
+
+```js
+naja.initialize();
+```
+
+Um einen gewöhnlichen Link (Signal) oder eine Formularübermittlung zu einer AJAX-Anfrage zu machen, markieren Sie einfach den entsprechenden Link, das Formular oder die Schaltfläche mit der Klasse `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Um eine AJAX-Anfrage aus einem regulären Link (Signal) oder einer Formularüber
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Schnipsel .[#toc-snippets]
-==========================
-
-Es gibt ein weitaus mächtigeres Werkzeug der eingebauten AJAX-Unterstützung - Snippets. Mit ihnen ist es möglich, eine normale Anwendung mit nur wenigen Zeilen Code in eine AJAX-Anwendung zu verwandeln. Wie das Ganze funktioniert, wird im Fifteen-Beispiel gezeigt, dessen Code auch im Build oder auf [GitHub |https://github.com/nette-examples/fifteen] verfügbar ist.
-
-Die Funktionsweise der Snippets besteht darin, dass bei der ersten (d.h. Nicht-AJAX-) Anfrage die gesamte Seite übertragen wird und dann bei jeder [AJAX-Unteranfrage |components#signal] (Anfrage derselben Ansicht desselben Präsentators) nur der Code der geänderten Teile in das bereits erwähnte Repository `payload` übertragen wird.
-
-Snippets erinnern vielleicht an Hotwire für Ruby on Rails oder Symfony UX Turbo, aber Nette hat sie schon vierzehn Jahre früher erfunden.
+Schnipsel neu zeichnen .[#toc-redrawing-snippets]
+-------------------------------------------------
 
-
-Invalidierung von Snippets .[#toc-invalidation-of-snippets]
-===========================================================
-
-Jeder Nachkomme der Klasse [Control |components] (also auch ein Presenter) ist in der Lage, sich zu merken, ob es während einer Anfrage Änderungen gab, die ein erneutes Rendern erforderlich machen. Dafür gibt es zwei Methoden: `redrawControl()` und `isControlInvalid()`. Ein Beispiel:
+Jedes Objekt der Klasse [Control |components] (einschließlich des Presenters selbst) hält fest, ob Änderungen eingetreten sind, die ein erneutes Zeichnen erforderlich machen. Zu diesem Zweck wird die Methode `redrawControl()` verwendet.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Das Objekt muss neu gerendert werden, nachdem sich der Benutzer angemeldet hat
+	// nach dem Einloggen muss der entsprechende Teil neu gezeichnet werden
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette bietet jedoch eine noch feinere Auflösung als ganze Komponenten. Die aufgeführten Methoden akzeptieren den Namen eines sogenannten "Snippets" als optionalen Parameter. Ein "Snippet" ist im Grunde ein Element in Ihrer Vorlage, das zu diesem Zweck durch ein Latte-Makro markiert wurde, mehr dazu später. So ist es möglich, eine Komponente aufzufordern, nur *Teile* ihrer Vorlage neu zu zeichnen. Wenn die gesamte Komponente ungültig ist, werden alle ihre Schnipsel neu gerendert. Eine Komponente ist auch dann "ungültig", wenn eine ihrer Unterkomponenten ungültig ist.
 
-```php
-$this->isControlInvalid(); // -> false
+Nette ermöglicht auch eine genauere Kontrolle darüber, was neu gezeichnet werden muss. Die oben erwähnte Methode kann den Snippet-Namen als Argument verwenden. So ist es möglich, auf der Ebene des Schablonenteils zu invalidieren (d.h. ein Neuzeichnen zu erzwingen). Wird die gesamte Komponente für ungültig erklärt, wird auch jedes Snippet davon neu gezeichnet:
 
-$this->redrawControl('header'); // macht das Snippet namens 'header' ungültig
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, mindestens ein Snippet ist ungültig
-
-$this->redrawControl(); // macht die gesamte Komponente ungültig, jedes Snippet
-$this->isControlInvalid('footer'); // -> true
+```php
+// macht den "Header"-Schnipsel ungültig
+$this->redrawControl('header');
 ```
 
-Eine Komponente, die ein Signal erhält, wird automatisch zum Neuzeichnen markiert.
-
-Dank des Snippet-Redrawing wissen wir genau, welche Teile welcher Elemente neu gezeichnet werden sollten.
-
-
-Tag `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
-
-Das Rendering der Seite verläuft ganz ähnlich wie bei einer normalen Anfrage: Es werden die gleichen Vorlagen geladen usw. Entscheidend ist jedoch, dass die Teile, die nicht in die Ausgabe gelangen sollen, weggelassen werden; die anderen Teile sollen mit einem Bezeichner verknüpft und in einem für einen JavaScript-Handler verständlichen Format an den Benutzer gesendet werden.
-
 
-Syntax .[#toc-syntax]
----------------------
+Schnipsel in Latte .[#toc-snippets-in-latte]
+--------------------------------------------
 
-Wenn ein Steuerelement oder ein Snippet in der Vorlage vorhanden ist, müssen wir es mit dem `{snippet} ... {/snippet}` pair-Tag einpacken - er sorgt dafür, dass das gerenderte Snippet "ausgeschnitten" und an den Browser gesendet wird. Außerdem wird es in ein Hilfs-Tag eingebettet `<div>` Tag (es ist möglich, einen anderen zu verwenden). Im folgenden Beispiel wird ein Snippet mit dem Namen `header` definiert. Es kann ebenso gut die Vorlage einer Komponente darstellen:
+Die Verwendung von Snippets in Latte ist extrem einfach. Um einen Teil der Vorlage als Snippet zu definieren, umhüllen Sie ihn einfach mit den Tags `{snippet}` und `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Wenn ein Steuerelement oder ein Snippet in der Vorlage vorhanden ist, müssen wi
 {/snippet}
 ```
 
-Wenn Sie ein Snippet mit einem anderen Element erstellen möchten als `<div>` erstellen oder dem Element benutzerdefinierte Attribute hinzufügen möchten, können Sie die folgende Definition verwenden:
+Das Snippet erzeugt ein Element `<div>` in der HTML-Seite mit einem speziell generierten `id`. Wenn ein Snippet neu gezeichnet wird, wird der Inhalt dieses Elements aktualisiert. Daher müssen beim ersten Rendering der Seite alle Snippets ebenfalls gerendert werden, auch wenn sie zunächst leer sind.
+
+Sie können auch ein Snippet mit einem anderen Element als `<div>` mit einem n:-Attribut erstellen:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Wenn Sie ein Snippet mit einem anderen Element erstellen möchten als `<div>` er
 ```
 
 
-Dynamische Schnipsel .[#toc-dynamic-snippets]
-=============================================
+Schnipsel Bereiche .[#toc-snippet-areas]
+----------------------------------------
 
-In Nette können Sie auch Snippets mit einem dynamischen Namen definieren, der auf einem Laufzeitparameter basiert. Dies eignet sich besonders für verschiedene Listen, bei denen nur eine Zeile geändert werden muss, aber nicht die ganze Liste mit übertragen werden soll. Ein Beispiel hierfür wäre:
+Snippet-Namen können auch Ausdrücke sein:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Es gibt ein statisches Snippet namens `itemsContainer`, das mehrere dynamische Snippets enthält: `item-0`, `item-1` und so weiter.
+Auf diese Weise erhalten wir mehrere Snippets wie `item-0`, `item-1`, usw. Wenn wir einen dynamischen Ausschnitt (z. B. `item-1`) direkt ungültig machen würden, würde nichts neu gezeichnet werden. Der Grund dafür ist, dass Snippets als echte Auszüge funktionieren und nur sie selbst direkt gerendert werden. In der Vorlage gibt es jedoch technisch gesehen kein Snippet namens `item-1`. Es taucht nur auf, wenn der umgebende Code des Snippets ausgeführt wird, in diesem Fall die foreach-Schleife. Daher markieren wir den Teil der Vorlage, der ausgeführt werden muss, mit dem Tag `{snippetArea}`:
 
-Ein dynamisches Snippet kann nicht direkt neu gezeichnet werden (das erneute Zeichnen von `item-1` hat keine Auswirkung), Sie müssen das übergeordnete Snippet (in diesem Beispiel `itemsContainer`) neu zeichnen. Dies bewirkt, dass der Code des übergeordneten Snippets ausgeführt wird, aber nur seine Unter-Snippets an den Browser gesendet werden. Wenn Sie nur einen der Teil-Snippets senden wollen, müssen Sie die Eingabe für das übergeordnete Snippet so ändern, dass die anderen Teil-Snippets nicht erzeugt werden.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-Im obigen Beispiel müssen Sie sicherstellen, dass bei einer AJAX-Anfrage nur ein Element zum Array `$list` hinzugefügt wird, so dass die Schleife `foreach` nur ein dynamisches Snippet ausgibt.
+Und wir werden sowohl das einzelne Snippet als auch den gesamten übergreifenden Bereich neu zeichnen:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Es ist auch wichtig, dass das Array `$items` nur die Elemente enthält, die neu gezeichnet werden sollen.
 
-Snippets in einer eingebundenen Vorlage .[#toc-snippets-in-an-included-template]
-================================================================================
-
-Es kann vorkommen, dass sich das Snippet in einer Vorlage befindet, die von einer anderen Vorlage eingebunden wird. In diesem Fall müssen wir den Einbindungscode in der zweiten Vorlage mit dem `snippetArea` -Makro einschließen, dann zeichnen wir sowohl den Snippet-Bereich als auch das eigentliche Snippet neu.
-
-Das Makro `snippetArea` sorgt dafür, dass der darin enthaltene Code ausgeführt wird, aber nur das eigentliche Snippet in der eingebundenen Vorlage an den Browser gesendet wird.
+Beim Einfügen einer anderen Vorlage in die Hauptvorlage unter Verwendung des `{include}` -Tags, das Snippets enthält, muss die eingefügte Vorlage erneut in ein `snippetArea` -Tag eingeschlossen und sowohl das Snippet als auch der Bereich gemeinsam ungültig gemacht werden:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* enthalten.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Sie können es auch mit dynamischen Snippets kombinieren.
-
-
-Hinzufügen und Löschen .[#toc-adding-and-deleting]
-==================================================
 
-Wenn Sie ein neues Element in die Liste einfügen und `itemsContainer` ungültig machen, liefert die AJAX-Anfrage Snippets, die das neue Element enthalten, aber der Javascript-Handler kann es nicht darstellen. Das liegt daran, dass es kein HTML-Element mit der neu erstellten ID gibt.
+Schnipsel in Komponenten .[#toc-snippets-in-components]
+-------------------------------------------------------
 
-In diesem Fall besteht die einfachste Möglichkeit darin, die gesamte Liste in ein weiteres Snippet zu verpacken und alles ungültig zu machen:
+Sie können Snippets in [Komponenten |components] erstellen, und Nette wird sie automatisch neu zeichnen. Es gibt jedoch eine bestimmte Einschränkung: Um Snippets neu zu zeichnen, wird die Methode `render()` ohne Parameter aufgerufen. Die Übergabe von Parametern in der Vorlage funktioniert also nicht:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Senden von Benutzerdaten .[#toc-sending-user-data]
+--------------------------------------------------
+
+Neben den Snippets können Sie beliebige weitere Daten an den Client senden. Schreiben Sie sie einfach in das `payload` Objekt:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Das Gleiche gilt für das Löschen eines Eintrags. Es wäre möglich, ein leeres Snippet zu senden, aber in der Regel können Listen paginiert werden, und es wäre kompliziert, das Löschen eines Elements und das Laden eines anderen (das sich auf einer anderen Seite der paginierten Liste befand) zu implementieren.
 
-
-Parameter an die Komponente senden .[#toc-sending-parameters-to-component]
-==========================================================================
+Senden von Parametern .[#toc-sending-parameters]
+================================================
 
 Wenn wir Parameter über eine AJAX-Anfrage an die Komponente senden, egal ob es sich um Signalparameter oder dauerhafte Parameter handelt, müssen wir ihren globalen Namen angeben, der auch den Namen der Komponente enthält. Den vollständigen Namen des Parameters gibt die Methode `getParameterId()` zurück.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Und behandeln Sie die Methode mit den entsprechenden Parametern in der Komponente.
+Eine Handle-Methode mit den entsprechenden Parametern in der Komponente:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/de/bootstrap.texy b/application/de/bootstrap.texy
index 590e4e76ef..6c441bfcf9 100644
--- a/application/de/bootstrap.texy
+++ b/application/de/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Der Konfigurator ist für das Einrichten der Anwendungsumgebung und der Dienste zuständig.
+		$this->configurator = new Configurator;
+		// Legen Sie das Verzeichnis für temporäre Dateien fest, die von Nette erzeugt werden (z. B. kompilierte Vorlagen)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette ist intelligent, und der Entwicklungsmodus wird automatisch aktiviert,
+		// oder Sie können ihn für eine bestimmte IP-Adresse aktivieren, indem Sie die folgende Zeile auskommentieren:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Aktiviert Tracy: das ultimative "Schweizer Taschenmesser" zur Fehlersuche.
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: Lädt automatisch alle Klassen im angegebenen Verzeichnis
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Konfigurationsdateien laden
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Im Falle von Webanwendungen ist die Ausgangsdatei `index.php`, die sich im öffentlichen Verzeichnis `www/` befindet. Sie überlässt es der Klasse `Bootstrap`, die Umgebung zu initialisieren und den `$configurator` zurückzugeben, der den DI-Container erstellt. Dann wird der Dienst `Application` aufgerufen, der die Webanwendung ausführt:
+Die Ausgangsdatei für Webanwendungen ist `index.php`, die sich im öffentlichen Verzeichnis `www/` befindet. Sie verwendet die Klasse `Bootstrap`, um die Umgebung zu initialisieren und einen DI-Container zu erstellen. Anschließend wird der Dienst `Application` aus dem Container abgerufen, der die Webanwendung startet:
 
 ```php
-// Initialisieren der Umgebung + Abrufen des Configurator-Objekts
-$configurator = App\Bootstrap::boot();
-// Erstellen eines DI-Containers
-$container = $configurator->createContainer();
-// DI-Container erstellt ein Nette\Application\Application-Objekt
+$bootstrap = new App\Bootstrap;
+// Initialisierung der Umgebung + Erstellung eines DI-Containers
+$container = $bootstrap->bootWebApplication();
+// DI-Container erstellt ein Nette\Anwendung\Anwendungsobjekt
 $application = $container->getByType(Nette\Application\Application::class);
-// Nette-Anwendung starten
+// Starten Sie die Nette-Anwendung und bearbeiten Sie die eingehende Anfrage
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Die Auswahl des Modus erfolgt durch automatische Erkennung, so dass in der Regel
 Wenn Sie den Entwicklungsmodus in anderen Fällen aktivieren möchten, z. B. für Programmierer, die von einer bestimmten IP-Adresse aus zugreifen, können Sie `setDebugMode()` verwenden:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // eine oder mehrere IP-Adressen
+$this->configurator->setDebugMode('23.75.345.200'); // eine oder mehrere IP-Adressen
 ```
 
 Wir empfehlen auf jeden Fall, eine IP-Adresse mit einem Cookie zu kombinieren. Wir speichern ein geheimes Token im `nette-debug` Cookie, z.B. `secret1234`, und der Entwicklungsmodus wird für Programmierer mit dieser Kombination von IP und Cookie aktiviert.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Wir können den Entwicklermodus auch komplett abschalten, sogar für localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Beachten Sie, dass der Wert `true` den Entwicklermodus standardmäßig einschaltet, was auf einem Produktionsserver niemals passieren sollte.
@@ -90,7 +115,7 @@ Debugging-Werkzeug Tracy .[#toc-debugging-tool-tracy]
 Zur einfachen Fehlersuche werden wir das großartige Tool [Tracy |tracy:] einschalten. Im Entwicklermodus zeigt es Fehler an und im Produktionsmodus protokolliert es Fehler in das angegebene Verzeichnis:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Temporäre Dateien .[#toc-temporary-files]
 Nette verwendet den Cache für DI-Container, RobotLoader, Vorlagen usw. Daher ist es notwendig, den Pfad zu dem Verzeichnis festzulegen, in dem der Cache gespeichert werden soll:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Unter Linux oder macOS setzen Sie die [Schreibrechte |nette:troubleshooting#Setting directory permissions] für die Verzeichnisse `log/` und `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Normalerweise wollen wir die Klassen automatisch mit [RobotLoader |robot-loader:] laden, also müssen wir ihn starten und ihn Klassen aus dem Verzeichnis laden lassen, in dem sich `Bootstrap.php` befindet (d.h. `__DIR__`) und aus allen seinen Unterverzeichnissen:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Zeitzone .[#toc-timezone]
 Configurator ermöglicht es Ihnen, eine Zeitzone für Ihre Anwendung festzulegen.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ Im Entwicklungsmodus wird der Container jedes Mal automatisch aktualisiert, wenn
 Konfigurationsdateien werden mit `addConfig()` geladen:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Die Methode `addConfig()` kann mehrfach aufgerufen werden, um mehrere Dateien hinzuzufügen.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Statische Parameter .[#toc-static-parameters]
 Parameter, die in Konfigurationsdateien verwendet werden, können [im Abschnitt `parameters` |dependency-injection:configuration#parameters] definiert und auch von der Methode `addStaticParameters()` übergeben (oder überschrieben) werden (sie hat den Alias `addParameters()`). Wichtig ist, dass unterschiedliche Parameterwerte die Erzeugung zusätzlicher DI-Container, d.h. zusätzlicher Klassen, bewirken.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Dynamische Parameter .[#toc-dynamic-parameters]
 Wir können dem Container auch dynamische Parameter hinzufügen, deren unterschiedliche Werte, im Gegensatz zu statischen Parametern, nicht die Erzeugung neuer DI-Container verursachen.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Umgebungsvariablen können mit dynamischen Parametern leicht verfügbar gemacht werden. Wir können über `%env.variable%` in Konfigurationsdateien auf sie zugreifen.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Sie können die folgenden statischen Parameter in den Konfigurationsdateien verw
 - `%wwwDir%` ist der absolute Pfad zu dem Verzeichnis, das die `index.php` Eintragsdatei enthält
 - `%tempDir%` ist der absolute Pfad zu dem Verzeichnis für temporäre Dateien
 - `%vendorDir%` ist der absolute Pfad zu dem Verzeichnis, in dem Composer die Bibliotheken installiert
+- `%rootDir%` ist der absolute Pfad zum Stammverzeichnis des Projekts
 - `%debugMode%` gibt an, ob sich die Anwendung im Debug-Modus befindet
 - `%consoleMode%` zeigt an, ob die Anfrage über die Befehlszeile kam
 
@@ -225,7 +252,7 @@ services:
 Erstellen Sie eine neue Instanz und fügen Sie sie in Bootstrap ein:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Verschiedene Umgebungen .[#toc-different-environments]
 ======================================================
 
-Es steht Ihnen frei, die Klasse `Bootstrap` an Ihre Bedürfnisse anzupassen. Sie können der Methode `boot()` Parameter hinzufügen, um Webprojekte zu unterscheiden, oder andere Methoden hinzufügen, wie `bootForTests()`, die die Umgebung für Unit-Tests initialisiert, `bootForCli()` für Skripte, die von der Befehlszeile aus aufgerufen werden, und so weiter.
+Zögern Sie nicht, die Klasse `Bootstrap` nach Ihren Bedürfnissen anzupassen. Sie können der Methode `bootWebApplication()` Parameter hinzufügen, um zwischen Webprojekten zu unterscheiden. Alternativ können Sie auch andere Methoden hinzufügen, z. B. `bootTestEnvironment()`, um die Umgebung für Unit-Tests zu initialisieren, `bootConsoleApplication()` für Skripte, die von der Befehlszeile aus aufgerufen werden, und so weiter.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Initialisierung des Nette-Testers
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Nette Tester Initialisierung
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/de/components.texy b/application/de/components.texy
index b4540b4808..d47cc5bd78 100644
--- a/application/de/components.texy
+++ b/application/de/components.texy
@@ -230,6 +230,28 @@ In der Vorlage stehen diese Meldungen in der Variablen `$flashes` als Objekte `s
 ```
 
 
+Umleitung nach einem Signal .[#toc-redirection-after-a-signal]
+==============================================================
+
+Nach der Verarbeitung eines Komponentensignals folgt oft eine Umleitung. Diese Situation ist ähnlich wie bei Formularen - nach dem Absenden eines Formulars leiten wir ebenfalls um, um eine erneute Übermittlung von Daten zu verhindern, wenn die Seite im Browser aktualisiert wird.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Da eine Komponente ein wiederverwendbares Element ist und in der Regel keine direkte Abhängigkeit von bestimmten Presentern haben sollte, interpretieren die Methoden `redirect()` und `link()` den Parameter automatisch als Komponentensignal:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Wenn Sie zu einem anderen Präsentator oder einer Aktion umleiten müssen, können Sie dies über den Präsentator tun:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Dauerhafte Parameter .[#toc-persistent-parameters]
 ==================================================
 
@@ -347,7 +369,7 @@ services:
 Schließlich werden wir diese Fabrik in unserem Präsentator verwenden:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Komponenten im Detail .[#toc-components-in-depth]
 Komponenten in einer Nette-Anwendung sind die wiederverwendbaren Teile einer Web-Anwendung, die wir in Seiten einbetten, was das Thema dieses Kapitels ist. Was genau sind die Fähigkeiten einer solchen Komponente?
 
 1) sie ist in einer Vorlage renderbar
-2) sie weiß, welcher Teil von ihr bei einer [AJAX-Anfrage |ajax#invalidation] gerendert werden soll (Snippets)
+2) es weiß, [welcher Teil von sich selbst |ajax#snippets] während einer AJAX-Anfrage zu rendern ist (Snippets)
 3) er kann seinen Zustand in einer URL speichern (persistente Parameter)
 4) es hat die Fähigkeit, auf Benutzeraktionen zu reagieren (Signale)
 5) er erstellt eine hierarchische Struktur (wobei die Wurzel der Präsentator ist)
diff --git a/application/de/configuration.texy b/application/de/configuration.texy
index da3a0fcebf..848f7abb64 100644
--- a/application/de/configuration.texy
+++ b/application/de/configuration.texy
@@ -13,11 +13,15 @@ Anwendung:
 	# zeigt das Feld "Nette Anwendung" in Tracy BlueScreen?
 	debugger: ...           # (bool) standardmäßig true
 
-	# wird der error-presenter im Fehlerfall aufgerufen?
-	catchExceptions: ...    # (bool) steht im Produktionsmodus standardmäßig auf true
+	# wird error-presenter im Fehlerfall aufgerufen?
+	# hat nur im Entwicklermodus Auswirkungen
+	catchExceptions: ...    # (bool) ist standardmäßig true
 
 	# Name des Fehlermelders
-	errorPresenter: Error   # (string) Standardwert ist 'Nette:Error'
+	errorPresenter: Error   # (string|array) Standardwert ist 'Nette:Error'
+
+	# definiert Aliase für Moderatoren und Veranstaltungen
+	aliases: ...
 
 	# definiert die Regeln für die Auflösung des Presenter-Namens in eine Klasse
 	mapping: ...
@@ -27,10 +31,19 @@ Anwendung:
 	silentLinks: ...        # (bool) ist standardmäßig auf false eingestellt
 ```
 
-Da Fehlerpräsenter im Entwicklungsmodus standardmäßig nicht aufgerufen werden und die Fehler von Tracy angezeigt werden, hilft das Ändern des Wertes `catchExceptions` in `true` dabei, zu überprüfen, ob die Fehlerpräsenter während der Entwicklung korrekt funktionieren.
+Ab `nette/application` Version 3.2 ist es möglich, ein Paar von Fehlerpräsentern zu definieren:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # für Nette\Application\BadRequestException
+		5xx: Error5xx   # für andere Ausnahmen
+```
 
 Die Option `silentLinks` legt fest, wie sich Nette im Entwicklermodus verhält, wenn die Link-Generierung fehlschlägt (z. B. weil kein Presenter vorhanden ist usw.). Der Standardwert `false` bedeutet, dass Nette `E_USER_WARNING` auslöst. Die Einstellung `true` unterdrückt diese Fehlermeldung. In einer Produktionsumgebung wird immer `E_USER_WARNING` aufgerufen. Wir können dieses Verhalten auch beeinflussen, indem wir die Presenter-Variable [$invalidLinkMode |creating-links#Invalid Links] setzen.
 
+[Aliasnamen vereinfachen das Aufsuchen |creating-links#aliases] häufig verwendeter Moderatoren.
+
 Das [Mapping definiert die Regeln |modules#mapping], nach denen der Klassenname aus dem Presenter-Namen abgeleitet wird.
 
 
@@ -82,6 +95,9 @@ Latte:
 	# aktiviert die [Überprüfung von generiertem Code |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) Voreinstellung ist null
 
+	# legt das Gebietsschema fest
+	locale: cs_CZ        # (string) Voreinstellung ist null
+
 	# Klasse von $this->template
 	templateClass: App\MyTemplateClass # Standardwert ist Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Wenn Sie Latte Version 3 verwenden, können Sie neue [Erweiterungen |latte:creat
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/de/creating-links.texy b/application/de/creating-links.texy
index 1ec3fbd1e9..2b5a91f73d 100644
--- a/application/de/creating-links.texy
+++ b/application/de/creating-links.texy
@@ -38,7 +38,7 @@ Es ist auch möglich, benannte Parameter zu übergeben. Der folgende Link überg
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Wenn die Methode `ProductPresenter::renderShow()` nicht `$lang` in ihrer Signatur hat, kann sie den Wert des Parameters mit `$lang = $this->getParameter('lang')` lesen.
+Wenn die Methode `ProductPresenter::renderShow()` nicht `$lang` in ihrer Signatur hat, kann sie den Wert des Parameters über `$lang = $this->getParameter('lang')` oder über die [Eigenschaft |presenters#Request Parameters] abrufen.
 
 Wenn die Parameter in einem Array gespeichert sind, können sie mit dem `...` -Operator (oder `(expand)` -Operator in Latte 2.x) expandiert werden:
 
@@ -140,7 +140,7 @@ Das Ziel `this` wird einen Link zur aktuellen Seite erstellen:
 <a n:href="this">refresh</a>
 ```
 
-Gleichzeitig werden alle Parameter, die in der Signatur des Befehls `render<View>()` oder `action<Action>()` Methode angegeben sind, übertragen. Wenn wir uns also auf den Seiten `Product:show` und `id:123` befinden, wird der Link zu `this` auch diesen Parameter übergeben.
+Gleichzeitig werden alle Parameter, die in der Signatur des Befehls `action<Action>()` oder `render<View>()` Methode angegebenen Parameter, wenn die `action<Action>()` nicht definiert ist, übertragen. Wenn wir uns also auf den Seiten `Product:show` und `id:123` befinden, wird der Link zu `this` auch diesen Parameter übergeben.
 
 Natürlich ist es auch möglich, die Parameter direkt anzugeben:
 
@@ -213,7 +213,7 @@ Da [Komponenten |components] separate, wiederverwendbare Einheiten sind, die kei
 Wenn wir auf Präsentatoren in der Komponentenvorlage verlinken wollen, verwenden wir das Tag `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 oder im Code
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Aliasnamen .[#toc-aliases]{data-version:v3.2.2}
+===============================================
+
+Manchmal ist es sinnvoll, einem Presenter:Action-Paar einen leicht zu merkenden Alias zuzuweisen. Zum Beispiel könnten Sie die Homepage `Front:Home:default` einfach als `home` oder `Admin:Dashboard:default` als `admin` benennen.
+
+Aliasnamen werden in der [Konfiguration |configuration] unter dem Schlüssel `application › aliases` definiert:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+In Links werden sie mit dem at-Symbol geschrieben, zum Beispiel:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Sie werden in allen Methoden unterstützt, die mit Links arbeiten, wie `redirect()` und ähnliche.
+
+
 Ungültige Links .[#toc-invalid-links]
 =====================================
 
diff --git a/application/de/how-it-works.texy b/application/de/how-it-works.texy
index 3ac55697e4..fde1735364 100644
--- a/application/de/how-it-works.texy
+++ b/application/de/how-it-works.texy
@@ -22,18 +22,18 @@ Die Verzeichnisstruktur sieht in etwa so aus:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← Verzeichnis mit Anwendung
-│   ├── <b>Presenters/</b>           ← Presenter-Klassen
-│   │   ├── <b>HomePresenter.php</b> ← Home presenterklasse
-│   │   └── <b>templates/</b>        ← Vorlagenverzeichnis
-│   │       ├── <b>@layout.latte</b> ← Vorlage für gemeinsames Layout
-│   │       └── <b>Home/</b>         ← Vorlagen für Home-presenter
-│   │           └── <b>default.latte</b>  ← Vorlage für Aktion `default`
-│   ├── <b>Router/</b>               ← Konfiguration von URL-Adressen
+│   ├── <b>Core/</b>                 ← grundlegende notwendige Klassen
+│   │   └── <b>RouterFactory.php</b> ← Konfiguration der URL-Adressen
+│   ├── <b>UI/</b>                   ← Moderatoren, Vorlagen & Co.
+│   │   ├── <b>@layout.latte</b>     ← Vorlage für gemeinsames Layout
+│   │   └── <b>Home/</b>             ← Home Presenter Verzeichnis
+│   │       ├── <b>HomePresenter.php</b> ← Home Presenter Klasse
+│   │       └── <b>default.latte</b> ← Vorlage für Aktion default
 │   └── <b>Bootstrap.php</b>         ← bootende Klasse Bootstrap
 ├── <b>bin/</b>                      ← Skripte für die Kommandozeile
 ├── <b>config/</b>                   ← Konfigurationsdateien
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← Fehlerprotokolle
 ├── <b>temp/</b>                     ← temporäre Dateien, Cache, …
 ├── <b>vendor/</b>                   ← vom Composer installierte Bibliotheken
@@ -91,7 +91,7 @@ In Nette geschriebene Anwendungen sind in viele so genannte Presenter unterteilt
 
 Die Anwendung beginnt damit, dass sie den so genannten Router bittet, zu entscheiden, an welchen der Presenter die aktuelle Anfrage zur Bearbeitung weitergeleitet werden soll. Der Router entscheidet, wer dafür zuständig ist. Er sieht sich die Eingabe-URL `https://example.com/product/123` handelt, der ein Produkt mit `id: 123` als Aktion an `show` weiterleiten möchte. Es ist eine gute Angewohnheit, ein durch einen Doppelpunkt getrenntes Paar aus Präsentator + Aktion als `Product:show` zu schreiben.
 
-Der Router verwandelt also die URL in ein Paar `Presenter:action` + Parameter, in unserem Fall `Product:show` + `id: 123`. Sie können sehen, wie ein Router in der Datei `app/Router/RouterFactory.php` aussieht, und wir werden ihn im Kapitel [Routing] ausführlich beschreiben.
+Der Router verwandelt also die URL in ein Paar `Presenter:action` + Parameter, in unserem Fall `Product:show` + `id: 123`. Sie können sehen, wie ein Router in der Datei `app/Core/RouterFactory.php` aussieht, und wir werden ihn im Kapitel [Routing] ausführlich beschreiben.
 
 Machen wir weiter. Die Anwendung kennt bereits den Namen des Präsentators und kann fortfahren. Sie erstellt ein Objekt `ProductPresenter`, das den Code des Presenters `Product` darstellt. Genauer gesagt, sie bittet den DI-Container um die Erstellung des Presenters, denn die Erstellung von Objekten ist seine Aufgabe.
 
@@ -121,12 +121,9 @@ So wurde die Methode `renderShow(123)` aufgerufen, deren Code ein fiktives Beisp
 
 Anschließend gibt der Präsentator die Antwort zurück. Dies kann eine HTML-Seite, ein Bild, ein XML-Dokument, das Senden einer Datei von der Festplatte, JSON oder die Routing zu einer anderen Seite sein. Wichtig ist, dass, wenn wir nicht ausdrücklich sagen, wie zu antworten ist (was bei `ProductPresenter` der Fall ist), die Antwort darin besteht, die Vorlage mit einer HTML-Seite wiederzugeben. Und warum? Nun, weil wir in 99 % der Fälle eine Vorlage zeichnen wollen, so dass der Präsentator dieses Verhalten als Standard annimmt und uns die Arbeit erleichtern will. Das ist der Punkt von Nette.
 
-Wir müssen nicht einmal angeben, welche Vorlage gezeichnet werden soll, er leitet den Pfad dorthin nach einer einfachen Logik ab. Im Fall von presenter `Product` und action `show` versucht er zu sehen, ob eine dieser Vorlagendateien relativ zu dem Verzeichnis existiert, in dem sich die Klasse `ProductPresenter` befindet:
+Wir müssen nicht einmal angeben, welche Vorlage gerendert werden soll; das Framework wird den Pfad selbst ermitteln. Im Fall der Aktion `show` versucht es einfach, die Vorlage `show.latte` im Verzeichnis mit der Klasse `ProductPresenter` zu laden. Es versucht auch, das Layout in der Datei `@layout.latte` zu finden (mehr über die [Vorlagensuche |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Außerdem wird versucht, das Layout in der Datei `@layout.latte` zu finden, und dann wird die Vorlage gerendert. Nun ist die Aufgabe des Präsentators und der gesamten Anwendung abgeschlossen. Wenn die Vorlage nicht existiert, wird eine Seite mit dem Fehler 404 zurückgegeben. Weitere Informationen über Präsentatoren finden Sie auf der Seite [Präsentatoren |Presenters].
+Anschließend werden die Vorlagen gerendert. Damit ist die Aufgabe des Präsentators und der gesamten Anwendung abgeschlossen, und die Arbeit ist getan. Wenn die Vorlage nicht vorhanden wäre, würde eine 404-Fehlerseite zurückgegeben werden. Weitere Informationen über Präsentatoren finden Sie auf der Seite [Präsentatoren |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Um sicherzugehen, versuchen wir, den gesamten Prozess mit einer etwas anderen UR
 3) der Router dekodiert die URL als ein Paar `Home:default`
 4) ein `HomePresenter` Objekt wird erstellt
 5) die Methode `renderDefault()` wird aufgerufen (falls vorhanden)
-6) eine Vorlage `templates/Home/default.latte` mit einem Layout `templates/@layout.latte` wird gerendert
+6) eine Vorlage `default.latte` mit einem Layout `@layout.latte` wird gerendert
 
 
 Vielleicht sind Sie jetzt auf eine Menge neuer Konzepte gestoßen, aber wir glauben, dass sie sinnvoll sind. Das Erstellen von Anwendungen in Nette ist ein Kinderspiel.
diff --git a/application/de/modules.texy b/application/de/modules.texy
index fcdf4331c4..75981ac23a 100644
--- a/application/de/modules.texy
+++ b/application/de/modules.texy
@@ -2,29 +2,31 @@ Module
 ******
 
 .[perex]
-In Nette stellen Module die logischen Einheiten dar, aus denen eine Anwendung besteht. Sie umfassen Presenter, Templates, eventuell auch Komponenten und Modellklassen.
+Module bringen Klarheit in Nette-Anwendungen, indem sie eine einfache Unterteilung in logische Einheiten ermöglichen.
 
-Ein Verzeichnis für Presenter und eines für Templates würde für echte Projekte nicht ausreichen. Dutzende von Dateien in einem Ordner zu haben, ist zumindest unorganisiert. Wie kommt man da wieder raus? Wir teilen sie einfach in Unterverzeichnisse auf der Festplatte und in Namensräume im Code auf. Und das ist genau das, was die Nette-Module tun.
-
-Vergessen wir also einen einzigen Ordner für Präsentatoren und Vorlagen und erstellen wir stattdessen Module, zum Beispiel `Admin` und `Front`.
+Ähnlich wie bei der Organisation von Dateien in Ordnern auf einer Festplatte, können wir in Nette Presenter, Vorlagen und andere Hilfsklassen in Module unterteilen. Wie funktioniert das in der Praxis? Ganz einfach, indem man neue Unterverzeichnisse in die Struktur einfügt. Hier ist ein Beispiel für eine Struktur mit zwei Modulen, Front und Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← Verzeichnis mit Modulen
-│   ├── <b>Admin/</b>            ← Modul Admin
-│   │   ├── <b>Presenters/</b>   ← seine Presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← Modul Front
-│       └── <b>Presenters/</b>   ← seine Presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Diese Verzeichnisstruktur spiegelt sich in den Klassennamensräumen wider, so dass z. B. `DashboardPresenter` im Namensraum `App\Modules\Admin\Presenters` liegt:
+Diese Verzeichnisstruktur spiegelt sich in den Namespaces der Klassen wider, so befindet sich z.B. `DashboardPresenter` im Namespace `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Der Präsentator `Dashboard` innerhalb des Moduls `Admin` wird innerhalb der Anwendung mit der Doppelpunktschreibweise als `Admin:Dashboard` referenziert, und seine Aktion `default` als `Admin:Dashboard:default`.
-Und woher weiß Nette selbst, dass `Admin:Dashboard` die Klasse `App\Modules\Admin\Presenters\DashboardPresenter` repräsentiert? Dies wird durch ein [Mapping |#mapping] in der Konfiguration festgelegt.
-Die vorgegebene Struktur ist also nicht fest vorgegeben und kann nach Belieben verändert werden.
+In der Anwendung wird der Presenter `Dashboard` innerhalb des Moduls `Admin` mit Doppelpunkt als `Admin:Dashboard` bezeichnet. Für die Aktion `default` wird er als `Admin:Dashboard:default` bezeichnet.
+
+Die vorgestellte Struktur ist nicht starr; Sie können [sie |#mapping] in der Konfiguration [vollständig an Ihre Bedürfnisse anpassen |#mapping]. .[tip]
 
-Module können neben Presentern und Templates natürlich auch alle anderen Elemente enthalten, wie z.B. Komponenten, Modellklassen, etc.
+Module können neben Presentern und Vorlagen auch alle anderen Dateien, wie Komponenten und Hilfsklassen, enthalten. Wenn Sie überlegen, wo Sie diese ablegen wollen, sollten Sie einen Ordner `Accessory` verwenden:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Verschachtelte Module .[#toc-nested-modules]
 --------------------------------------------
 
-Module müssen nicht nur eine flache Struktur bilden, Sie können auch Untermodule erstellen, zum Beispiel:
+Module können mehrere Verschachtelungsebenen haben, ähnlich wie eine Verzeichnisstruktur auf einer Festplatte:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← Verzeichnis mit Modulen
-│   ├── <b>Blog/</b>             ← Modul Blog
-│   │   ├── <b>Admin/</b>        ← Submodul Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← Submodul Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← Modul Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-So wird das Modul `Blog` in die Untermodule `Admin` und `Front` aufgeteilt. Dies spiegelt sich auch in den Namensräumen wider, die dann `App\Modules\Blog\Admin\Presenters` usw. lauten. Der Präsentator `Dashboard` innerhalb des Submoduls wird als `Blog:Admin:Dashboard` bezeichnet.
+Das Modul `Blog` ist in die Untermodule `Admin` und `Front` unterteilt. Dies spiegelt sich auch in den Namespaces wider, die dann als `App\UI\Blog\Admin` und ähnlich erscheinen. Um auf den Präsentator `Dashboard` innerhalb des Submoduls `Admin` zu verweisen, wird er als `Blog:Admin:Dashboard` bezeichnet.
+
+Die Verschachtelung kann so tief wie nötig sein und erlaubt die Erstellung von Sub-Submodulen.
 
-Die Verschachtelung kann beliebig tief gehen, so dass Sub-Submodule erstellt werden können.
+Wenn Sie zum Beispiel in der Verwaltung viele Präsentatoren haben, die mit der Auftragsverwaltung zusammenhängen, wie `OrderDetail`, `OrderEdit`, `OrderDispatch`, usw., könnten Sie ein `Order` Modul erstellen, in dem Präsentatoren wie `Detail`, `Edit`, `Dispatch` und andere organisiert werden.
 
 
 Erstellen von Links .[#toc-creating-links]
@@ -99,50 +115,69 @@ Routing .[#toc-routing]
 Siehe [Kapitel über Routing |routing#Modules].
 
 
-Abbildung .[#toc-mapping]
--------------------------
+Kartierung .[#toc-mapping]
+--------------------------
 
-Legt die Regeln fest, nach denen der Klassenname aus dem Namen des Präsentators abgeleitet wird. Wir schreiben sie in die [Konfiguration |configuration] unter dem Schlüssel `application › mapping`.
+Mapping definiert die Regeln für die Ableitung des Klassennamens aus dem Presenter-Namen. Diese Regeln werden in der [Konfiguration |configuration] unter dem Schlüssel `application › mapping` angegeben.
 
-Beginnen wir mit einem Beispiel, das keine Module verwendet. Wir wollen nur, dass die Presenter-Klassen den Namespace `App\Presenters` haben. Das bedeutet, dass ein Presenter wie `Home` auf die Klasse `App\Presenters\HomePresenter` abgebildet werden soll. Dies kann durch die folgende Konfiguration erreicht werden:
+Die oben auf dieser Seite erwähnten Verzeichnisstrukturen basieren auf der folgenden Zuordnung:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Der Name des Presenters wird durch das Sternchen in der Klassenmaske ersetzt und das Ergebnis ist der Klassenname. Einfach!
+Wie funktioniert das Mapping? Zum besseren Verständnis stellen wir uns zunächst eine Anwendung ohne Module vor. Wir wollen, dass die Presenter-Klassen in den Namensraum `App\UI` fallen, so dass der Presenter `Home` auf die Klasse `App\UI\HomePresenter` abgebildet wird. Dies kann mit dieser Konfiguration erreicht werden:
 
-Wenn wir die Vortragenden in Module unterteilen, können wir für jedes Modul eine eigene Zuordnung vornehmen:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Diese Zuordnung funktioniert, indem das Sternchen in der Maske `App\UI\*Presenter` durch den Presenter-Namen `Home` ersetzt wird, was zu dem endgültigen Klassennamen `App\UI\HomePresenter` führt. Einfach!
+
+Wie Sie jedoch in den Beispielen in diesem und anderen Kapiteln sehen können, platzieren wir Presenter-Klassen in gleichnamigen Unterverzeichnissen, z. B. wird der Presenter `Home` der Klasse `App\UI\Home\HomePresenter` zugeordnet. Dies wird durch die Verdoppelung des Sternchens erreicht (erfordert Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Gehen wir nun dazu über, Presenter in Modulen abzubilden. Für jedes Modul können wir spezifische Zuordnungen definieren:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Der Referent `Front:Home` wird der Klasse `App\Modules\Front\Presenters\HomePresenter` zugeordnet und der Referent `Admin:Dashboard` der Klasse `App\Modules\Admin\Presenters\DashboardPresenter`.
+Nach dieser Konfiguration wird der Präsentator `Front:Home` der Klasse `App\UI\Front\Home\HomePresenter` zugeordnet, während der Präsentator `Api:OAuth` der Klasse `App\Api\OAuthPresenter` zugeordnet wird.
 
-Es ist praktischer, eine allgemeine (Stern-)Regel zu erstellen, um die ersten beiden zu ersetzen. Das zusätzliche Sternchen wird der Klassenmaske nur für dieses Modul hinzugefügt:
+Da die Module `Front` und `Admin` einen ähnlichen Zuordnungsansatz haben und es wahrscheinlich noch mehr solcher Module gibt, ist es möglich, eine allgemeine Regel zu erstellen, die sie ersetzt. In der Klassenmaske wird ein neues Sternchen für das Modul hinzugefügt:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Was aber, wenn wir verschachtelte Module verwenden und einen Präsentator `Admin:User:Edit` haben? In diesem Fall wird das Segment mit dem Sternchen, das das Modul für jede Ebene darstellt, einfach wiederholt und das Ergebnis ist die Klasse `App\Modules\Admin\User\Presenters\EditPresenter`.
+Bei mehrstufig verschachtelten Modulen, wie z. B. dem Moderator `Admin:User:Edit`, wird das Sternchen-Segment für jede Stufe wiederholt, was zu der Klasse `App\UI\Admin\User\Edit\EditPresenter` führt.
 
-Eine alternative Schreibweise ist die Verwendung eines Arrays, das aus drei Segmenten anstelle einer Zeichenkette besteht. Diese Notation ist gleichwertig mit der vorherigen:
+Eine alternative Schreibweise ist die Verwendung eines Arrays, das aus drei Segmenten besteht, anstelle einer Zeichenkette. Diese Notation ist äquivalent zur vorherigen:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Der Standardwert ist `*: *Module\*Presenter`.
+Wenn wir nur eine Regel in der Konfiguration haben, die allgemeine, können wir kurz schreiben:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/de/presenters.texy b/application/de/presenters.texy
index 35bc4c3513..8622224006 100644
--- a/application/de/presenters.texy
+++ b/application/de/presenters.texy
@@ -60,7 +60,7 @@ Unmittelbar nach Erhalt der Anfrage wird die Methode `startup ()` aufgerufen. Si
 
 Es ist wichtig, dass `action<Action>()` vor aufgerufen wird `render<View>()`aufgerufen wird, damit wir darin möglicherweise den weiteren Verlauf des Lebenszyklus ändern können, d. h. die Vorlage, die gerendert wird, und auch die Methode `render<View>()` die aufgerufen wird, mit `setView('otherView')`.
 
-Die Parameter der Anfrage werden an die Methode übergeben. Es ist möglich und empfehlenswert, Typen für die Parameter anzugeben, z. B. `actionShow(int $id, string $slug = null)` - wenn der Parameter `id` fehlt oder keine ganze Zahl ist, gibt der Präsentator den [Fehler 404 |#Error 404 etc.] zurück und bricht die Operation ab.
+Die Parameter der Anfrage werden an die Methode übergeben. Es ist möglich und empfehlenswert, Typen für die Parameter anzugeben, z. B. `actionShow(int $id, ?string $slug = null)` - wenn der Parameter `id` fehlt oder keine ganze Zahl ist, gibt der Präsentator den [Fehler 404 |#Error 404 etc.] zurück und bricht die Operation ab.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ In der Vorlage sind diese Meldungen in der Variablen `$flashes` als Objekte `std
 Fehler 404 usw. .[#toc-error-404-etc]
 =====================================
 
-Wenn wir die Anfrage nicht erfüllen können, weil z.B. der Artikel, den wir anzeigen wollen, nicht in der Datenbank existiert, werden wir den Fehler 404 mit der Methode `error(string $message = null, int $httpCode = 404)` ausgeben, die den HTTP-Fehler 404 darstellt:
+Wenn wir die Anfrage nicht erfüllen können, weil z.B. der Artikel, den wir anzeigen wollen, nicht in der Datenbank existiert, werden wir den Fehler 404 mit der Methode `error(?string $message = null, int $httpCode = 404)` ausgeben, die den HTTP-Fehler 404 darstellt:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parameter anfordern .[#toc-request-parameters]
+==============================================
+
+Der Präsentator, wie auch jede Komponente, bezieht seine Parameter aus der HTTP-Anfrage. Ihre Werte können mit der Methode `getParameter($name)` oder `getParameters()` abgerufen werden. Bei den Werten handelt es sich um Strings oder Arrays von Strings, also im Wesentlichen um Rohdaten, die direkt aus der URL bezogen werden.
+
+Für zusätzlichen Komfort empfiehlt es sich, die Parameter über Eigenschaften zugänglich zu machen. Beschriften Sie sie einfach mit dem `#[Parameter]` Attribut:
+
+```php
+use Nette\Application\Attributes\Parameter;  // diese Zeile ist wichtig
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // muss öffentlich sein
+}
+```
+
+Für Eigenschaften empfehlen wir die Angabe des Datentyps (z. B. `string`). Nette wird den Wert dann automatisch auf der Grundlage dieses Typs umwandeln. Parameterwerte können auch [validiert |#Validation of Parameters] werden.
+
+Beim Erstellen einer Verknüpfung können Sie den Wert für die Parameter direkt festlegen:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Dauerhafte Parameter .[#toc-persistent-parameters]
 ==================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Wenn `$this->lang` einen Wert wie `'en'` hat, dann werden Links, die mit `link()` oder `n:href` erstellt werden, auch den Parameter `lang=en` enthalten. Und wenn der Link angeklickt wird, wird er wieder `$this->lang = 'en'` sein.
 
-Für Eigenschaften wird empfohlen, den Datentyp anzugeben (z. B. `string`), und Sie können auch einen Standardwert angeben. Parameterwerte können [validiert |#Validation of Persistent Parameters] werden.
+Für Eigenschaften wird empfohlen, den Datentyp anzugeben (z. B. `string`), und Sie können auch einen Standardwert angeben. Parameterwerte können [validiert |#Validation of Parameters] werden.
 
 Persistente Parameter werden standardmäßig zwischen allen Aktionen eines bestimmten Präsentators weitergegeben. Um sie zwischen mehreren Präsentatoren zu übergeben, müssen Sie sie entweder definieren:
 
@@ -307,18 +333,12 @@ Tiefer gehen .[#toc-going-deeper]
 Was wir bisher in diesem Kapitel gezeigt haben, wird wahrscheinlich ausreichen. Die folgenden Zeilen sind für diejenigen gedacht, die sich eingehend mit Moderatoren beschäftigen und alles wissen wollen.
 
 
-Anforderung und Parameter .[#toc-requirement-and-parameters]
-------------------------------------------------------------
-
-Die vom Präsentator bearbeitete Anfrage ist das Objekt [api:Nette\Application\Request] und wird von der Methode `getRequest()` des Präsentators zurückgegeben. Sie enthält ein Array von Parametern, und jeder von ihnen gehört entweder zu einer der Komponenten oder direkt zum Präsentator (der eigentlich auch eine Komponente ist, wenn auch eine spezielle). Nette verteilt also die Parameter um und übergibt sie zwischen den einzelnen Komponenten (und dem Präsentator) durch Aufruf der Methode `loadState(array $params)`. Die Parameter können mit der Methode `getParameters(): array`, einzeln mit `getParameter($name)` abgerufen werden. Bei den Parameterwerten handelt es sich um Strings oder Arrays von Strings, also im Grunde um Rohdaten, die direkt aus einer URL bezogen werden.
+Validierung von Parametern .[#toc-validation-of-parameters]
+-----------------------------------------------------------
 
+Die Werte von [Anfrageparametern |#request parameters] und [dauerhaften Parametern |#persistent parameters], die von URLs empfangen werden, werden von der Methode `loadState()` in Eigenschaften geschrieben. Sie prüft auch, ob der in der Eigenschaft angegebene Datentyp übereinstimmt, andernfalls antwortet sie mit einem 404-Fehler und die Seite wird nicht angezeigt.
 
-Validierung von persistenten Parametern .[#toc-validation-of-persistent-parameters]
------------------------------------------------------------------------------------
-
-Die Werte von [persistenten Parametern |#persistent parameters], die von URLs empfangen werden, werden von der Methode `loadState()` in Eigenschaften geschrieben. Sie prüft auch, ob der in der Eigenschaft angegebene Datentyp übereinstimmt, andernfalls antwortet sie mit einem 404-Fehler und die Seite wird nicht angezeigt.
-
-Verlassen Sie sich niemals blind auf persistente Parameter, da sie leicht vom Benutzer in der URL überschrieben werden können. So überprüfen wir zum Beispiel, ob `$this->lang` zu den unterstützten Sprachen gehört. Eine gute Möglichkeit, dies zu tun, besteht darin, die oben erwähnte Methode `loadState()` zu überschreiben:
+Verlassen Sie sich niemals blind auf Parameter, da sie leicht vom Benutzer in der URL überschrieben werden können. So überprüfen wir zum Beispiel, ob `$this->lang` zu den unterstützten Sprachen gehört. Eine gute Möglichkeit, dies zu tun, besteht darin, die oben erwähnte Methode `loadState()` zu überschreiben:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Speichern und Wiederherstellen der Anfrage .[#toc-save-and-restore-the-request]
 -------------------------------------------------------------------------------
 
-Sie können die aktuelle Anfrage in einer Session speichern oder sie aus der Session wiederherstellen und den Präsentator sie erneut ausführen lassen. Dies ist z. B. nützlich, wenn ein Benutzer ein Formular ausfüllt und seine Anmeldung abläuft. Um keine Daten zu verlieren, speichern wir vor der Routing zur Anmeldeseite die aktuelle Anfrage in der Session mit `$reqId = $this->storeRequest()`, die einen Bezeichner in Form einer kurzen Zeichenkette zurückgibt und ihn als Parameter an den Anmeldepräsentator übergibt.
+Die Anfrage, die der Präsentator bearbeitet, ist ein Objekt [api:Nette\Application\Request] und wird von der Methode `getRequest()` des Präsentators zurückgegeben.
+
+Sie können die aktuelle Anfrage in einer Sitzung speichern oder sie aus der Sitzung wiederherstellen und den Präsentator sie erneut ausführen lassen. Dies ist z. B. nützlich, wenn ein Benutzer ein Formular ausfüllt und sein Login abläuft. Um keine Daten zu verlieren, speichern wir vor der Weiterleitung zur Anmeldeseite die aktuelle Anfrage in der Sitzung mit `$reqId = $this->storeRequest()`, die einen Bezeichner in Form eines kurzen Strings zurückgibt und diesen als Parameter an den Anmeldepräsentator übergibt.
 
 Nach der Anmeldung rufen wir die Methode `$this->restoreRequest($reqId)` auf, die die Anfrage aus der Session abholt und an diese weiterleitet. Die Methode prüft, ob die Anfrage von demselben Benutzer erstellt wurde, der jetzt angemeldet ist. Wenn sich ein anderer Benutzer anmeldet oder der Schlüssel ungültig ist, tut sie nichts und das Programm läuft weiter.
 
@@ -362,7 +384,7 @@ Eine Umleitung findet bei einer AJAX- oder POST-Anfrage nicht statt, da dies zu
 Sie können die Kanonisierung auch manuell mit der Methode `canonicalize()` aufrufen, die wie die Methode `link()` den Präsentator, Aktionen und Parameter als Argumente erhält. Sie erstellt einen Link und vergleicht ihn mit der aktuellen URL. Wenn sie sich unterscheidet, wird sie auf den erzeugten Link umgeleitet.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// leitet um, wenn $slug nicht mit $realSlug übereinstimmt
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Zugangsbeschränkung mit `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+---------------------------------------------------------------------------------------------------
+
+Das Attribut `#[Requires]` Attribut bietet erweiterte Optionen zur Einschränkung des Zugriffs auf Präsentatoren und ihre Methoden. Es kann verwendet werden, um HTTP-Methoden zu spezifizieren, AJAX-Anfragen zu verlangen, den Zugriff auf denselben Ursprung zu beschränken und den Zugriff nur auf Weiterleitungen zu beschränken. Das Attribut kann sowohl auf Presenter-Klassen als auch auf einzelne Methoden angewendet werden, z. B. `action<Action>()`, `render<View>()`, `handle<Signal>()`, und `createComponent<Name>()`.
+
+Sie können diese Einschränkungen angeben:
+- auf HTTP-Methoden: `#[Requires(methods: ['GET', 'POST'])]`
+- die eine AJAX-Anfrage erfordern: `#[Requires(ajax: true)]`
+- Zugriff nur vom selben Ursprung: `#[Requires(sameOrigin: true)]`
+- Zugriff nur über Weiterleitung: `#[Requires(forward: true)]`
+- Einschränkungen für bestimmte Aktionen: `#[Requires(actions: 'default')]`
+
+Für Einzelheiten siehe [Verwendung des Requires Attributs |best-practices:attribute-requires].
+
+
+HTTP-Methodenprüfung .[#toc-http-method-check]
+----------------------------------------------
+
+In Nette überprüfen die Moderatoren die HTTP-Methode jeder eingehenden Anfrage automatisch, hauptsächlich aus Sicherheitsgründen. Standardmäßig sind die Methoden `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` zugelassen.
+
+Wenn Sie zusätzliche Methoden wie `OPTIONS` aktivieren möchten, können Sie das `#[Requires]` Attribut verwenden (ab Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+In Version 3.1 wird die Überprüfung in `checkHttpMethod()` durchgeführt, das prüft, ob die in der Anfrage angegebene Methode im Array `$presenter->allowedMethods` enthalten ist. Fügen Sie eine Methode wie diese hinzu:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Es ist wichtig zu betonen, dass, wenn Sie die `OPTIONS` -Methode zulassen, Sie sie auch in Ihrem Präsentator richtig behandeln müssen. Diese Methode wird häufig als so genannte Preflight-Anfrage verwendet, die von Browsern automatisch vor der eigentlichen Anfrage gesendet wird, wenn es darum geht, festzustellen, ob die Anfrage aus Sicht der CORS-Richtlinie (Cross-Origin Resource Sharing) zulässig ist. Wenn Sie diese Methode zulassen, aber keine angemessene Antwort implementieren, kann dies zu Inkonsistenzen und potenziellen Sicherheitsproblemen führen.
+
+
 Weitere Lektüre .[#toc-further-reading]
 =======================================
 
diff --git a/application/de/routing.texy b/application/de/routing.texy
index dac42c271d..f3b4ae88de 100644
--- a/application/de/routing.texy
+++ b/application/de/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Erweiterte Notation .[#toc-advanced-notation]
 ---------------------------------------------
 
-Der zweite Parameter der Route, den wir oft im Format `Presenter:action` schreiben, ist eine Abkürzung, die wir auch in Form eines Feldes schreiben können, in dem wir die (Standard-)Werte der einzelnen Parameter direkt angeben:
+Das Ziel einer Route, in der Regel in der Form `Presenter:action` geschrieben, kann auch durch ein Array ausgedrückt werden, das einzelne Parameter und ihre Standardwerte definiert:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Oder wir können diese Form verwenden, beachten Sie die Umschreibung des regulären Ausdrucks für die Validierung:
+Für eine detailliertere Spezifikation kann eine noch umfangreichere Form verwendet werden, bei der zusätzlich zu den Standardwerten weitere Parametereigenschaften festgelegt werden können, wie z. B. ein regulärer Ausdruck für die Validierung (siehe den Parameter `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Diese gesprächigeren Formate sind nützlich, um andere Metadaten hinzuzufügen.
+Es ist wichtig zu beachten, dass, wenn die im Array definierten Parameter nicht in der Pfadmaske enthalten sind, ihre Werte nicht geändert werden können, auch nicht mit Abfrageparametern, die nach einem Fragezeichen in der URL angegeben werden.
 
 
 Filter und Übersetzungen .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Einbindung .[#toc-integration]
 ==============================
 
-Um unseren Router in die Anwendung einzubinden, müssen wir ihn dem DI-Container mitteilen. Am einfachsten ist es, die Fabrik vorzubereiten, die das Router-Objekt erstellt, und der Container-Konfiguration mitzuteilen, dass sie es verwenden soll. Schreiben wir also eine Methode für diesen Zweck `App\Router\RouterFactory::createRouter()`:
+Um unseren Router in die Anwendung einzubinden, müssen wir ihn dem DI-Container mitteilen. Am einfachsten ist es, die Fabrik vorzubereiten, die das Router-Objekt erstellt, und der Container-Konfiguration mitzuteilen, dass sie es verwenden soll. Schreiben wir also eine Methode für diesen Zweck `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Dann schreiben wir in [configuration |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Alle Abhängigkeiten, wie z. B. eine Datenbankverbindung usw., werden der Factory-Methode als Parameter über [Autowiring |dependency-injection:autowiring] übergeben:
@@ -663,7 +663,7 @@ Unter getrennter Nutzung verstehen wir die Verwendung der Router-Funktionen in e
 Wir werden also wieder eine Methode erstellen, die einen Router aufbaut, zum Beispiel:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Oder wir erstellen die Objekte direkt:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/de/templates.texy b/application/de/templates.texy
index a21bd7266f..466cb501c3 100644
--- a/application/de/templates.texy
+++ b/application/de/templates.texy
@@ -34,35 +34,81 @@ Und dies könnte die Aktionsvorlage sein:
 Sie definiert den Block `content`, der anstelle von `{include content}` in das Layout eingefügt wird, und definiert auch den Block `title` neu, der `{block title}` im Layout überschreibt. Versuchen Sie, sich das Ergebnis vorzustellen.
 
 
-Suche nach Templates .[#toc-search-for-templates]
--------------------------------------------------
+Vorlage nachschlagen .[#toc-template-lookup]
+--------------------------------------------
+
+In Presentern müssen Sie nicht angeben, welche Vorlage gerendert werden soll; das Framework bestimmt den Pfad automatisch, was die Codierung für Sie einfacher macht.
+
+Wenn Sie eine Verzeichnisstruktur verwenden, in der jeder Präsentator sein eigenes Verzeichnis hat, legen Sie die Vorlage einfach in diesem Verzeichnis unter dem Namen der Aktion (d. h. der Ansicht) ab. Verwenden Sie zum Beispiel für die Aktion `default` die Vorlage `default.latte`:
 
-Der Pfad zu den Vorlagen wird nach einer einfachen Logik hergeleitet. Es wird versucht zu sehen, ob eine dieser Vorlagendateien relativ zu dem Verzeichnis existiert, in dem sich die Presenter-Klasse befindet, wobei `<Presenter>` der Name des aktuellen Präsentators ist und `<view>` der Name der aktuellen Aktion ist:
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Wenn Sie eine Struktur verwenden, bei der sich die Präsentatoren in einem Verzeichnis und die Vorlagen in einem Ordner `templates` befinden, speichern Sie sie entweder in einer Datei `<Presenter>.<view>.latte` oder `<Presenter>/<view>.latte`:
 
-Wird die Vorlage nicht gefunden, wird versucht, im Verzeichnis `templates` eine Ebene höher zu suchen, d. h. auf der gleichen Ebene wie das Verzeichnis mit der Presenter-Klasse.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
 
-Wenn die Vorlage auch dort nicht gefunden wird, ist die Antwort ein [404-Fehler |presenters#Error 404 etc.].
+Das Verzeichnis `templates` kann auch eine Ebene höher platziert werden, auf derselben Ebene wie das Verzeichnis mit den Presenter-Klassen.
 
-Sie können die Ansicht auch mit `$this->setView('otherView')` ändern. Oder geben Sie statt der Suche direkt den Namen der Vorlagendatei mit `$this->template->setFile('/path/to/template.latte')` an.
+Wenn die Vorlage nicht gefunden wird, antwortet der Präsentator mit dem [Fehler 404 - Seite nicht gefunden |presenters#Error 404 etc].
+
+Sie können die Ansicht mit `$this->setView('anotherView')` ändern. Es ist auch möglich, die Vorlagendatei direkt mit `$this->template->setFile('/path/to/template.latte')` anzugeben.
 
 .[note]
-Sie können die Pfade, in denen Vorlagen gesucht werden, ändern, indem Sie die Methode [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] überschreiben, die ein Array mit möglichen Dateipfaden zurückgibt.
+Dateien, in denen Vorlagen gesucht werden, können durch Überschreiben der Methode [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()] geändert werden, die ein Array mit möglichen Dateinamen zurückgibt.
+
+
+Layout-Vorlagen-Suche .[#toc-layout-template-lookup]
+----------------------------------------------------
+
+Nette sucht auch automatisch nach der Layout-Datei.
+
+Wenn Sie eine Verzeichnisstruktur verwenden, in der jeder Präsentator sein eigenes Verzeichnis hat, legen Sie das Layout entweder in dem Ordner mit dem Präsentator ab, wenn es nur für diesen spezifisch ist, oder eine Ebene höher, wenn es für mehrere Präsentatoren gemeinsam ist:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Wenn Sie eine Struktur verwenden, bei der die Vortragenden in einem Verzeichnis zusammengefasst sind und sich die Vorlagen in einem Ordner `templates` befinden, wird das Layout an den folgenden Stellen erwartet:
 
-Das Layout wird in den folgenden Dateien erwartet:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` gemeinsames Layout für mehrere Präsentatoren
+Befindet sich der Präsentator in einem [Modul |modules], wird er auch weiter oben im Verzeichnisbaum entsprechend der Verschachtelung des Moduls gesucht.
 
-`<Presenter>` ist der Name des aktuellen Präsentators und `<layout>` ist der Name des Layouts, der standardmäßig `'layout'` lautet. Der Name kann mit `$this->setLayout('otherLayout')` geändert werden, so dass `@otherLayout.latte` Dateien ausprobiert werden.
+Der Name des Layouts kann mit `$this->setLayout('layoutAdmin')` geändert werden und wird dann in der Datei `@layoutAdmin.latte` erwartet. Sie können die Layout-Vorlagendatei auch direkt mit `$this->setLayout('/path/to/template.latte')` angeben.
 
-Sie können auch direkt den Dateinamen der Layoutvorlage mit `$this->setLayout('/path/to/template.latte')` angeben. Durch die Verwendung von `$this->setLayout(false)` wird die Layout-Suche deaktiviert.
+Die Verwendung von `$this->setLayout(false)` oder des Tags `{layout none}` innerhalb der Vorlage deaktiviert die Layout-Suche.
 
 .[note]
-Sie können die Pfade, in denen Vorlagen gesucht werden, ändern, indem Sie die Methode [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] überschreiben, die ein Array mit möglichen Dateipfaden zurückgibt.
+Die Dateien, in denen Layoutvorlagen gesucht werden, können durch Überschreiben der Methode [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] geändert werden, die ein Array mit möglichen Dateinamen zurückgibt.
 
 
 Variablen in der Vorlage .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ Die `@property-read` Annotation ist für die IDE und die statische Analyse, sie
 Sie können sich auch den Luxus gönnen, in Vorlagen zu flüstern. Installieren Sie einfach das Latte-Plugin in PhpStorm und geben Sie den Klassennamen am Anfang der Vorlage an, siehe den Artikel "Latte: how to type system":https://blog.nette.org/de/latte-wie-benutzt-man-das-typensystem:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte Version 3 bietet einen fortgeschritteneren Weg, indem es eine [Erweiterung |latte:creating-extension] für jedes Webprojekt erstellt. Hier ist ein grobes Beispiel für eine solche Klasse:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ Wir registrieren sie mit [configuration |configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternativ kann der Übersetzer auch über die [Konfiguration |configuration#Lat
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Der Übersetzer kann dann z.B. als Filter `|translate` verwendet werden, wobei zusätzliche Parameter an die Methode `translate()` übergeben werden (siehe `foo, bar`):
diff --git a/application/el/@home.texy b/application/el/@home.texy
index 8020e59b5f..9a733fd102 100644
--- a/application/el/@home.texy
+++ b/application/el/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | έκδοση | συμβατό με PHP
 |-----------|-------------------
-| Εφαρμογή Nette 4.0 | PHP 8.0 - 8.2
-| Nette Application 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/el/ajax.texy b/application/el/ajax.texy
index 8ca0741a48..ab0e2f48f5 100644
--- a/application/el/ajax.texy
+++ b/application/el/ajax.texy
@@ -3,10 +3,10 @@ AJAX & Snippets
 
 <div class=perex>
 
-Οι σύγχρονες διαδικτυακές εφαρμογές τρέχουν σήμερα κατά το ήμισυ σε έναν διακομιστή και κατά το ήμισυ σε ένα πρόγραμμα περιήγησης. Το AJAX είναι ένας ζωτικής σημασίας ενωτικός παράγοντας. Τι υποστήριξη προσφέρει το Nette Framework;
-- αποστολή τμημάτων προτύπου (τα λεγόμενα *snippets*)
-- μεταβίβαση μεταβλητών μεταξύ PHP και JavaScript
-- αποσφαλμάτωση εφαρμογών AJAX
+Στην εποχή των σύγχρονων διαδικτυακών εφαρμογών, όπου η λειτουργικότητα συχνά εκτείνεται μεταξύ του διακομιστή και του προγράμματος περιήγησης, το AJAX είναι ένα απαραίτητο συνδετικό στοιχείο. Ποιες επιλογές προσφέρει το Nette Framework σε αυτόν τον τομέα;
+- αποστολή τμημάτων του προτύπου, των λεγόμενων αποσπασμάτων
+- διαβίβαση μεταβλητών μεταξύ PHP και JavaScript
+- εργαλεία για την αποσφαλμάτωση αιτημάτων AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ AJAX & Snippets
 Αίτηση AJAX .[#toc-ajax-request]
 ================================
 
-Ένα αίτημα AJAX δεν διαφέρει από ένα κλασικό αίτημα - ο παρουσιαστής καλείται με μια συγκεκριμένη προβολή και παραμέτρους. Εξαρτάται επίσης από τον παρουσιαστή πώς θα απαντήσει σε αυτό: μπορεί να χρησιμοποιήσει τη δική του ρουτίνα, η οποία επιστρέφει ένα τμήμα κώδικα HTML (απόσπασμα HTML), ένα έγγραφο XML, ένα αντικείμενο JSON ή κώδικα JavaScript.
+Ένα αίτημα AJAX δεν διαφέρει ουσιαστικά από ένα κλασικό αίτημα HTTP. Ένας παρουσιαστής καλείται με συγκεκριμένες παραμέτρους. Από τον παρουσιαστή εξαρτάται πώς θα απαντήσει στο αίτημα - μπορεί να επιστρέψει δεδομένα σε μορφή JSON, να στείλει ένα τμήμα κώδικα HTML, ένα έγγραφο XML κ.λπ.
 
-Από την πλευρά του διακομιστή, ένα αίτημα AJAX μπορεί να ανιχνευθεί χρησιμοποιώντας τη μέθοδο service που [ενθυλακώνει το αίτημα HTTP |http:request] `$httpRequest->isAjax()` (ανιχνεύει με βάση την επικεφαλίδα HTTP `X-Requested-With`). Στο εσωτερικό του παρουσιαστή, είναι διαθέσιμη μια συντόμευση με τη μορφή της μεθόδου `$this->isAjax()`.
+Από την πλευρά του προγράμματος περιήγησης, ξεκινάμε ένα αίτημα AJAX χρησιμοποιώντας τη συνάρτηση `fetch()`:
 
-Υπάρχει ένα προεπεξεργασμένο αντικείμενο που ονομάζεται `payload` και είναι αφιερωμένο στην αποστολή δεδομένων στο πρόγραμμα περιήγησης σε JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// επεξεργασία της απάντησης
+});
 ```
 
-Για πλήρη έλεγχο της εξόδου JSON χρησιμοποιήστε τη μέθοδο `sendJson` στον παρουσιαστή σας. Τερματίζει αμέσως τον presenter και θα κάνετε χωρίς πρότυπο:
+Στην πλευρά του διακομιστή, ένα αίτημα AJAX αναγνωρίζεται από τη μέθοδο `$httpRequest->isAjax()` της υπηρεσίας που [ενθυλακώνει το αίτημα HTTP |http:request]. Χρησιμοποιεί την επικεφαλίδα HTTP `X-Requested-With`, οπότε είναι απαραίτητη η αποστολή της. Μέσα στον παρουσιαστή, μπορείτε να χρησιμοποιήσετε τη μέθοδο `$this->isAjax()`.
+
+Εάν θέλετε να στείλετε δεδομένα σε μορφή JSON, χρησιμοποιήστε τη μέθοδο [`sendJson()` |presenters#Sending a response] μέθοδο. Η μέθοδος τερματίζει επίσης τη δραστηριότητα του παρουσιαστή.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Εάν θέλουμε να στείλουμε HTML, μπορούμε είτε να ορίσουμε ένα ειδικό πρότυπο για αιτήσεις AJAX:
+Αν σκοπεύετε να απαντήσετε με ένα ειδικό πρότυπο σχεδιασμένο για AJAX, μπορείτε να το κάνετε ως εξής:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Αποσπάσματα .[#toc-snippets]
+============================
+
+Το πιο ισχυρό εργαλείο που προσφέρει η Nette για τη σύνδεση του διακομιστή με τον πελάτη είναι τα snippets. Με αυτά μπορείτε να μετατρέψετε μια συνηθισμένη εφαρμογή σε AJAX με ελάχιστη προσπάθεια και λίγες γραμμές κώδικα. Το παράδειγμα Fifteen δείχνει πώς λειτουργούν όλα αυτά, και ο κώδικάς του μπορεί να βρεθεί στο [GitHub |https://github.com/nette-examples/fifteen].
+
+Τα αποσπάσματα, ή αποκόμματα, σας επιτρέπουν να ενημερώνετε μόνο τμήματα της σελίδας, αντί να επαναφορτώνετε ολόκληρη τη σελίδα. Αυτό είναι πιο γρήγορο και αποτελεσματικό, και παρέχει επίσης μια πιο άνετη εμπειρία χρήσης. Τα αποσπάσματα μπορεί να σας θυμίζουν το Hotwire για το Ruby on Rails ή το Symfony UX Turbo. Είναι ενδιαφέρον ότι η Nette εισήγαγε τα snippets 14 χρόνια νωρίτερα.
+
+Πώς λειτουργούν τα snippets; Όταν φορτώνεται για πρώτη φορά η σελίδα (μια αίτηση χωρίς-AJAX), φορτώνεται ολόκληρη η σελίδα, συμπεριλαμβανομένων όλων των snippets. Όταν ο χρήστης αλληλεπιδρά με τη σελίδα (π.χ. κάνει κλικ σε ένα κουμπί, υποβάλλει μια φόρμα κ.λπ.), αντί να φορτωθεί ολόκληρη η σελίδα, γίνεται ένα αίτημα AJAX. Ο κώδικας στον παρουσιαστή εκτελεί την ενέργεια και αποφασίζει ποια αποσπάσματα χρειάζονται ενημέρωση. Η Nette αποδίδει αυτά τα αποσπάσματα και τα αποστέλλει με τη μορφή ενός πίνακα JSON. Ο κώδικας χειρισμού στο πρόγραμμα περιήγησης εισάγει στη συνέχεια τα ληφθέντα αποσπάσματα πίσω στη σελίδα. Επομένως, μεταφέρεται μόνο ο κώδικας των αλλαγμένων αποσπασμάτων, εξοικονομώντας εύρος ζώνης και επιταχύνοντας τη φόρτωση σε σύγκριση με τη μεταφορά ολόκληρου του περιεχομένου της σελίδας.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-Η [βιβλιοθήκη Naja |https://naja.js.org] χρησιμοποιείται για το χειρισμό αιτημάτων AJAX στην πλευρά του προγράμματος περιήγησης. [Εγκαταστήστε |https://naja.js.org/#/guide/01-install-setup-naja] την ως πακέτο node.js (για χρήση με Webpack, Rollup, Vite, Parcel και άλλα):
+Για το χειρισμό των αποσπασμάτων στην πλευρά του προγράμματος περιήγησης, χρησιμοποιείται η [βιβλιοθήκη Naja |https://naja.js.org]. [Εγκαταστήστε την |https://naja.js.org/#/guide/01-install-setup-naja] ως πακέτο node.js (για χρήση με εφαρμογές όπως Webpack, Rollup, Vite, Parcel και άλλες):
 
 ```shell
 npm install naja
 ```
 
-...ή να την εισαγάγετε απευθείας στο πρότυπο της σελίδας:
+... ή να την εισαγάγετε απευθείας στο πρότυπο της σελίδας:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Για να δημιουργήσετε μια αίτηση AJAX από έναν κανονικό σύνδεσμο (σήμα) ή μια υποβολή φόρμας, απλά επισημάνετε τον σχετικό σύνδεσμο, τη φόρμα ή το κουμπί με την κλάση `ajax`:
+Πρώτα πρέπει να [αρχικοποιήσετε |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] τη βιβλιοθήκη:
+
+```js
+naja.initialize();
+```
+
+Για να μετατρέψετε έναν συνηθισμένο σύνδεσμο (σήμα) ή την υποβολή φόρμας σε αίτηση AJAX, απλά σημειώστε τον αντίστοιχο σύνδεσμο, φόρμα ή κουμπί με την κλάση `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ npm install naja
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippets .[#toc-snippets]
-=========================
-
-Υπάρχει ένα πολύ πιο ισχυρό εργαλείο ενσωματωμένης υποστήριξης AJAX - τα αποσπάσματα. Η χρήση τους καθιστά δυνατή τη μετατροπή μιας κανονικής εφαρμογής σε εφαρμογή AJAX χρησιμοποιώντας μόνο μερικές γραμμές κώδικα. Το πώς λειτουργούν όλα αυτά παρουσιάζεται στο παράδειγμα Fifteen του οποίου ο κώδικας είναι επίσης προσβάσιμος στο build ή στο [GitHub |https://github.com/nette-examples/fifteen].
-
-Ο τρόπος που λειτουργούν τα snippets είναι ότι ολόκληρη η σελίδα μεταφέρεται κατά το αρχικό (δηλαδή μη-AJAX) αίτημα και στη συνέχεια με κάθε AJAX [υποερώτημα |components#signal] (αίτημα της ίδιας προβολής του ίδιου παρουσιαστή) μεταφέρεται μόνο ο κώδικας των αλλαγμένων τμημάτων στο αποθετήριο `payload` που αναφέρθηκε προηγουμένως.
-
-Τα Snippets μπορεί να σας θυμίζουν το Hotwire για το Ruby on Rails ή το Symfony UX Turbo, αλλά η Nette τα επινόησε δεκατέσσερα χρόνια νωρίτερα.
-
+Επανασχεδίαση αποσπασμάτων .[#toc-redrawing-snippets]
+-----------------------------------------------------
 
-Ακύρωση των Snippets .[#toc-invalidation-of-snippets]
-=====================================================
-
-Κάθε απόγονος της κλάσης [Control |components] (που είναι και ένας Παρουσιαστής) είναι σε θέση να θυμάται αν υπήρξαν αλλαγές κατά τη διάρκεια μιας αίτησης που απαιτούν την εκ νέου εμφάνιση. Υπάρχει ένα ζευγάρι μεθόδων για το χειρισμό αυτό: `redrawControl()` και `isControlInvalid()`. Ένα παράδειγμα:
+Κάθε αντικείμενο της κλάσης [Control |components] (συμπεριλαμβανομένου και του ίδιου του Presenter) διατηρεί αρχείο για το αν έχουν συμβεί αλλαγές που καθιστούν αναγκαία την επανασχεδίασή του. Για το σκοπό αυτό χρησιμοποιείται η μέθοδος `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Το αντικείμενο πρέπει να αναδημιουργηθεί εκ νέου μετά τη σύνδεση του χρήστη.
+	// μετά τη σύνδεση, είναι απαραίτητο να σχεδιάσετε εκ νέου το σχετικό τμήμα
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Η Nette ωστόσο προσφέρει μια ακόμη πιο λεπτή ανάλυση από ολόκληρα στοιχεία. Οι αναφερόμενες μέθοδοι δέχονται το όνομα ενός λεγόμενου "αποσπάσματος" ως προαιρετική παράμετρο. Ένα "απόσπασμα" είναι ουσιαστικά ένα στοιχείο στο πρότυπό σας που επισημαίνεται για το σκοπό αυτό με μια ετικέτα Latte, περισσότερα γι' αυτό αργότερα. Έτσι είναι δυνατόν να ζητήσετε από ένα στοιχείο να ξανασχεδιάσει μόνο *μέρη* του προτύπου του. Εάν ακυρωθεί ολόκληρο το συστατικό, τότε όλα τα αποσπάσματά του αναδημιουργούνται εκ νέου. Ένα συστατικό είναι "άκυρο" επίσης εάν οποιοδήποτε από τα υποσυστήματά του είναι άκυρο.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // ακυρώνει το απόσπασμα με το όνομα 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, τουλάχιστον ένα απόσπασμα είναι άκυρο
+Η Nette επιτρέπει επίσης έναν πιο λεπτομερή έλεγχο του τι χρειάζεται επανασχεδίαση. Η προαναφερθείσα μέθοδος μπορεί να λάβει το όνομα του αποσπάσματος ως όρισμα. Έτσι, είναι δυνατή η ακύρωση (που σημαίνει: εξαναγκασμός σε επανασχεδίαση) σε επίπεδο τμήματος προτύπου. Εάν ακυρωθεί ολόκληρο το συστατικό, κάθε απόσπασμα αυτού επανασχεδιάζεται επίσης:
 
-$this->redrawControl(); // ακυρώνει ολόκληρο το συστατικό, κάθε απόσπασμα
-$this->isControlInvalid('footer'); // -> true
+```php
+// ακυρώνει το απόσπασμα 'header'
+$this->redrawControl('header');
 ```
 
-Ένα συστατικό που λαμβάνει σήμα επισημαίνεται αυτόματα για επανασχεδίαση.
-
-Χάρη στην επανασχεδίαση αποσπασμάτων γνωρίζουμε επακριβώς ποια τμήματα ποιων στοιχείων πρέπει να επανασχεδιαστούν.
-
-
-Ετικέτα `{snippet} … {/snippet}` .{toc: Tag snippet}
-====================================================
-
-Η απόδοση της σελίδας εξελίσσεται πολύ παρόμοια με μια κανονική αίτηση: φορτώνονται τα ίδια πρότυπα κ.λπ. Το ζωτικής σημασίας μέρος είναι, ωστόσο, να παραλείπονται τα μέρη που δεν πρέπει να φτάσουν στην έξοδο- τα υπόλοιπα μέρη πρέπει να συσχετίζονται με ένα αναγνωριστικό και να αποστέλλονται στο χρήστη σε κατανοητή μορφή για έναν χειριστή JavaScript.
-
 
-Σύνταξη .[#toc-syntax]
-----------------------
+Αποσπάσματα σε Latte .[#toc-snippets-in-latte]
+----------------------------------------------
 
-Εάν υπάρχει ένα στοιχείο ελέγχου ή ένα απόσπασμα στο πρότυπο, πρέπει να το τυλίξουμε χρησιμοποιώντας την ετικέτα `{snippet} ... {/snippet}` pair - θα διασφαλίσει ότι το αποδιδόμενο απόσπασμα θα "αποκοπεί" και θα σταλεί στο πρόγραμμα περιήγησης. Θα το περικλείσει επίσης σε ένα βοηθητικό `<div>` tag (είναι δυνατόν να χρησιμοποιηθεί ένα διαφορετικό). Στο ακόλουθο παράδειγμα ορίζεται ένα απόσπασμα με το όνομα `header`. Μπορεί κάλλιστα να αντιπροσωπεύει το πρότυπο ενός στοιχείου:
+Η χρήση αποσπασμάτων στο Latte είναι εξαιρετικά εύκολη. Για να ορίσετε ένα μέρος του προτύπου ως snippet, απλά τυλίξτε το σε ετικέτες `{snippet}` και `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ $this->isControlInvalid('footer'); // -> true
 {/snippet}
 ```
 
-Ένα απόσπασμα άλλου τύπου από το `<div>` ή ένα απόσπασμα με πρόσθετα χαρακτηριστικά HTML επιτυγχάνεται με τη χρήση της παραλλαγής χαρακτηριστικών:
+Το απόσπασμα δημιουργεί ένα στοιχείο `<div>` στη σελίδα HTML με ένα ειδικά δημιουργημένο `id`. Κατά την επανασχεδίαση ενός αποσπάσματος, το περιεχόμενο αυτού του στοιχείου ενημερώνεται. Επομένως, κατά την αρχική απόδοση της σελίδας, όλα τα snippets πρέπει επίσης να αποδοθούν, ακόμη και αν μπορεί αρχικά να είναι κενά.
+
+Μπορείτε επίσης να δημιουργήσετε ένα απόσπασμα με ένα στοιχείο διαφορετικό από το `<div>` χρησιμοποιώντας ένα χαρακτηριστικό n:attribute:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ $this->isControlInvalid('footer'); // -> true
 ```
 
 
-Δυναμικά αποσπάσματα .[#toc-dynamic-snippets]
-=============================================
+Περιοχές αποσπασμάτων .[#toc-snippet-areas]
+-------------------------------------------
 
-Στο Nette μπορείτε επίσης να ορίσετε αποσπάσματα με δυναμικό όνομα βάσει μιας παραμέτρου εκτέλεσης. Αυτό είναι πιο κατάλληλο για διάφορες λίστες όπου πρέπει να αλλάξουμε μόνο μια γραμμή αλλά δεν θέλουμε να μεταφέρουμε ολόκληρη τη λίστα μαζί με αυτήν. Ένα τέτοιο παράδειγμα θα ήταν το εξής:
+Τα ονόματα αποσπασμάτων μπορούν επίσης να είναι εκφράσεις:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Υπάρχει ένα στατικό απόσπασμα που ονομάζεται `itemsContainer`, το οποίο περιέχει διάφορα δυναμικά αποσπάσματα: `item-0`, `item-1` κ.ο.κ.
+ `item-0`, `item-1`, κ.λπ. Αν ακυρώναμε άμεσα ένα δυναμικό απόσπασμα (π.χ. `item-1`), τίποτα δεν θα ξανασχεδιαζόταν. Ο λόγος είναι ότι τα αποσπάσματα λειτουργούν ως αληθινά αποσπάσματα και μόνο τα ίδια αποδίδονται άμεσα. Ωστόσο, στο πρότυπο, δεν υπάρχει τεχνικά ένα απόσπασμα με το όνομα `item-1`. Εμφανίζεται μόνο όταν εκτελείται ο περιβάλλων κώδικας του αποσπάσματος, στην προκειμένη περίπτωση, ο βρόχος foreach. Ως εκ τούτου, θα επισημάνουμε το τμήμα του προτύπου που πρέπει να εκτελεστεί με την ετικέτα `{snippetArea}`:
 
-Δεν μπορείτε να ξανασχεδιάσετε άμεσα ένα δυναμικό απόσπασμα (η επανασχεδίαση του `item-1` δεν έχει κανένα αποτέλεσμα), πρέπει να ξανασχεδιάσετε το γονικό του απόσπασμα (σε αυτό το παράδειγμα `itemsContainer`). Αυτό προκαλεί την εκτέλεση του κώδικα του γονικού αποσπάσματος, αλλά στη συνέχεια αποστέλλονται στο πρόγραμμα περιήγησης μόνο τα επιμέρους αποσπάσματά του. Αν θέλετε να στείλετε μόνο ένα από τα υπο-στοιχεία, πρέπει να τροποποιήσετε την είσοδο για το γονικό απόσπασμα ώστε να μην παράγει τα άλλα υπο-στοιχεία.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-Στο παραπάνω παράδειγμα πρέπει να βεβαιωθείτε ότι για μια αίτηση AJAX θα προστεθεί μόνο ένα στοιχείο στον πίνακα `$list`, επομένως ο βρόχος `foreach` θα εκτυπώσει μόνο ένα δυναμικό απόσπασμα.
+Και θα ξανασχεδιάσουμε τόσο το μεμονωμένο απόσπασμα όσο και ολόκληρη την υπερκείμενη περιοχή:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Είναι επίσης σημαντικό να διασφαλίσουμε ότι ο πίνακας `$items` περιέχει μόνο τα στοιχεία που πρέπει να επανασχεδιαστούν.
 
-Αποσπάσματα σε συμπεριλαμβανόμενο πρότυπο .[#toc-snippets-in-an-included-template]
-==================================================================================
-
-Μπορεί να συμβεί το απόσπασμα να βρίσκεται σε ένα πρότυπο το οποίο συμπεριλαμβάνεται από ένα διαφορετικό πρότυπο. Σε αυτή την περίπτωση πρέπει να τυλίξουμε τον κώδικα συμπερίληψης στο δεύτερο πρότυπο με την ετικέτα `snippetArea`, και στη συνέχεια να ξανασχεδιάσουμε τόσο το snippetArea όσο και το πραγματικό απόσπασμα.
-
-Η ετικέτα `snippetArea` διασφαλίζει ότι ο κώδικας στο εσωτερικό της εκτελείται, αλλά μόνο το πραγματικό απόσπασμα στο συμπεριλαμβανόμενο πρότυπο αποστέλλεται στο πρόγραμμα περιήγησης.
+Κατά την εισαγωγή ενός άλλου προτύπου στο κύριο με τη χρήση της ετικέτας `{include}`, το οποίο έχει αποσπάσματα, είναι απαραίτητο να τυλίξετε και πάλι το συμπεριλαμβανόμενο πρότυπο σε ένα `snippetArea` και να ακυρώσετε τόσο το απόσπασμα όσο και την περιοχή μαζί:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Μπορείτε επίσης να το συνδυάσετε με δυναμικά αποσπάσματα.
 
+Αποσπάσματα σε στοιχεία .[#toc-snippets-in-components]
+------------------------------------------------------
 
-Προσθήκη και διαγραφή .[#toc-adding-and-deleting]
-=================================================
-
-Εάν προσθέσετε ένα νέο στοιχείο στη λίστα και ακυρώσετε το `itemsContainer`, η αίτηση AJAX επιστρέφει αποσπάσματα που περιλαμβάνουν το νέο στοιχείο, αλλά ο χειριστής javascript δεν θα είναι σε θέση να το αποδώσει. Αυτό συμβαίνει επειδή δεν υπάρχει κανένα στοιχείο HTML με το νεοδημιουργηθέν ID.
-
-Σε αυτή την περίπτωση, ο απλούστερος τρόπος είναι να τυλίξετε ολόκληρη τη λίστα σε ένα ακόμη απόσπασμα και να τα ακυρώσετε όλα:
+Μπορείτε να δημιουργήσετε αποσπάσματα μέσα σε [στοιχεία |components] και η Nette θα τα ανασχεδιάσει αυτόματα. Ωστόσο, υπάρχει ένας συγκεκριμένος περιορισμός: για να ξανασχεδιάσει αποσπάσματα, καλεί τη μέθοδο `render()` χωρίς καμία παράμετρο. Έτσι, η μετάδοση παραμέτρων στο πρότυπο δεν θα λειτουργήσει:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Αποστολή δεδομένων χρήστη .[#toc-sending-user-data]
+---------------------------------------------------
+
+Μαζί με τα αποσπάσματα, μπορείτε να στείλετε οποιαδήποτε πρόσθετα δεδομένα στον πελάτη. Απλά γράψτε τα στο αντικείμενο `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Το ίδιο ισχύει και για τη διαγραφή ενός στοιχείου. Θα ήταν δυνατό να στείλετε κενό snippet, αλλά συνήθως οι λίστες μπορούν να είναι σελιδοποιημένες και θα ήταν περίπλοκο να υλοποιήσετε τη διαγραφή ενός στοιχείου και τη φόρτωση ενός άλλου (το οποίο βρισκόταν σε διαφορετική σελίδα της σελιδοποιημένης λίστας).
-
 
-Αποστολή παραμέτρων στο συστατικό .[#toc-sending-parameters-to-component]
-=========================================================================
+Παράμετροι αποστολής .[#toc-sending-parameters]
+===============================================
 
 Όταν στέλνουμε παραμέτρους στο στοιχείο μέσω αίτησης AJAX, είτε πρόκειται για παραμέτρους σήματος είτε για μόνιμες παραμέτρους, πρέπει να παρέχουμε το συνολικό τους όνομα, το οποίο περιέχει επίσης το όνομα του στοιχείου. Το πλήρες όνομα της παραμέτρου επιστρέφει η μέθοδος `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Και χειρίζεται τη μέθοδο με s αντίστοιχες παραμέτρους στο συστατικό.
+Μια μέθοδος χειρισμού με τις αντίστοιχες παραμέτρους στο συστατικό:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/el/bootstrap.texy b/application/el/bootstrap.texy
index 71f6028048..f71018bac5 100644
--- a/application/el/bootstrap.texy
+++ b/application/el/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Ο διαμορφωτής είναι υπεύθυνος για τη ρύθμιση του περιβάλλοντος και των υπηρεσιών της εφαρμογής.
+		$this->configurator = new Configurator;
+		// Ορίστε τον κατάλογο για τα προσωρινά αρχεία που παράγονται από τη Nette (π.χ. μεταγλωττισμένα πρότυπα)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Η Nette είναι έξυπνη και η λειτουργία ανάπτυξης ενεργοποιείται αυτόματα,
+		// ή μπορείτε να την ενεργοποιήσετε για μια συγκεκριμένη διεύθυνση IP ξεσχολιάζοντας την ακόλουθη γραμμή:
+		// $this->configurator->setDebugMode('secret@23.75.345.200'),
+
+		// Ενεργοποιεί το Tracy: το απόλυτο εργαλείο αποσφαλμάτωσης "ελβετικό μαχαίρι του στρατού".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: αυτόματη φόρτωση όλων των κλάσεων στον δεδομένο κατάλογο
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Φόρτωση αρχείων διαμόρφωσης
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Στην περίπτωση των διαδικτυακών εφαρμογών, το αρχικό αρχείο είναι το `index.php`, το οποίο βρίσκεται στον δημόσιο κατάλογο `www/`. Επιτρέπει στην κλάση `Bootstrap` να αρχικοποιήσει το περιβάλλον και να επιστρέψει το `$configurator` που δημιουργεί το DI container. Στη συνέχεια αποκτά την υπηρεσία `Application`, η οποία εκτελεί την εφαρμογή ιστού:
+Το αρχικό αρχείο για τις διαδικτυακές εφαρμογές είναι το `index.php`, το οποίο βρίσκεται στον δημόσιο κατάλογο `www/`. Χρησιμοποιεί την κλάση `Bootstrap` για την αρχικοποίηση του περιβάλλοντος και τη δημιουργία ενός δοχείου DI. Στη συνέχεια, λαμβάνει την υπηρεσία `Application` από το δοχείο, η οποία εκκινεί την εφαρμογή ιστού:
 
 ```php
-// αρχικοποίηση του περιβάλλοντος + λήψη του αντικειμένου Configurator
-$configurator = App\Bootstrap::boot();
-// Δημιουργία ενός δοχείου DI
-$container = $configurator->createContainer();
+$bootstrap = new App\Bootstrap;
+// Αρχικοποίηση του περιβάλλοντος + δημιουργία ενός δοχείου DI
+$container = $bootstrap->bootWebApplication();
 // Το δοχείο DI δημιουργεί ένα αντικείμενο Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// έναρξη της εφαρμογής Nette
+// Εκκίνηση της εφαρμογής Nette και χειρισμός της εισερχόμενης αίτησης
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ $application->run();
 Αν θέλετε να ενεργοποιήσετε τη λειτουργία ανάπτυξης σε άλλες περιπτώσεις, για παράδειγμα, για προγραμματιστές που έχουν πρόσβαση από μια συγκεκριμένη διεύθυνση IP, μπορείτε να χρησιμοποιήσετε τη διεύθυνση `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // μία ή περισσότερες διευθύνσεις IP
+$this->configurator->setDebugMode('23.75.345.200'); // μία ή περισσότερες διευθύνσεις IP
 ```
 
 Συνιστούμε οπωσδήποτε τον συνδυασμό μιας διεύθυνσης IP με ένα cookie. Θα αποθηκεύσουμε ένα μυστικό token στο cookie `nette-debug`, π.χ. `secret1234`, και η λειτουργία ανάπτυξης θα ενεργοποιηθεί για τους προγραμματιστές με αυτόν τον συνδυασμό IP και cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Μπορούμε επίσης να απενεργοποιήσουμε εντελώς τη λειτουργία προγραμματιστή, ακόμη και για το localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Σημειώστε ότι η τιμή `true` ενεργοποιεί τη λειτουργία προγραμματιστή με σκληρό τρόπο, κάτι που δεν πρέπει ποτέ να συμβαίνει σε έναν διακομιστή παραγωγής.
@@ -90,7 +115,7 @@ $configurator->setDebugMode(false);
 Για εύκολη αποσφαλμάτωση, θα ενεργοποιήσουμε το σπουδαίο εργαλείο [Tracy |tracy:]. Στη λειτουργία προγραμματιστή απεικονίζει τα σφάλματα και στη λειτουργία παραγωγής καταγράφει τα σφάλματα στον καθορισμένο κατάλογο:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ $configurator->enableTracy($appDir . '/log');
 Η Nette χρησιμοποιεί την κρυφή μνήμη για το DI container, το RobotLoader, τα πρότυπα κ.λπ. Ως εκ τούτου, είναι απαραίτητο να ορίσετε τη διαδρομή προς τον κατάλογο όπου θα αποθηκεύεται η προσωρινή μνήμη:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Σε Linux ή macOS, ορίστε τα [δικαιώματα εγγραφής |nette:troubleshooting#Setting directory permissions] για τους καταλόγους `log/` και `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Συνήθως, θα θέλουμε να φορτώνουμε αυτόματα τις κλάσεις χρησιμοποιώντας [τον RobotLoader |robot-loader:], οπότε πρέπει να τον εκκινήσουμε και να τον αφήσουμε να φορτώσει κλάσεις από τον κατάλογο όπου βρίσκεται το `Bootstrap.php` (δηλαδή το `__DIR__`) και όλους τους υποκαταλόγους του:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ $configurator->createRobotLoader()
 Το Configurator σας επιτρέπει να καθορίσετε μια ζώνη ώρας για την εφαρμογή σας.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ $configurator->setTimeZone('Europe/Prague');
 Τα αρχεία διαμόρφωσης φορτώνονται με τη χρήση του `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Η μέθοδος `addConfig()` μπορεί να κληθεί πολλές φορές για την προσθήκη πολλών αρχείων.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ if (PHP_SAPI === 'cli') {
 Οι παράμετροι που χρησιμοποιούνται σε αρχεία ρυθμίσεων μπορούν να οριστούν [στην ενότητα `parameters` |dependency-injection:configuration#parameters] και επίσης να μεταβιβαστούν (ή να αντικατασταθούν) από τη μέθοδο `addStaticParameters()` (έχει το ψευδώνυμο `addParameters()`). Είναι σημαντικό ότι διαφορετικές τιμές παραμέτρων προκαλούν τη δημιουργία πρόσθετων δοχείων DI, δηλαδή πρόσθετων κλάσεων.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ $configurator->addStaticParameters([
 Μπορούμε επίσης να προσθέσουμε δυναμικές παραμέτρους στο δοχείο, οι διαφορετικές τιμές τους, σε αντίθεση με τις στατικές παραμέτρους, δεν θα προκαλέσουν τη δημιουργία νέων δοχείων DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Οι μεταβλητές περιβάλλοντος θα μπορούσαν εύκολα να γίνουν διαθέσιμες με τη χρήση δυναμικών παραμέτρων. Μπορούμε να έχουμε πρόσβαση σε αυτές μέσω της διεύθυνσης `%env.variable%` στα αρχεία ρυθμίσεων.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ $configurator->addDynamicParameters([
 - `%wwwDir%` είναι η απόλυτη διαδρομή προς τον κατάλογο που περιέχει το αρχείο καταχώρησης `index.php`
 - `%tempDir%` είναι η απόλυτη διαδρομή προς τον κατάλογο για τα προσωρινά αρχεία
 - `%vendorDir%` είναι η απόλυτη διαδρομή προς τον κατάλογο όπου ο Composer εγκαθιστά τις βιβλιοθήκες
+- `%rootDir%` είναι η απόλυτη διαδρομή προς τον ριζικό κατάλογο του έργου
 - Το `%debugMode%` δηλώνει αν η εφαρμογή βρίσκεται σε κατάσταση αποσφαλμάτωσης.
 - Το `%consoleMode%` δηλώνει αν η αίτηση υποβλήθηκε μέσω της γραμμής εντολών.
 
@@ -225,7 +252,7 @@ services:
 Δημιουργούμε μια νέα περίπτωση και την εισάγουμε στο bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Διαφορετικά περιβάλλοντα .[#toc-different-environments]
 =======================================================
 
-Μπορείτε να προσαρμόσετε την τάξη `Bootstrap` ανάλογα με τις ανάγκες σας. Μπορείτε να προσθέσετε παραμέτρους στη μέθοδο `boot()` για να διαφοροποιήσετε τα έργα ιστού ή να προσθέσετε άλλες μεθόδους, όπως η `bootForTests()`, η οποία αρχικοποιεί το περιβάλλον για δοκιμές μονάδας, η `bootForCli()` για σενάρια που καλούνται από τη γραμμή εντολών κ.ο.κ.
+Μη διστάσετε να προσαρμόσετε την τάξη `Bootstrap` σύμφωνα με τις ανάγκες σας. Μπορείτε να προσθέσετε παραμέτρους στη μέθοδο `bootWebApplication()` για να διαφοροποιήσετε τα διάφορα web projects. Εναλλακτικά, μπορείτε να προσθέσετε άλλες μεθόδους, όπως `bootTestEnvironment()` για την αρχικοποίηση του περιβάλλοντος για δοκιμές μονάδας, `bootConsoleApplication()` για σενάρια που καλούνται από τη γραμμή εντολών κ.ο.κ.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
 {
-	$configurator = self::boot();
 	Tester\Environment::setup(); // Αρχικοποίηση Nette Tester
-	return $configurator;
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
+{
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/el/components.texy b/application/el/components.texy
index ae5fc64c2f..06fafcf4d4 100644
--- a/application/el/components.texy
+++ b/application/el/components.texy
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // και ανακατεύθυνση
 ```
 
 
+Επανακατεύθυνση μετά από ένα σήμα .[#toc-redirection-after-a-signal]
+====================================================================
+
+Μετά την επεξεργασία ενός σήματος συνιστωσών, ακολουθεί συχνά ανακατεύθυνση. Αυτή η κατάσταση είναι παρόμοια με τις φόρμες - μετά την υποβολή μιας φόρμας, κάνουμε επίσης ανακατεύθυνση για να αποτρέψουμε την εκ νέου υποβολή δεδομένων όταν η σελίδα ανανεώνεται στο πρόγραμμα περιήγησης.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Δεδομένου ότι ένα συστατικό είναι ένα επαναχρησιμοποιήσιμο στοιχείο και συνήθως δεν πρέπει να έχει άμεση εξάρτηση από συγκεκριμένους παρουσιαστές, οι μέθοδοι `redirect()` και `link()` ερμηνεύουν αυτόματα την παράμετρο ως σήμα συστατικού:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Εάν χρειάζεται να ανακατευθύνετε σε διαφορετικό παρουσιαστή ή ενέργεια, μπορείτε να το κάνετε μέσω του παρουσιαστή:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Μόνιμες παράμετροι .[#toc-persistent-parameters]
 ================================================
 
@@ -347,7 +369,7 @@ services:
 Τέλος, θα χρησιμοποιήσουμε αυτό το εργοστάσιο στον παρουσιαστή μας:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ interface PollControlFactory
 Τα συστατικά σε μια εφαρμογή Nette είναι τα επαναχρησιμοποιήσιμα μέρη μιας διαδικτυακής εφαρμογής που ενσωματώνουμε σε σελίδες, τα οποία αποτελούν το αντικείμενο αυτού του κεφαλαίου. Ποιες ακριβώς είναι οι δυνατότητες ενός τέτοιου συστατικού;
 
 1) είναι δυνατό να αποδοθεί σε ένα πρότυπο
-2) γνωρίζει ποιο μέρος του εαυτού του να αποδώσει κατά τη διάρκεια μιας [αίτησης AJAX |ajax#invalidation] (αποσπάσματα)
+2) γνωρίζει [ποιο μέρος του εαυτού του |ajax#snippets] να αποδώσει κατά τη διάρκεια μιας αίτησης AJAX (αποσπάσματα)
 3) έχει τη δυνατότητα να αποθηκεύει την κατάστασή του σε μια διεύθυνση URL (μόνιμες παράμετροι)
 4) έχει τη δυνατότητα να ανταποκρίνεται σε ενέργειες του χρήστη (σήματα)
 5) δημιουργεί μια ιεραρχική δομή (όπου η ρίζα είναι ο παρουσιαστής)
@@ -430,7 +452,7 @@ class PaginatingControl extends Control
 }
 ```
 
-Η αντίθετη διαδικασία, δηλαδή η συλλογή τιμών από persistent properites, αντιμετωπίζεται από τη μέθοδο `saveState()`.
+Η αντίθετη διαδικασία, δηλαδή η συλλογή τιμών από persistent properties, αντιμετωπίζεται από τη μέθοδο `saveState()`.
 
 
 Σήματα σε βάθος .[#toc-signals-in-depth]
diff --git a/application/el/configuration.texy b/application/el/configuration.texy
index 01b036704b..dcf8543ece 100644
--- a/application/el/configuration.texy
+++ b/application/el/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# δείχνει τον πίνακα "Nette Application" στο Tracy BlueScreen?
 	debugger: ...           # (bool) προεπιλογή true
 
-	# θα καλείται ο παρουσιαστής σφαλμάτων σε περίπτωση σφάλματος;
-	catchExceptions: ...    # (bool) προεπιλεγμένη τιμή true σε κατάσταση παραγωγής
+	# θα κληθεί ο παρουσιαστής σφαλμάτων στο σφάλμα;
+	# έχει αποτέλεσμα μόνο σε λειτουργία προγραμματιστή
+	catchExceptions: ...    # (bool) προεπιλογή true
 
 	# όνομα του error-presenter
-	errorPresenter: Error   # (string) προεπιλογή 'Nette:Error'
+	errorPresenter: Error   # (string|array) προεπιλογή 'Nette:Error'
+
+	# ορίζει ψευδώνυμα για παρουσιαστές και εκδηλώσεις
+	aliases: ...
 
 	# ορίζει τους κανόνες για την επίλυση του ονόματος του παρουσιαστή σε μια κλάση
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) προεπιλογή σε false
 ```
 
-Επειδή οι παρουσιαστές σφαλμάτων δεν καλούνται εξ ορισμού σε κατάσταση ανάπτυξης και τα σφάλματα εμφανίζονται από το Tracy, η αλλαγή της τιμής `catchExceptions` σε `true` βοηθάει στην επαλήθευση της σωστής λειτουργίας των παρουσιαστών σφαλμάτων κατά την ανάπτυξη.
+Από την έκδοση 3.2 του `nette/application` είναι δυνατό να ορίσετε ένα ζεύγος παρουσιαστών σφαλμάτων:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # για την εξαίρεση Nette\Application\BadRequestException
+		5xx: Error5xx   # για άλλες εξαιρέσεις
+```
 
 Η επιλογή `silentLinks` καθορίζει τον τρόπο με τον οποίο η Nette συμπεριφέρεται στη λειτουργία ανάπτυξης όταν η δημιουργία συνδέσμων αποτυγχάνει (για παράδειγμα, επειδή δεν υπάρχει παρουσιαστής κ.λπ.). Η προεπιλεγμένη τιμή `false` σημαίνει ότι η Nette ενεργοποιεί το `E_USER_WARNING`. Η ρύθμιση σε `true` καταστέλλει αυτό το μήνυμα σφάλματος. Σε περιβάλλον παραγωγής, το `E_USER_WARNING` ενεργοποιείται πάντα. Μπορούμε επίσης να επηρεάσουμε αυτή τη συμπεριφορά θέτοντας τη μεταβλητή του παρουσιαστή [$invalidLinkMode |creating-links#Invalid Links].
 
+Τα [ψευδώνυμα απλοποιούν την αναφορά σε |creating-links#aliases] συχνά χρησιμοποιούμενους παρουσιαστές.
+
 Η [αντιστοίχιση ορίζει τους κανόνες |modules#mapping] με τους οποίους το όνομα της κλάσης προκύπτει από το όνομα του παρουσιαστή.
 
 
@@ -82,6 +95,9 @@ latte:
 	# ενεργοποιεί τον [έλεγχο του παραγόμενου κώδικα |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) η προεπιλογή είναι null
 
+	# ορίζει την τοπική γλώσσα
+	locale: cs_CZ        # (string) η προεπιλογή είναι null
+
 	# κλάση του $this->template
 	templateClass: App\MyTemplateClass # προεπιλογή σε Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ latte:
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/el/creating-links.texy b/application/el/creating-links.texy
index e36d982225..1914401594 100644
--- a/application/el/creating-links.texy
+++ b/application/el/creating-links.texy
@@ -38,7 +38,7 @@
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Εάν η μέθοδος `ProductPresenter::renderShow()` δεν έχει στην υπογραφή της την `$lang`, μπορεί να διαβάσει την τιμή της παραμέτρου χρησιμοποιώντας την `$lang = $this->getParameter('lang')`.
+Εάν η μέθοδος `ProductPresenter::renderShow()` δεν έχει στην υπογραφή της την `$lang`, μπορεί να ανακτήσει την τιμή της παραμέτρου χρησιμοποιώντας την `$lang = $this->getParameter('lang')` ή από την [ιδιότητα |presenters#Request Parameters].
 
 Εάν οι παράμετροι είναι αποθηκευμένες σε πίνακα, μπορούν να επεκταθούν με τον τελεστή `...` (ή `(expand)` στο Latte 2.x):
 
@@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 <a n:href="this">refresh</a>
 ```
 
-Ταυτόχρονα, όλες οι παράμετροι που καθορίζονται στην υπογραφή της εντολής `render<View>()` ή `action<Action>()` μεταφέρονται. Έτσι, αν βρισκόμαστε στις σελίδες `Product:show` και `id:123`, ο σύνδεσμος προς την `this` θα μεταφέρει και αυτή την παράμετρο.
+Ταυτόχρονα, όλες οι παράμετροι που καθορίζονται στην υπογραφή της `action<Action>()` ή `render<View>()` μεθόδου, εάν η `action<Action>()` δεν έχει οριστεί, μεταφέρονται. Έτσι, αν βρισκόμαστε στις σελίδες `Product:show` και `id:123`, ο σύνδεσμος προς την `this` θα μεταφέρει και αυτή την παράμετρο.
 
 Φυσικά, είναι δυνατόν να καθορίσετε τις παραμέτρους απευθείας:
 
@@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 Αν θέλουμε να συνδέσουμε με παρουσιαστές στο πρότυπο συστατικού, χρησιμοποιούμε την ετικέτα `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 ή στον κώδικα
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Ψευδώνυμα .[#toc-aliases]{data-version:v3.2.2}
+==============================================
+
+Μερικές φορές είναι χρήσιμο να αντιστοιχίσετε ένα εύκολα απομνημονεύσιμο ψευδώνυμο σε ένα ζεύγος Παρουσιαστής:ενέργεια. Για παράδειγμα, θα μπορούσατε να ονομάσετε την αρχική σελίδα `Front:Home:default` απλά ως `home` ή `Admin:Dashboard:default` ως `admin`.
+
+Τα ψευδώνυμα ορίζονται στη [ρύθμιση παρα |configuration] μέτρων κάτω από το κλειδί `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+Στους συνδέσμους, γράφονται χρησιμοποιώντας το σύμβολο at, για παράδειγμα:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Υποστηρίζονται σε όλες τις μεθόδους που λειτουργούν με συνδέσμους, όπως το `redirect()` και παρόμοια.
+
+
 Άκυροι σύνδεσμοι .[#toc-invalid-links]
 ======================================
 
diff --git a/application/el/how-it-works.texy b/application/el/how-it-works.texy
index 2cfe6c52b9..8593798f00 100644
--- a/application/el/how-it-works.texy
+++ b/application/el/how-it-works.texy
@@ -22,18 +22,18 @@
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← βασικές αναγκαίες τάξεις
+│   │   └── <b>RouterFactory.php</b> ← διαμόρφωση των διευθύνσεων URL
+│   ├── <b>UI/</b>                   ← παρουσιαστές, πρότυπα και λοιπά.
+│   │   ├── <b>@layout.latte</b>     ← πρότυπο κοινής διάταξης
+│   │   └── <b>Home/</b>             ← Αρχικός κατάλογος παρουσιαστών
+│   │       ├── <b>HomePresenter.php</b> ← Κλάση οικιακού παρουσιαστή
+│   │       └── <b>default.latte</b> ← πρότυπο για τη δράση default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ composer create-project nette/web-project
 
 Η εφαρμογή ξεκινά ζητώντας από τον λεγόμενο δρομολογητή να αποφασίσει ποιος από τους παρουσιαστές θα περάσει το τρέχον αίτημα για επεξεργασία. Ο δρομολογητής αποφασίζει ποιανού ευθύνη είναι. Κοιτάζει τη διεύθυνση URL εισόδου `https://example.com/product/123`, ο οποίος θέλει να `show` ένα προϊόν με `id: 123` ως ενέργεια. Είναι καλή συνήθεια να γράφετε τα ζεύγη παρουσιαστής + δράση χωρισμένα με άνω και κάτω τελεία ως `Product:show`.
 
-Έτσι, ο δρομολογητής μετατρέπει τη διεύθυνση URL σε ένα ζεύγος `Presenter:action` + παράμετροι, στην περίπτωσή μας `Product:show` + `id: 123`. Μπορείτε να δείτε πώς μοιάζει ένας δρομολογητής στο αρχείο `app/Router/RouterFactory.php` και θα τον περιγράψουμε αναλυτικά στο κεφάλαιο [Δρομολόγηση |Routing].
+Έτσι, ο δρομολογητής μετατρέπει τη διεύθυνση URL σε ένα ζεύγος `Presenter:action` + παράμετροι, στην περίπτωσή μας `Product:show` + `id: 123`. Μπορείτε να δείτε πώς μοιάζει ένας δρομολογητής στο αρχείο `app/Core/RouterFactory.php` και θα τον περιγράψουμε αναλυτικά στο κεφάλαιο [Δρομολόγηση |Routing].
 
 Ας συνεχίσουμε. Η εφαρμογή γνωρίζει ήδη το όνομα του παρουσιαστή και μπορεί να συνεχίσει. Δημιουργώντας ένα αντικείμενο `ProductPresenter`, το οποίο είναι ο κώδικας του παρουσιαστή `Product`. Πιο συγκεκριμένα, ζητάει από το DI container τη δημιουργία του presenter, επειδή η παραγωγή αντικειμένων είναι η δουλειά του.
 
@@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Στη συνέχεια, ο παρουσιαστής επιστρέφει την απάντηση. Αυτό μπορεί να είναι μια σελίδα HTML, μια εικόνα, ένα έγγραφο XML, η αποστολή ενός αρχείου από το δίσκο, JSON ή η ανακατεύθυνση σε μια άλλη σελίδα. Σημαντικό είναι ότι, αν δεν πούμε ρητά πώς να απαντήσουμε (κάτι που συμβαίνει στην περίπτωση του `ProductPresenter`), η απάντηση θα είναι η απόδοση του προτύπου με μια σελίδα HTML. Γιατί; Λοιπόν, επειδή στο 99% των περιπτώσεων θέλουμε να σχεδιάσουμε ένα πρότυπο, οπότε ο παρουσιαστής θεωρεί αυτή τη συμπεριφορά ως προεπιλεγμένη και θέλει να διευκολύνει τη δουλειά μας. Αυτό είναι το νόημα της Nette.
 
-Δεν χρειάζεται καν να δηλώσουμε ποιο πρότυπο θέλουμε να σχεδιάσουμε, αυτός εξάγει τη διαδρομή προς αυτό σύμφωνα με απλή λογική. Στην περίπτωση του presenter `Product` και της δράσης `show`, προσπαθεί να δει αν ένα από αυτά τα αρχεία προτύπων υπάρχει σε σχέση με τον κατάλογο όπου βρίσκεται η κλάση `ProductPresenter`:
+Δεν χρειάζεται καν να καθορίσουμε ποιο πρότυπο θα αναπαραχθεί- το πλαίσιο θα βρει μόνο του τη διαδρομή. Στην περίπτωση της ενέργειας `show`, απλώς προσπαθεί να φορτώσει το πρότυπο `show.latte` στον κατάλογο με την κλάση `ProductPresenter`. Προσπαθεί επίσης να βρει τη διάταξη στο αρχείο `@layout.latte` (περισσότερα για την [αναζήτηση προτύπων |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Θα προσπαθήσει επίσης να βρει τη διάταξη στο αρχείο `@layout.latte` και στη συνέχεια θα αποδώσει το πρότυπο. Τώρα ολοκληρώνεται η εργασία του παρουσιαστή και ολόκληρης της εφαρμογής. Εάν το πρότυπο δεν υπάρχει, θα επιστραφεί μια σελίδα με σφάλμα 404. Μπορείτε να διαβάσετε περισσότερα για τους παρουσιαστές στη σελίδα [Παρουσιαστές |Presenters].
+Στη συνέχεια, τα πρότυπα αποδίδονται. Με αυτόν τον τρόπο ολοκληρώνεται η εργασία του παρουσιαστή και ολόκληρης της εφαρμογής, και η εργασία έχει τελειώσει. Εάν το πρότυπο δεν υπήρχε, θα επιστρεφόταν μια σελίδα σφάλματος 404. Μπορείτε να διαβάσετε περισσότερα για τους παρουσιαστές στη σελίδα [Παρουσιαστές |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 3) ο δρομολογητής αποκωδικοποιεί τη διεύθυνση URL ως ζεύγος `Home:default`
 4) δημιουργείται ένα αντικείμενο `HomePresenter`
 5) καλείται η μέθοδος `renderDefault()` (αν υπάρχει)
-6) αποδίδεται ένα πρότυπο `templates/Home/default.latte` με διάταξη `templates/@layout.latte`
+6) αποδίδεται ένα πρότυπο `default.latte` με διάταξη `@layout.latte`
 
 
 Μπορεί να έχετε συναντήσει πολλές νέες έννοιες τώρα, αλλά πιστεύουμε ότι βγάζουν νόημα. Η δημιουργία εφαρμογών στη Nette είναι πανεύκολη.
diff --git a/application/el/modules.texy b/application/el/modules.texy
index b2bb1dffd0..5e22451dba 100644
--- a/application/el/modules.texy
+++ b/application/el/modules.texy
@@ -2,29 +2,31 @@
 ********
 
 .[perex]
-Στη Nette, οι ενότητες αντιπροσωπεύουν τις λογικές μονάδες που συνθέτουν μια εφαρμογή. Περιλαμβάνουν παρουσιαστές, πρότυπα, ενδεχομένως επίσης συστατικά και κλάσεις μοντέλων.
+Οι ενότητες φέρνουν σαφήνεια στις εφαρμογές Nette διευκολύνοντας τον εύκολο διαχωρισμό σε λογικές μονάδες.
 
-Ένας κατάλογος για τους παρουσιαστές και ένας για τα πρότυπα δεν θα ήταν αρκετός για πραγματικά έργα. Το να έχετε δεκάδες αρχεία σε έναν φάκελο είναι τουλάχιστον ανοργάνωτο. Πώς να απαλλαγείτε από αυτό; Απλώς τα χωρίζουμε σε υποκαταλόγους στο δίσκο και σε χώρους ονομάτων στον κώδικα. Και αυτό ακριβώς κάνουν τα modules της Nette.
-
-Ας ξεχάσουμε λοιπόν έναν ενιαίο φάκελο για τους παρουσιαστές και τα πρότυπα και ας δημιουργήσουμε αντ' αυτού ενότητες, για παράδειγμα `Admin` και `Front`.
+Παρόμοια με την οργάνωση των αρχείων σε φακέλους σε ένα σκληρό δίσκο, στη Nette μπορούμε να χωρίσουμε τους παρουσιαστές, τα πρότυπα και άλλες βοηθητικές κλάσεις σε ενότητες. Πώς λειτουργεί αυτό στην πράξη; Απλά με την ενσωμάτωση νέων υποκαταλόγων στη δομή. Ακολουθεί ένα παράδειγμα δομής με δύο ενότητες, Front και Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Αυτή η δομή καταλόγου θα αντικατοπτρίζεται από τα namespaces των κλάσεων, έτσι για παράδειγμα το `DashboardPresenter` θα βρίσκεται στο namespace `App\Modules\Admin\Presenters`:
+Αυτή η δομή καταλόγου αντικατοπτρίζεται στα namespaces των κλάσεων, έτσι για παράδειγμα, η `DashboardPresenter` βρίσκεται στο namespace `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Ο παρουσιαστής `Dashboard` μέσα στην ενότητα `Admin` αναφέρεται μέσα στην εφαρμογή χρησιμοποιώντας τον συμβολισμό της άνω και κάτω τελείας ως `Admin:Dashboard`, και η ενέργεια `default` ως `Admin:Dashboard:default`.
-Και πώς γνωρίζει η Nette proper ότι το `Admin:Dashboard` αντιπροσωπεύει την κλάση `App\Modules\Admin\Presenters\DashboardPresenter`; Αυτό καθορίζεται από την [αντιστοίχιση |#mapping] στη διαμόρφωση.
-Έτσι, η δεδομένη δομή δεν είναι αυστηρά καθορισμένη και μπορείτε να την τροποποιήσετε ανάλογα με τις ανάγκες σας.
+Στην εφαρμογή, αναφερόμαστε στον παρουσιαστή `Dashboard` μέσα στην ενότητα `Admin` χρησιμοποιώντας τον συμβολισμό της άνω και κάτω τελείας ως `Admin:Dashboard`. Για τη δράση του `default`, αναφερόμαστε σε αυτόν ως `Admin:Dashboard:default`.
+
+Η δομή που παρουσιάζεται δεν είναι άκαμπτη- μπορείτε να [την προσαρμόσετε πλήρως στις ανάγκες σας |#mapping] στη διαμόρφωση. .[tip]
 
-Οι ενότητες μπορούν φυσικά να περιέχουν όλα τα άλλα στοιχεία εκτός από τους παρουσιαστές και τα πρότυπα, όπως συστατικά, κλάσεις μοντέλων κ.λπ.
+Οι ενότητες μπορούν να περιλαμβάνουν όλα τα άλλα αρχεία, όπως συστατικά και βοηθητικές κλάσεις, εκτός από τους παρουσιαστές και τα πρότυπα. Αν σκέφτεστε πού να τα τοποθετήσετε αυτά, σκεφτείτε να χρησιμοποιήσετε έναν φάκελο `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Ενσωματωμένες ενότητες .[#toc-nested-modules]
 ---------------------------------------------
 
-Οι ενότητες δεν χρειάζεται να σχηματίζουν μόνο μια επίπεδη δομή, μπορείτε επίσης να δημιουργήσετε υποενότητες, για παράδειγμα:
+Οι ενότητες μπορούν να έχουν πολλαπλά επίπεδα ένθεσης, παρόμοια με μια δομή καταλόγου σε ένα δίσκο:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Έτσι, η ενότητα `Blog` χωρίζεται σε υποενότητες `Admin` και `Front`. Και πάλι, αυτό θα αντικατοπτρίζεται στα namespaces, τα οποία θα είναι `App\Modules\Blog\Admin\Presenters` κ.λπ. Ο παρουσιαστής `Dashboard` μέσα στην υποενότητα αναφέρεται ως `Blog:Admin:Dashboard`.
+Η ενότητα `Blog` χωρίζεται σε υποενότητες `Admin` και `Front`. Αυτό αντικατοπτρίζεται επίσης στα namespaces, τα οποία εμφανίζονται ως `App\UI\Blog\Admin` και παρόμοια. Για να αναφερθούμε στον παρουσιαστή `Dashboard` μέσα στην υποενότητα `Admin`, αναφερόμαστε σε αυτόν ως `Blog:Admin:Dashboard`.
+
+Η φωλεοποίηση μπορεί να είναι όσο βαθιά χρειάζεται, επιτρέποντας τη δημιουργία υπο-υπομονάδων.
 
-Η ένθεση μπορεί να προχωρήσει όσο βαθιά θέλετε, οπότε μπορούν να δημιουργηθούν υπο-υποενότητες.
+Για παράδειγμα, αν στη διαχείριση έχετε πολλούς παρουσιαστές που σχετίζονται με τη διαχείριση παραγγελιών, όπως `OrderDetail`, `OrderEdit`, `OrderDispatch`, κ.λπ., μπορείτε να δημιουργήσετε μια ενότητα `Order` στην οποία θα οργανωθούν παρουσιαστές όπως `Detail`, `Edit`, `Dispatch` και άλλοι.
 
 
 Δημιουργία συνδέσμων .[#toc-creating-links]
@@ -102,47 +118,66 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 Χαρτογράφηση .[#toc-mapping]
 ----------------------------
 
-Καθορίζει τους κανόνες με τους οποίους το όνομα της κλάσης προκύπτει από το όνομα του παρουσιαστή. Τους γράφουμε στη [διαμόρφωση |configuration] κάτω από το κλειδί `application › mapping`.
+Η αντιστοίχιση ορίζει τους κανόνες για την εξαγωγή του ονόματος της κλάσης από το όνομα του παρουσιαστή. Οι κανόνες αυτοί καθορίζονται στη [διαμόρφωση |configuration] στο κλειδί `application › mapping`.
 
-Ας ξεκινήσουμε με ένα δείγμα που δεν χρησιμοποιεί ενότητες. Θα θέλουμε απλώς οι κλάσεις presenter να έχουν το namespace `App\Presenters`. Αυτό σημαίνει ότι ένας παρουσιαστής όπως το `Home` θα πρέπει να αντιστοιχίζεται στην κλάση `App\Presenters\HomePresenter`. Αυτό μπορεί να επιτευχθεί με την ακόλουθη διαμόρφωση:
+Οι δομές καταλόγων που αναφέρθηκαν νωρίτερα σε αυτή τη σελίδα βασίζονται στην ακόλουθη αντιστοίχιση:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Το όνομα του παρουσιαστή αντικαθίσταται με τον αστερίσκο στη μάσκα κλάσης και το αποτέλεσμα είναι το όνομα της κλάσης. Εύκολο!
+Πώς λειτουργεί η χαρτογράφηση; Για καλύτερη κατανόηση, ας φανταστούμε πρώτα μια εφαρμογή χωρίς ενότητες. Θέλουμε οι κλάσεις του παρουσιαστή να υπάγονται στο χώρο ονομάτων `App\UI`, έτσι ώστε ο παρουσιαστής `Home` να αντιστοιχίζεται στην κλάση `App\UI\HomePresenter`. Αυτό μπορεί να επιτευχθεί με αυτή τη διαμόρφωση:
 
-Αν χωρίσουμε τους παρουσιαστές σε ενότητες, μπορούμε να έχουμε τη δική μας χαρτογράφηση για κάθε ενότητα:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Αυτή η αντιστοίχιση λειτουργεί αντικαθιστώντας τον αστερίσκο στη μάσκα `App\UI\*Presenter` με το όνομα του παρουσιαστή `Home`, με αποτέλεσμα το τελικό όνομα της κλάσης `App\UI\HomePresenter`. Απλό!
+
+Ωστόσο, όπως μπορείτε να δείτε στα παραδείγματα σε αυτό και σε άλλα κεφάλαια, τοποθετούμε τις κλάσεις παρουσιαστή σε επώνυμους υποκαταλόγους, π.χ. ο παρουσιαστής `Home` αντιστοιχίζεται στην κλάση `App\UI\Home\HomePresenter`. Αυτό επιτυγχάνεται με τον διπλασιασμό του αστερίσκου (απαιτεί Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Τώρα, ας προχωρήσουμε στην αντιστοίχιση των παρουσιαστών σε ενότητες. Μπορούμε να ορίσουμε συγκεκριμένες αντιστοιχίσεις για κάθε ενότητα:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Τώρα ο παρουσιαστής `Front:Home` αντιστοιχίζεται στην κλάση `App\Modules\Front\Presenters\HomePresenter` και ο παρουσιαστής `Admin:Dashboard` στην κλάση `App\Modules\Admin\Presenters\DashboardPresenter`.
+Σύμφωνα με αυτή τη διαμόρφωση, ο παρουσιαστής `Front:Home` αντιστοιχίζεται στην κλάση `App\UI\Front\Home\HomePresenter`, ενώ ο παρουσιαστής `Api:OAuth` αντιστοιχίζεται στην κλάση `App\Api\OAuthPresenter`.
 
-Είναι πιο πρακτικό να δημιουργήσετε έναν γενικό κανόνα (αστέρι) για να αντικαταστήσετε τους δύο πρώτους. Ο επιπλέον αστερίσκος θα προστεθεί στη μάσκα κλάσης μόνο για την ενότητα:
+Δεδομένου ότι οι ενότητες `Front` και `Admin` έχουν παρόμοια προσέγγιση αντιστοίχισης και είναι πιθανό να υπάρχουν περισσότερες τέτοιες ενότητες, είναι δυνατόν να δημιουργηθεί ένας γενικός κανόνας που να τις αντικαθιστά. Ένας νέος αστερίσκος για την ενότητα προστίθεται στη μάσκα κλάσης:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Τι γίνεται όμως αν χρησιμοποιούμε φωλιασμένες ενότητες και έχουμε έναν παρουσιαστή `Admin:User:Edit`; Σε αυτή την περίπτωση, το τμήμα με τον αστερίσκο που αντιπροσωπεύει την ενότητα για κάθε επίπεδο απλώς επαναλαμβάνεται και το αποτέλεσμα είναι η κλάση `App\Modules\Admin\User\Presenters\EditPresenter`.
+Για πολυεπίπεδες φωλιασμένες ενότητες, όπως ο παρουσιαστής `Admin:User:Edit`, το τμήμα αστερίσκου επαναλαμβάνεται για κάθε επίπεδο, με αποτέλεσμα την κλάση `App\UI\Admin\User\Edit\EditPresenter`.
 
-Ένας εναλλακτικός συμβολισμός είναι η χρήση ενός πίνακα που αποτελείται από τρία τμήματα αντί για συμβολοσειρά. Αυτή η σημειογραφία είναι ισοδύναμη με την προηγούμενη:
+Ένας εναλλακτικός συμβολισμός είναι η χρήση ενός πίνακα που αποτελείται από τρία τμήματα αντί για μια συμβολοσειρά. Αυτός ο συμβολισμός είναι ισοδύναμος με τον προηγούμενο:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Η προεπιλεγμένη τιμή είναι `*: *Module\*Presenter`.
+Αν έχουμε μόνο έναν κανόνα στη διαμόρφωση, τον γενικό, μπορούμε να γράψουμε συνοπτικά:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/el/presenters.texy b/application/el/presenters.texy
index 07cb8b4482..8b7a737672 100644
--- a/application/el/presenters.texy
+++ b/application/el/presenters.texy
@@ -60,7 +60,7 @@ class ArticlePresenter extends Nette\Application\UI\Presenter
 
 Είναι σημαντικό ότι `action<Action>()` καλείται πριν από την `render<View>()`, ώστε μέσα σε αυτό να μπορούμε ενδεχομένως να αλλάξουμε την επόμενη πορεία του κύκλου ζωής, δηλαδή να αλλάξουμε το πρότυπο που θα αποδοθεί και επίσης τη μέθοδο `render<View>()` που θα κληθεί, χρησιμοποιώντας το `setView('otherView')`.
 
-Οι παράμετροι από το αίτημα περνούν στη μέθοδο. Είναι δυνατόν και συνιστάται να καθορίσετε τύπους για τις παραμέτρους, π.χ. `actionShow(int $id, string $slug = null)` - αν η παράμετρος `id` λείπει ή αν δεν είναι ακέραιος αριθμός, ο παρουσιαστής επιστρέφει [σφάλμα 404 |#Error 404 etc.] και τερματίζει τη λειτουργία.
+Οι παράμετροι από το αίτημα περνούν στη μέθοδο. Είναι δυνατόν και συνιστάται να καθορίσετε τύπους για τις παραμέτρους, π.χ. `actionShow(int $id, ?string $slug = null)` - αν η παράμετρος `id` λείπει ή αν δεν είναι ακέραιος αριθμός, ο παρουσιαστής επιστρέφει [σφάλμα 404 |#Error 404 etc.] και τερματίζει τη λειτουργία.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */);
 Σφάλμα 404 κ.λπ. .[#toc-error-404-etc]
 ======================================
 
-Όταν δεν μπορούμε να ικανοποιήσουμε το αίτημα επειδή για παράδειγμα το άρθρο που θέλουμε να εμφανίσουμε δεν υπάρχει στη βάση δεδομένων, θα πετάξουμε το σφάλμα 404 χρησιμοποιώντας τη μέθοδο `error(string $message = null, int $httpCode = 404)`, η οποία αντιπροσωπεύει το σφάλμα HTTP 404:
+Όταν δεν μπορούμε να ικανοποιήσουμε το αίτημα επειδή για παράδειγμα το άρθρο που θέλουμε να εμφανίσουμε δεν υπάρχει στη βάση δεδομένων, θα πετάξουμε το σφάλμα 404 χρησιμοποιώντας τη μέθοδο `error(?string $message = null, int $httpCode = 404)`, η οποία αντιπροσωπεύει το σφάλμα HTTP 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Παράμετροι αίτησης .[#toc-request-parameters]
+=============================================
+
+Ο παρουσιαστής, όπως και κάθε στοιχείο, λαμβάνει τις παραμέτρους του από την αίτηση HTTP. Οι τιμές τους μπορούν να ανακτηθούν χρησιμοποιώντας τη μέθοδο `getParameter($name)` ή `getParameters()`. Οι τιμές είναι συμβολοσειρές ή πίνακες συμβολοσειρών, ουσιαστικά ακατέργαστα δεδομένα που λαμβάνονται απευθείας από τη διεύθυνση URL.
+
+Για μεγαλύτερη ευκολία, συνιστούμε να κάνετε τις παραμέτρους προσβάσιμες μέσω ιδιοτήτων. Απλά σχολιάστε τις με την εντολή `#[Parameter]` χαρακτηριστικό:
+
+```php
+use Nette\Application\Attributes\Parameter;  // αυτή η γραμμή είναι σημαντική
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // πρέπει να είναι δημόσια
+}
+```
+
+Για τις ιδιότητες, προτείνουμε να προσδιορίσετε τον τύπο δεδομένων (π.χ. `string`). Στη συνέχεια, η Nette θα μετατρέψει αυτόματα την τιμή με βάση αυτόν. Οι τιμές των παραμέτρων μπορούν επίσης να [επικυρωθούν |#Validation of Parameters].
+
+Κατά τη δημιουργία ενός συνδέσμου, μπορείτε να ορίσετε απευθείας την τιμή για τις παραμέτρους:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Εμμένουσες παράμετροι .[#toc-persistent-parameters]
 ===================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Εάν το `$this->lang` έχει μια τιμή όπως `'en'`, τότε οι σύνδεσμοι που δημιουργούνται με χρήση των `link()` ή `n:href` θα περιέχουν επίσης την παράμετρο `lang=en`. Και όταν ο σύνδεσμος πατηθεί, θα είναι και πάλι `$this->lang = 'en'`.
 
-Για τις ιδιότητες, συνιστούμε να περιλαμβάνετε τον τύπο δεδομένων (π.χ. `string`) και μπορείτε επίσης να συμπεριλάβετε μια προεπιλεγμένη τιμή. Οι τιμές των παραμέτρων μπορούν να [επικυρωθούν |#Validation of Persistent Parameters].
+Για τις ιδιότητες, συνιστούμε να συμπεριλάβετε τον τύπο δεδομένων (π.χ. `string`) και μπορείτε επίσης να συμπεριλάβετε μια προεπιλεγμένη τιμή. Οι τιμές των παραμέτρων μπορούν να [επικυρωθούν |#Validation of Parameters].
 
 Οι μόνιμες παράμετροι μεταβιβάζονται μεταξύ όλων των ενεργειών ενός συγκεκριμένου παρουσιαστή από προεπιλογή. Για να τις περάσετε μεταξύ πολλαπλών παρουσιαστών, πρέπει να τις ορίσετε είτε:
 
@@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Όσα έχουμε δείξει μέχρι στιγμής σε αυτό το κεφάλαιο μάλλον αρκούν. Οι επόμενες γραμμές απευθύνονται σε όσους ενδιαφέρονται για τους παρουσιαστές σε βάθος και θέλουν να μάθουν τα πάντα.
 
 
-Απαίτηση και παράμετροι .[#toc-requirement-and-parameters]
-----------------------------------------------------------
+Επικύρωση των παραμέτρων .[#toc-validation-of-parameters]
+---------------------------------------------------------
 
-Το αίτημα που χειρίζεται ο παρουσιαστής είναι το αντικείμενο [api:Nette\Application\Request] και επιστρέφεται από τη μέθοδο του παρουσιαστή `getRequest()`. Περιλαμβάνει έναν πίνακα παραμέτρων και κάθε μία από αυτές ανήκει είτε σε κάποιο από τα συστατικά είτε απευθείας στον παρουσιαστή (ο οποίος στην πραγματικότητα είναι επίσης ένα συστατικό, αν και ειδικό). Έτσι, η Nette ανακατανέμει τις παραμέτρους και περνάει μεταξύ των επιμέρους συστατικών (και του παρουσιαστή) καλώντας τη μέθοδο `loadState(array $params)`. Οι παράμετροι μπορούν να ληφθούν με τη μέθοδο `getParameters(): array`, μεμονωμένα με τη χρήση του `getParameter($name)`. Οι τιμές των παραμέτρων είναι συμβολοσειρές ή πίνακες συμβολοσειρών, είναι ουσιαστικά ακατέργαστα δεδομένα που λαμβάνονται απευθείας από μια διεύθυνση URL.
+Οι τιμές των [παραμέτρων αίτησης |#request parameters] και των [μόνιμων παραμέτρων |#persistent parameters] που λαμβάνονται από τις διευθύνσεις URL εγγράφονται στις ιδιότητες από τη μέθοδο `loadState()`. Ελέγχει επίσης αν ο τύπος δεδομένων που καθορίζεται στην ιδιότητα ταιριάζει, διαφορετικά θα απαντήσει με σφάλμα 404 και η σελίδα δεν θα εμφανιστεί.
 
-
-Επικύρωση μόνιμων παραμέτρων .[#toc-validation-of-persistent-parameters]
-------------------------------------------------------------------------
-
-Οι τιμές των [μόνιμων παραμέτρων |#persistent parameters] που λαμβάνονται από τις διευθύνσεις URL εγγράφονται στις ιδιότητες με τη μέθοδο `loadState()`. Ελέγχει επίσης αν ο τύπος δεδομένων που καθορίζεται στην ιδιότητα ταιριάζει, διαφορετικά θα απαντήσει με σφάλμα 404 και η σελίδα δεν θα εμφανιστεί.
-
-Ποτέ μην εμπιστεύεστε τυφλά τις μόνιμες παραμέτρους, καθώς μπορούν εύκολα να αντικατασταθούν από τον χρήστη στη διεύθυνση URL. Για παράδειγμα, με αυτόν τον τρόπο ελέγχουμε αν το `$this->lang` είναι μεταξύ των υποστηριζόμενων γλωσσών. Ένας καλός τρόπος για να το κάνετε αυτό είναι να παρακάμψετε τη μέθοδο `loadState()` που αναφέρθηκε παραπάνω:
+Ποτέ μην εμπιστεύεστε τυφλά τις παραμέτρους, καθώς μπορούν εύκολα να αντικατασταθούν από τον χρήστη στη διεύθυνση URL. Για παράδειγμα, με αυτόν τον τρόπο ελέγχουμε αν το `$this->lang` είναι μεταξύ των υποστηριζόμενων γλωσσών. Ένας καλός τρόπος για να το κάνετε αυτό είναι να παρακάμψετε τη μέθοδο `loadState()` που αναφέρθηκε παραπάνω:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Αποθήκευση και επαναφορά της αίτησης .[#toc-save-and-restore-the-request]
 -------------------------------------------------------------------------
 
-Μπορείτε να αποθηκεύσετε την τρέχουσα αίτηση σε μια συνεδρία ή να την επαναφέρετε από τη συνεδρία και να αφήσετε τον παρουσιαστή να την εκτελέσει ξανά. Αυτό είναι χρήσιμο, για παράδειγμα, όταν ένας χρήστης συμπληρώνει μια φόρμα και λήγει η σύνδεσή του. Για να μην χαθούν δεδομένα, πριν από την ανακατεύθυνση στη σελίδα σύνδεσης, αποθηκεύουμε το τρέχον αίτημα στη σύνοδο χρησιμοποιώντας το `$reqId = $this->storeRequest()`, το οποίο επιστρέφει ένα αναγνωριστικό με τη μορφή σύντομης συμβολοσειράς και το περνάει ως παράμετρο στον παρουσιαστή σύνδεσης.
+Το αίτημα που χειρίζεται ο παρουσιαστής είναι ένα αντικείμενο [api:Nette\Application\Request] και επιστρέφεται από τη μέθοδο του παρουσιαστή `getRequest()`.
+
+Μπορείτε να αποθηκεύσετε την τρέχουσα αίτηση σε μια συνεδρία ή να την επαναφέρετε από τη συνεδρία και να αφήσετε τον παρουσιαστή να την εκτελέσει ξανά. Αυτό είναι χρήσιμο, για παράδειγμα, όταν ένας χρήστης συμπληρώνει μια φόρμα και η σύνδεσή του λήγει. Για να μην χαθούν δεδομένα, πριν από την ανακατεύθυνση στη σελίδα σύνδεσης, αποθηκεύουμε την τρέχουσα αίτηση στη σύνοδο χρησιμοποιώντας τη μέθοδο `$reqId = $this->storeRequest()`, η οποία επιστρέφει ένα αναγνωριστικό με τη μορφή σύντομης συμβολοσειράς και το περνάει ως παράμετρο στον παρουσιαστή σύνδεσης.
 
 Μετά την είσοδο, καλούμε τη μέθοδο `$this->restoreRequest($reqId)`, η οποία παραλαμβάνει το αίτημα από τη σύνοδο και το προωθεί σε αυτήν. Η μέθοδος επαληθεύει ότι το αίτημα δημιουργήθηκε από τον ίδιο χρήστη που τώρα έχει συνδεθεί είναι. Αν συνδεθεί άλλος χρήστης ή το κλειδί είναι άκυρο, δεν κάνει τίποτα και το πρόγραμμα συνεχίζει.
 
@@ -362,7 +384,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Μπορείτε επίσης να επικαλεστείτε την κανονικοποίηση χειροκίνητα χρησιμοποιώντας τη μέθοδο `canonicalize()`, η οποία, όπως και η μέθοδος `link()`, λαμβάνει τον παρουσιαστή, τις ενέργειες και τις παραμέτρους ως ορίσματα. Δημιουργεί έναν σύνδεσμο και τον συγκρίνει με την τρέχουσα διεύθυνση URL. Εάν είναι διαφορετική, ανακατευθύνει στον δημιουργημένο σύνδεσμο.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// ανακατευθύνει εάν το $slug είναι διαφορετικό από το $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Περιορισμός πρόσβασης με χρήση `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+----------------------------------------------------------------------------------------------------------
+
+Το `#[Requires]` παρέχει προηγμένες επιλογές για τον περιορισμό της πρόσβασης στους παρουσιαστές και τις μεθόδους τους. Μπορεί να χρησιμοποιηθεί για τον προσδιορισμό μεθόδων HTTP, την απαίτηση αιτήσεων AJAX, τον περιορισμό της πρόσβασης στην ίδια προέλευση και τον περιορισμό της πρόσβασης μόνο στην προώθηση. Το χαρακτηριστικό μπορεί να εφαρμοστεί σε κλάσεις παρουσιαστών καθώς και σε μεμονωμένες μεθόδους όπως οι `action<Action>()`, `render<View>()`, `handle<Signal>()`, και `createComponent<Name>()`.
+
+Μπορείτε να καθορίσετε αυτούς τους περιορισμούς:
+- σε μεθόδους HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- AJAX: `#[Requires(ajax: true)]`
+- πρόσβαση μόνο από την ίδια προέλευση: `#[Requires(sameOrigin: true)]`
+- πρόσβαση μόνο μέσω προώθησης: `#[Requires(forward: true)]`
+- περιορισμοί σε συγκεκριμένες ενέργειες: `#[Requires(actions: 'default')]`
+
+Για λεπτομέρειες, ανατρέξτε στην ενότητα [Πώς να χρησιμοποιήσετε το Requires attribute |best-practices:attribute-requires].
+
+
+Έλεγχος μεθόδου HTTP .[#toc-http-method-check]
+----------------------------------------------
+
+Στη Nette, οι παρουσιαστές επαληθεύουν αυτόματα τη μέθοδο HTTP κάθε εισερχόμενης αίτησης κυρίως για λόγους ασφαλείας. Από προεπιλογή, επιτρέπονται οι μέθοδοι `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Εάν θέλετε να ενεργοποιήσετε επιπλέον μεθόδους, όπως η `OPTIONS`, μπορείτε να χρησιμοποιήσετε την εντολή `#[Requires]` (από την εφαρμογή Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Στην έκδοση 3.1, η επαλήθευση πραγματοποιείται στο `checkHttpMethod()`, το οποίο ελέγχει αν η μέθοδος που καθορίζεται στην αίτηση περιλαμβάνεται στον πίνακα `$presenter->allowedMethods`. Προσθέστε μια μέθοδο ως εξής:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Είναι ζωτικής σημασίας να τονιστεί ότι αν επιτρέψετε τη μέθοδο `OPTIONS`, πρέπει επίσης να τη χειριστείτε σωστά μέσα στον παρουσιαστή σας. Αυτή η μέθοδος χρησιμοποιείται συχνά ως το λεγόμενο preflight request, το οποίο οι φυλλομετρητές στέλνουν αυτόματα πριν από το πραγματικό αίτημα, όταν είναι απαραίτητο να καθοριστεί αν το αίτημα επιτρέπεται από την άποψη της πολιτικής CORS (Cross-Origin Resource Sharing). Εάν επιτρέψετε αυτή τη μέθοδο αλλά δεν υλοποιήσετε μια κατάλληλη απάντηση, μπορεί να οδηγήσει σε ασυνέπειες και πιθανά ζητήματα ασφάλειας.
+
+
 Περαιτέρω ανάγνωση .[#toc-further-reading]
 ==========================================
 
diff --git a/application/el/routing.texy b/application/el/routing.texy
index 448fa6f67b..78ebb607a0 100644
--- a/application/el/routing.texy
+++ b/application/el/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Σύνθετος συμβολισμός .[#toc-advanced-notation]
 ----------------------------------------------
 
-Η δεύτερη παράμετρος της διαδρομής, την οποία συχνά γράφουμε με τη μορφή `Presenter:action`, είναι μια συντομογραφία, την οποία μπορούμε επίσης να γράψουμε με τη μορφή πεδίου, όπου δηλώνουμε απευθείας τις (προεπιλεγμένες) τιμές των επιμέρους παραμέτρων:
+Ο στόχος μιας διαδρομής, που συνήθως γράφεται με τη μορφή `Presenter:action`, μπορεί επίσης να εκφραστεί με τη χρήση ενός πίνακα που ορίζει τις επιμέρους παραμέτρους και τις προεπιλεγμένες τιμές τους:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Ή μπορούμε να χρησιμοποιήσουμε αυτή τη μορφή, παρατηρήστε την αναδιατύπωση της κανονικής έκφρασης επικύρωσης:
+Για μια πιο λεπτομερή προδιαγραφή, μπορεί να χρησιμοποιηθεί μια ακόμη πιο εκτεταμένη μορφή, όπου εκτός από τις προεπιλεγμένες τιμές, μπορούν να οριστούν και άλλες ιδιότητες παραμέτρων, όπως μια κανονική έκφραση επικύρωσης (βλ. την παράμετρο `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Αυτές οι πιο ομιλητικές μορφές είναι χρήσιμες για την προσθήκη άλλων μεταδεδομένων.
+Είναι σημαντικό να σημειωθεί ότι εάν οι παράμετροι που ορίζονται στον πίνακα δεν περιλαμβάνονται στη μάσκα διαδρομής, οι τιμές τους δεν μπορούν να αλλάξουν, ούτε καν με τη χρήση παραμέτρων ερωτήματος που καθορίζονται μετά από ένα ερωτηματικό στη διεύθυνση URL.
 
 
 Φίλτρα και μεταφράσεις .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Ενσωμάτωση .[#toc-integration]
 ==============================
 
-Για να συνδέσουμε τον δρομολογητή μας στην εφαρμογή, πρέπει να ενημερώσουμε το DI container σχετικά με αυτόν. Ο ευκολότερος τρόπος είναι να προετοιμάσουμε το εργοστάσιο που θα κατασκευάσει το αντικείμενο του δρομολογητή και να πούμε στη διαμόρφωση του δοχείου να το χρησιμοποιήσει. Ας πούμε λοιπόν ότι γράφουμε μια μέθοδο για το σκοπό αυτό `App\Router\RouterFactory::createRouter()`:
+Για να συνδέσουμε τον δρομολογητή μας στην εφαρμογή, πρέπει να ενημερώσουμε το DI container σχετικά με αυτόν. Ο ευκολότερος τρόπος είναι να προετοιμάσουμε το εργοστάσιο που θα κατασκευάσει το αντικείμενο του δρομολογητή και να πούμε στη διαμόρφωση του δοχείου να το χρησιμοποιήσει. Ας πούμε λοιπόν ότι γράφουμε μια μέθοδο για το σκοπό αυτό `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ class RouterFactory
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Οποιεσδήποτε εξαρτήσεις, όπως μια σύνδεση βάσης δεδομένων κ.λπ., περνούν στη μέθοδο factory ως παράμετροι με τη χρήση [αυτόματης σύνδεσης |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ $router->addRoute(/* ... */);
 Έτσι και πάλι θα δημιουργήσουμε μια μέθοδο που θα κατασκευάσει ένα δρομολογητή, για παράδειγμα:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Ή θα δημιουργήσουμε αντικείμενα απευθείας:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/el/templates.texy b/application/el/templates.texy
index 4b83599f45..dfe884dd1b 100644
--- a/application/el/templates.texy
+++ b/application/el/templates.texy
@@ -34,35 +34,81 @@
 Ορίζει το μπλοκ `content`, το οποίο εισάγεται στη θέση του `{include content}` στη διάταξη, και επίσης επαναπροσδιορίζει το μπλοκ `title`, το οποίο αντικαθιστά το `{block title}` στη διάταξη. Προσπαθήστε να φανταστείτε το αποτέλεσμα.
 
 
-Αναζήτηση προτύπων .[#toc-search-for-templates]
------------------------------------------------
+Αναζήτηση προτύπου .[#toc-template-lookup]
+------------------------------------------
 
-Η διαδρομή προς τα πρότυπα προκύπτει σύμφωνα με μια απλή λογική. Προσπαθεί να δει αν ένα από αυτά τα αρχεία προτύπων υπάρχει σε σχέση με τον κατάλογο όπου βρίσκεται η κλάση presenter, όπου `<Presenter>` είναι το όνομα του τρέχοντος παρουσιαστή και `<view>` είναι το όνομα της τρέχουσας δράσης:
+Στους παρουσιαστές, δεν χρειάζεται να καθορίσετε ποιο πρότυπο πρέπει να αποδοθεί- το πλαίσιο θα καθορίσει αυτόματα τη διαδρομή, διευκολύνοντας την κωδικοποίηση για εσάς.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Αν χρησιμοποιείτε μια δομή καταλόγου όπου κάθε παρουσιαστής έχει το δικό του κατάλογο, απλά τοποθετήστε το πρότυπο σε αυτόν τον κατάλογο κάτω από το όνομα της ενέργειας (π.χ. προβολή). Για παράδειγμα, για τη δράση `default`, χρησιμοποιήστε το πρότυπο `default.latte`:
 
-Αν το πρότυπο δεν βρεθεί, θα προσπαθήσει να ψάξει στον κατάλογο `templates` ένα επίπεδο πιο πάνω, δηλαδή στο ίδιο επίπεδο με τον κατάλογο με την κλάση παρουσιαστή.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Εάν το πρότυπο δεν βρεθεί ούτε εκεί, η απάντηση είναι ένα [σφάλμα 404 |presenters#Error 404 etc.].
+Εάν χρησιμοποιείτε μια δομή όπου οι παρουσιαστές βρίσκονται μαζί σε έναν κατάλογο και τα πρότυπα σε έναν φάκελο `templates`, αποθηκεύστε το είτε σε ένα αρχείο `<Presenter>.<view>.latte` είτε στο `<Presenter>/<view>.latte`:
 
-Μπορείτε επίσης να αλλάξετε την προβολή χρησιμοποιώντας το `$this->setView('otherView')`. Ή, αντί για αναζήτηση, καθορίστε απευθείας το όνομα του αρχείου προτύπου χρησιμοποιώντας τη διεύθυνση `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+Ο κατάλογος `templates` μπορεί επίσης να τοποθετηθεί ένα επίπεδο ψηλότερα, στο ίδιο επίπεδο με τον κατάλογο με τις κλάσεις παρουσιαστών.
+
+Εάν το πρότυπο δεν βρεθεί, ο παρουσιαστής απαντά με το [σφάλμα 404 - σελίδα δεν βρέθηκε |presenters#Error 404 etc].
+
+Μπορείτε να αλλάξετε την προβολή χρησιμοποιώντας το `$this->setView('anotherView')`. Είναι επίσης δυνατό να καθορίσετε απευθείας το αρχείο προτύπου με το `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Μπορείτε να αλλάξετε τις διαδρομές στις οποίες αναζητούνται τα πρότυπα υπερκαλύπτοντας τη μέθοδο [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών διαδρομών αρχείων.
+Τα αρχεία στα οποία αναζητούνται τα πρότυπα μπορούν να αλλάξουν με την παράκαμψη της μεθόδου [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών ονομάτων αρχείων.
+
+
+Αναζήτηση προτύπων διάταξης .[#toc-layout-template-lookup]
+----------------------------------------------------------
+
+Η Nette αναζητά επίσης αυτόματα το αρχείο διάταξης.
+
+Εάν χρησιμοποιείτε μια δομή καταλόγου όπου κάθε παρουσιαστής έχει το δικό του κατάλογο, τοποθετήστε τη διάταξη είτε στο φάκελο με τον παρουσιαστή, εάν αφορά μόνο αυτόν, είτε ένα επίπεδο ψηλότερα εάν είναι κοινή για πολλούς παρουσιαστές:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Εάν χρησιμοποιείτε μια δομή όπου οι παρουσιαστές είναι ομαδοποιημένοι σε έναν κατάλογο και τα πρότυπα βρίσκονται σε έναν φάκελο `templates`, η διάταξη αναμένεται στις ακόλουθες θέσεις:
 
-Η διάταξη αναμένεται στα ακόλουθα αρχεία:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` διάταξη κοινή για πολλούς παρουσιαστές
+Εάν ο παρουσιαστής βρίσκεται σε μια [ενότητα |modules], θα αναζητήσει επίσης πιο πάνω στο δέντρο καταλόγων σύμφωνα με την ένθεση της ενότητας.
 
-`<Presenter>` είναι το όνομα του τρέχοντος παρουσιαστή και `<layout>` είναι το όνομα της διάταξης, η οποία είναι εξ ορισμού `'layout'`. Το όνομα μπορεί να αλλάξει με το `$this->setLayout('otherLayout')`, έτσι ώστε να δοκιμάζονται τα αρχεία `@otherLayout.latte`.
+Το όνομα της διάταξης μπορεί να αλλάξει χρησιμοποιώντας το `$this->setLayout('layoutAdmin')` και τότε θα αναμένεται στο αρχείο `@layoutAdmin.latte`. Μπορείτε επίσης να καθορίσετε απευθείας το αρχείο προτύπου διάταξης χρησιμοποιώντας το `$this->setLayout('/path/to/template.latte')`.
 
-Μπορείτε επίσης να καθορίσετε απευθείας το όνομα του αρχείου του προτύπου διάταξης χρησιμοποιώντας το `$this->setLayout('/path/to/template.latte')`. Η χρήση του `$this->setLayout(false)` θα απενεργοποιήσει την αναζήτηση διάταξης.
+Η χρήση του `$this->setLayout(false)` ή της ετικέτας `{layout none}` μέσα στο πρότυπο απενεργοποιεί την αναζήτηση διάταξης.
 
 .[note]
-Μπορείτε να αλλάξετε τις διαδρομές στις οποίες αναζητούνται τα πρότυπα με την παράκαμψη της μεθόδου [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών διαδρομών αρχείων.
+Τα αρχεία στα οποία αναζητούνται τα πρότυπα διάταξης μπορούν να αλλάξουν με την παράκαμψη της μεθόδου [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών ονομάτων αρχείων.
 
 
 Μεταβλητές στο πρότυπο .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
 Μπορείτε επίσης να αφεθείτε στην πολυτέλεια του ψιθυρίσματος στα πρότυπα, απλά εγκαταστήστε το πρόσθετο Latte στο PhpStorm και καθορίστε το όνομα της κλάσης στην αρχή του προτύπου, δείτε το άρθρο "Latte: πώς να πληκτρολογήσετε το σύστημα":https://blog.nette.org/el/latte-pos-na-chresimopoiesete-to-systema-typon:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte έκδοση 3 προσφέρει έναν πιο προηγμένο τρόπο δημιουργώντας μια [επέκταση |latte:creating-extension] για κάθε έργο ιστού. Εδώ είναι ένα πρόχειρο παράδειγμα μιας τέτοιας κλάσης:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ protected function beforeRender(): void
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Ο μεταφραστής μπορεί στη συνέχεια να χρησιμοποιηθεί, για παράδειγμα, ως φίλτρο `|translate`, με πρόσθετες παραμέτρους που περνούν στη μέθοδο `translate()` (βλ. `foo, bar`):
diff --git a/application/en/@home.texy b/application/en/@home.texy
index fac8c0d767..0892ae2d2d 100644
--- a/application/en/@home.texy
+++ b/application/en/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | version   | compatible with PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 – 8.2
-| Nette Application 3.1 | PHP 7.2 – 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 – 8.0
 | Nette Application 2.4 | PHP 5.6 – 8.0
 
diff --git a/application/en/ajax.texy b/application/en/ajax.texy
index f43ff28c2f..819a6e4627 100644
--- a/application/en/ajax.texy
+++ b/application/en/ajax.texy
@@ -3,10 +3,10 @@ AJAX & Snippets
 
 <div class=perex>
 
-Modern web applications nowadays run half on a server and half in a browser. AJAX is a vital uniting factor. What support does the Nette Framework offer?
-- sending template fragments (so-called *snippets*)
+In the era of modern web applications, where functionality often spans between the server and the browser, AJAX is an essential connecting element. What options does the Nette Framework offer in this area?
+- sending parts of the template, so-called snippets
 - passing variables between PHP and JavaScript
-- AJAX applications debugging
+- tools for debugging AJAX requests
 
 </div>
 
@@ -14,29 +14,32 @@ Modern web applications nowadays run half on a server and half in a browser. AJA
 AJAX Request
 ============
 
-An AJAX request does not differ from a classic request - the presenter is called with a specific view and parameters. It is also up to the presenter how to respond to it: it can use its own routine, which returns an HTML code fragment (HTML snippet), an XML document, a JSON object, or JavaScript code.
+An AJAX request fundamentally does not differ from a classic HTTP request. A presenter is called with specific parameters. It's up to the presenter how to respond to the request - it can return data in JSON format, send a part of HTML code, an XML document, etc.
 
-On the server side, an AJAX request can be detected using the service method [encapsulating the HTTP request |http:request] `$httpRequest->isAjax()` (detects based on the HTTP header `X-Requested-With`). Inside the presenter, a shortcut is available in the form of the method `$this->isAjax()`.
+On the browser side, we initiate an AJAX request using the `fetch()` function:
 
-There is a pre-processed object called `payload` dedicated to sending data to the browser in JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// processing the response
+});
 ```
 
-For a full control over your JSON output use the `sendJson` method in your presenter. It terminates presenter immediately and you'll do without a template:
+On the server side, an AJAX request is recognized by the `$httpRequest->isAjax()` method of the service [encapsulating the HTTP request |http:request]. It uses the HTTP header `X-Requested-With`, so it's essential to send it. Within the presenter, you can use the `$this->isAjax()` method.
+
+If you want to send data in JSON format, use the [`sendJson()` |presenters#Sending a response] method. The method also terminates the presenter's activity.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-If we want to send HTML, we can either set a special template for AJAX requests:
+If you plan to respond with a special template designed for AJAX, you can do it as follows:
 
 ```php
 public function handleClick($param): void
@@ -49,22 +52,38 @@ public function handleClick($param): void
 ```
 
 
+Snippets
+========
+
+The most powerful tool offered by Nette for connecting the server with the client are snippets. With them, you can turn an ordinary application into an AJAX one with minimal effort and a few lines of code. The Fifteen example demonstrates how it all works, and its code can be found on [GitHub |https://github.com/nette-examples/fifteen].
+
+Snippets, or clippings, allow you to update only parts of the page, instead of reloading the entire page. This is faster and more efficient, and also provides a more comfortable user experience. Snippets might remind you of Hotwire for Ruby on Rails or Symfony UX Turbo. Interestingly, Nette introduced snippets 14 years earlier.
+
+How do snippets work? When the page is first loaded (a non-AJAX request), the entire page, including all snippets, is loaded. When the user interacts with the page (e.g., clicks a button, submits a form, etc.), instead of loading the entire page, an AJAX request is made. The code in the presenter performs the action and decides which snippets need updating. Nette renders these snippets and sends them in the form of a JSON array. The handling code in the browser then inserts the received snippets back into the page. Therefore, only the code of the changed snippets is transferred, saving bandwidth and speeding up loading compared to transferring the entire page content.
+
+
 Naja
-====
+----
 
-The [Naja library|https://naja.js.org] is used to handle AJAX requests on the browser side. [Install |https://naja.js.org/#/guide/01-install-setup-naja] it as a node.js package (to use with Webpack, Rollup, Vite, Parcel and more):
+To handle snippets on the browser side, the [Naja library |https://naja.js.org] is used. [Install it |https://naja.js.org/#/guide/01-install-setup-naja] as a node.js package (for use with applications such as Webpack, Rollup, Vite, Parcel, and others):
 
 ```shell
 npm install naja
 ```
 
-…or insert it directly into the page template:
+... or insert it directly into the page template:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-To create an AJAX request from a regular link (signal) or form submittion, simply mark the relevant link, form, or button with the class `ajax`:
+First you need to [initialize |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] the library:
+
+```js
+naja.initialize();
+```
+
+To make an ordinary link (signal) or form submission an AJAX request, simply mark the respective link, form, or button with the `ajax` class:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ To create an AJAX request from a regular link (signal) or form submittion, simpl
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippets
-========
-
-There is a far more powerful tool of built-in AJAX support – snippets. Using them makes it possible to turn a regular application into an AJAX one using only a few lines of code. How it all works is demonstrated in the Fifteen example whose code is also accessible in the build or on [GitHub |https://github.com/nette-examples/fifteen].
-
-The way snippets work is that the whole page is transferred during the initial (i.e. non-AJAX) request and then with every AJAX [subrequest |components#signal] (request of the same view of the same presenter) only the code of the changed parts is transferred in the `payload` repository mentioned earlier.
+Redrawing Snippets
+------------------
 
-Snippets may remind you of Hotwire for Ruby on Rails or Symfony UX Turbo, but Nette came up with them fourteen years earlier.
-
-
-Invalidation of Snippets
-========================
-
-Each descendant of class [Control |components] (which a Presenter is too) is able to remember whether there were any changes during a request that require it to re-render. There are a pair of methods to handle this: `redrawControl()` and  `isControlInvalid()`. An example:
+Every object of the [Control |components] class (including the Presenter itself) keeps a record of whether changes have occurred that necessitate its redrawing. The `redrawControl()` method is employed for this purpose.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// The object has to re-render after the user has logged in
+	// after logging in, it is necessary to redraw the relevant part
 	$this->redrawControl();
 	// ...
 }
 ```
-Nette however offers an even finer resolution than whole components. The listed methods accept the name of a so-called "snippet" as an optional parameter. A "snippet" is basically an element in your template marked for that purpose by a Latte tag, more on that later. Thus it is possible to ask a component to redraw only *parts* of its template. If the entire component is invalidated then all of its snippets are re-rendered. A component is “invalid” also if any of its subcomponents is invalid.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // invalidates the snippet named 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, at least one snippet is invalid
+Nette also allows for finer control of what needs redrawing. The aforementioned method can take the snippet name as an argument. Thus, it's possible to invalidate (meaning: force a redraw) at the template part level. If the entire component is invalidated, every snippet of it is also redrawn:
 
-$this->redrawControl(); // invalidates the whole component, every snippet
-$this->isControlInvalid('footer'); // -> true
+```php
+// invalidates the 'header' snippet
+$this->redrawControl('header');
 ```
 
-A component which receives a signal is automatically marked for redrawing.
-
-Thanks to snippet redrawing we know exactly which parts of which elements should be re-rendered.
-
-
-Tag `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
 
-Rendering of the page proceeds very similarly to a regular request: the same templates are loaded, etc. The vital part is, however, to leave out the parts that are not supposed to reach the output; the other parts shall be associated with an identifier and sent to the user in a comprehensible format for a JavaScript handler.
+Snippets in Latte
+-----------------
 
-
-Syntax
-------
-
-If there is a control or a snippet in the template, we have to wrap it using the `{snippet} ... {/snippet}` pair tag - it will make sure that the rendered snippet will be "cut out" and sent to the browser. It will also enclose it in a helper `<div>` tag (it is possible to use a different one). In the following example a snippet named `header` is defined. It may as well represent the template of a component:
+Using snippets in Latte is extremely easy. To define a part of the template as a snippet, simply wrap it in `{snippet}` and `{/snippet}` tags:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ If there is a control or a snippet in the template, we have to wrap it using the
 {/snippet}
 ```
 
-A snippet of a type other than `<div>` or a snippet with additional HTML attributes is achieved by using the attribute variant:
+The snippet creates an element `<div>` in the HTML page with a specially generated `id`. When redrawing a snippet, the content of this element is updated. Therefore, when the page is initially rendered, all snippets must also be rendered, even if they may initially be empty.
+
+You can also create a snippet with an element other than `<div>` using an n:attribute:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ A snippet of a type other than `<div>` or a snippet with additional HTML attribu
 ```
 
 
-Dynamic Snippets
-================
+Snippet Areas
+-------------
 
-In Nette you can also define snippets with a dynamic name based on a runtime parameter. This is most suitable for various lists where we need to change just one row but we don't want transfer the whole list along with it. An example of this would be:
+Snippet names can also be expressions:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-There is one static snippet called `itemsContainer`, containing several dynamic snippets: `item-0`, `item-1` and so on.
+This way, we'll get several snippets like `item-0`, `item-1`, etc. If we were to directly invalidate a dynamic snippet (e.g., `item-1`), nothing would be redrawn. The reason being, snippets function as true excerpts and only they themselves are rendered directly. However, in the template, there isn't technically a snippet named `item-1`. It only emerges when executing the surrounding code of the snippet, in this case, the foreach loop. Hence, we'll mark the part of the template that needs to be executed with the `{snippetArea}` tag:
 
-You can't redraw a dynamic snippet directly (redrawing of `item-1` has no effect), you have to redraw its parent snippet (in this example `itemsContainer`). This causes the code of the parent snippet to be executed, but then just its sub-snippets are sent to the browser. If you want to send over just one of the sub-snippets, you have to modify input for the parent snippet to not generate the other sub-snippets.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-In the example above you have to make sure that for an AJAX request only one item will be added to the `$list` array, therefore the `foreach` loop will print just one dynamic snippet.
+And we'll redraw both the individual snippet and the entire overarching area:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+It's also essential to ensure that the `$items` array contains only the items that should be redrawn.
 
-Snippets in an Included Template
-================================
-
-It can happen that the snippet is in a template which is being included from a different template. In that case we need to wrap the inclusion code in the second template with the `snippetArea` tag, then we redraw both the snippetArea and the actual snippet.
-
-Tag `snippetArea` ensures that the code inside is executed but only the actual snippet in the included template is sent to the browser.
+When inserting another template into the main one using the `{include}` tag, which has snippets, it's necessary to again wrap the included template in a `snippetArea` and invalidate both the snippet and the area together:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-You can also combine it with dynamic snippets.
 
+Snippets in Components
+----------------------
 
-Adding and Deleting
-===================
-
-If you add a new item into the list and invalidate `itemsContainer`, the AJAX request returns snippets including the new one, but the javascript handler won’t be able to render it. This is because there is no HTML element with the newly created ID.
-
-In this case, the simplest way is to wrap the whole list in one more snippet and invalidate it all:
+You can create snippets within [components], and Nette will automatically redraw them. However, there's a specific limitation: to redraw snippets, it calls the `render()` method without any parameters. Thus, passing parameters in the template won't work:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Sending User Data
+-----------------
+
+Along with snippets, you can send any additional data to the client. Simply write them into the `payload` object:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	// ...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-The same goes for deleting an item. It would be possible to send empty snippet, but usually lists can be paginated and it would be complicated to implement deleting one item and loading another (which used to be on a different page of the paginated list).
-
 
-Sending Parameters to Component
-===============================
+Sending Parameters
+==================
 
 When we send parameters to the component via AJAX request, whether signal parameters or persistent parameters, we must provide their global name, which also contains the name of the component. The full name of parameter returns the `getParameterId()` method.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-And handle method with s corresponding parameters in component.
+A handle method with the corresponding parameters in the component:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/en/bootstrap.texy b/application/en/bootstrap.texy
index c763e715a3..a950df1e88 100644
--- a/application/en/bootstrap.texy
+++ b/application/en/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// The configurator is responsible for setting up the application environment and services.
+		$this->configurator = new Configurator;
+		// Set the directory for temporary files generated by Nette (e.g. compiled templates)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette is smart, and the development mode turns on automatically,
+		// or you can enable for a specific IP address it by uncommenting the following line:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Enables Tracy: the ultimate "swiss army knife" debugging tool.
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: autoloads all classes in the given directory
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Load configuration files
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php
 =========
 
-In the case of web applications, the initial file is `index.php`, which is located in the public directory `www/`. It lets the `Bootstrap` class to initialize the environment and return the `$configurator` which creates DI container. Then it obtains the `Application` service, that runs the web application:
+The initial file for web applications is `index.php`, located in the public directory `www/`. It uses the `Bootstrap` class to initialize the environment and create a DI container. Then, it obtains the `Application` service from the container, which launches the web application:
 
 ```php
-// initialize the environment + get Configurator object
-$configurator = App\Bootstrap::boot();
-// create a DI container
-$container = $configurator->createContainer();
+$bootstrap = new App\Bootstrap;
+// Initialize the environment + create a DI container
+$container = $bootstrap->bootWebApplication();
 // DI container creates a Nette\Application\Application object
 $application = $container->getByType(Nette\Application\Application::class);
-// start Nette application
+// Start the Nette application and handle the incoming request
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Mode selection is done by autodetection, so there is usually no need to configur
 If you want to enable development mode in other cases, for example, for programmers accessing from a specific IP address, you can use `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // one or more IP addresses
+$this->configurator->setDebugMode('23.75.345.200'); // one or more IP addresses
 ```
 
 We definitely recommend combining an IP address with a cookie. We will store a secret token into the `nette-debug` cookie, e.g. `secret1234`, and the development mode will be activated for programmers with this combination of IP and cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 We can also turn off developer mode completely, even for localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Note that the value `true` turns on developer mode by hard, which should never happen on a production server.
@@ -90,7 +115,7 @@ Debugging Tool Tracy
 For easy debugging, we will turn on the great tool [Tracy |tracy:]. In developer mode it visualizes errors and in production mode it logs errors to the specified directory:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Temporary Files
 Nette uses the cache for DI container, RobotLoader, templates, etc. Therefore it is necessary to set the path to the directory where the cache will be stored:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 On Linux or macOS, set the [write permissions |nette:troubleshooting#Setting directory permissions] for directories `log/` and `temp/`.
@@ -112,7 +137,7 @@ RobotLoader
 Usually, we will want to automatically load the classes using [RobotLoader |robot-loader:], so we have to start it up and let it load classes from the directory where `Bootstrap.php` is located (i.e. `__DIR__`) and all its subdirectories:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Timezone
 Configurator allows you to specify a timezone for your application.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ In the development mode, the container is automatically updated each time you ch
 Configuration files are loaded using `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 The method `addConfig()` can be called multiple times to add multiple files.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Static Parameters
 Parameters used in configuration files can be defined [in the section `parameters`|dependency-injection:configuration#parameters] and also passed (or overwritten) by the `addStaticParameters()` method (it has alias `addParameters()`). It is important that different parameter values cause the generation of additional DI containers, i.e. additional classes.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Dynamic Parameters
 We can also add dynamic parameters to the container, their different values, unlike static parameters, will not cause the generation of new DI containers.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Environment variables could be easily made available using dynamic parameters. We can access them via `%env.variable%` in configuration files.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ You can use the following static parameters in the configuration files:
 - `%wwwDir%` is the absolute path to the directory containing the `index.php` entry file
 - `%tempDir%` is the absolute path to the directory for temporary files
 - `%vendorDir%` is the absolute path to the directory where Composer installs libraries
+- `%rootDir%` is the absolute path to the root directory of the project
 - `%debugMode%` indicates whether the application is in debug mode
 - `%consoleMode%` indicates whether the request came through the command line
 
@@ -225,7 +252,7 @@ services:
 Create a new instance and insert it in bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Different Environments
 ======================
 
-Feel free to customize the `Bootstrap` class to suit your needs. You can add parameters to the `boot()` method to differentiate web projects, or add other methods, such as `bootForTests()`, which initializes the environment for unit tests, `bootForCli()` for scripts called from the command line, and so on.
+Don't hesitate to customize the `Bootstrap` class according to your needs. You can add parameters to the `bootWebApplication()` method to differentiate between web projects. Alternatively, you can add other methods, such as `bootTestEnvironment()` to initialize the environment for unit tests, `bootConsoleApplication()` for scripts called from the command line, and so on.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
 {
-	$configurator = self::boot();
 	Tester\Environment::setup(); // Nette Tester initialization
-	return $configurator;
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
+{
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/en/components.texy b/application/en/components.texy
index b610a84739..2c79308bef 100644
--- a/application/en/components.texy
+++ b/application/en/components.texy
@@ -198,7 +198,7 @@ The link that calls the signal is created in the usual way, i.e. in the template
 <a n:href="click! $x, $y">click here</a>
 ```
 
-The signal is always called on the current presenter and view, so it is not possible to link to signal in different presenter / action.
+The signal is always called on the current presenter and action, it cannot be called on another presenter or action.
 
 Thus, the signal causes the page to be reloaded in exactly the same way as in the original request, only in addition it calls the signal handling method with the appropriate parameters. If the method does not exist, exception [api:Nette\Application\UI\BadSignalException] is thrown, which is displayed to the user as error page 403 Forbidden.
 
@@ -230,6 +230,28 @@ In the template, these messages are available in the variable `$flashes` as obje
 ```
 
 
+Redirection After a Signal
+==========================
+
+After processing a component signal, redirection often follows. This situation is similar to forms—after submitting a form, we also redirect to prevent resubmission of data when the page is refreshed in the browser.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Since a component is a reusable element and should not usually have a direct dependency on specific presenters, the `redirect()` and `link()` methods automatically interpret the parameter as a component signal:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+If you need to redirect to a different presenter or action, you can do so through the presenter:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Persistent Parameters
 =====================
 
@@ -347,7 +369,7 @@ services:
 Finally, we will use this factory in our presenter:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Components in Depth
 Components in a Nette Application are the reusable parts of a web application that we embed in pages, which is the subject of this chapter. What exactly are the capabilities of such a component?
 
 1) it is renderable in a template
-2) it knows which part of itself to render during an [AJAX request |ajax#invalidation] (snippets)
+2) it knows [which part of itself |ajax#snippets] to render during an AJAX request (snippets)
 3) it has the ability to store its state in a URL (persistent parameters)
 4) has the ability to respond to user actions (signals)
 5) creates a hierarchical structure (where the root is the presenter)
@@ -430,7 +452,7 @@ class PaginatingControl extends Control
 }
 ```
 
-The opposite process, that is, collecting values from persistent properites, is handled by the `saveState()` method.
+The opposite process, that is, collecting values from persistent properties, is handled by the `saveState()` method.
 
 
 Signals in Depth
@@ -444,7 +466,7 @@ Signal can be received by any component, presenter of object which implements in
 
 The main receivers of signals are `Presenters` and visual components extending `Control`. A signal is a sign for an object that it has to do something - poll counts in a vote from user, box with news has to unfold, form was sent and has to process data and so on.
 
-The URL for the signal is created using the method [Component::link() |api:Nette\Application\UI\Component::link()]. As parameter `$destination` we pass string `{signal}!` and as `$args` an array of arguments which we want to pass to the signal handler. Signal parameters are attached to the URL of the current presenter/view. **The parameter `?do` in the URL determines the signal called.**
+The URL for the signal is created using the [Component::link() |api:Nette\Application\UI\Component::link()] method. We pass the string `{signal}!` as the `$destination` parameter and the array of arguments we want to pass to the signal as `$args`. The signal is always called on the current presenter and action with the current parameters, the signal parameters are just added. In addition, the **parameter `?do`, which specifies the signal** is added right at the beginning.
 
 Its format is `{signal}` or `{signalReceiver}-{signal}`. `{signalReceiver}` is the name of the component in the presenter. This is why hyphen (inaccurately dash) can't be present in the name of components - it is used to divide the name of the component and signal, but it's possible to compose several components.
 
diff --git a/application/en/configuration.texy b/application/en/configuration.texy
index 208194e78f..e9df62aef7 100644
--- a/application/en/configuration.texy
+++ b/application/en/configuration.texy
@@ -14,10 +14,14 @@ application:
 	debugger: ...           # (bool) defaults to true
 
 	# will error-presenter be called on error?
-	catchExceptions: ...    # (bool) defaults to true in production mode
+	# has effect only in developer mode
+	catchExceptions: ...    # (bool) defaults to true
 
 	# name of error-presenter
-	errorPresenter: Error   # (string) defaults to 'Nette:Error'
+	errorPresenter: Error   # (string|array) defaults to 'Nette:Error'
+
+	# defines aliases for presenters and events
+	aliases: ...
 
 	# defines the rules for resolving the presenter name to a class
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) defaults to false
 ```
 
-Because error-presenters are not called by default in development mode and the errors are displayed by Tracy, changing the value `catchExceptions` to `true` helps to verify that error-presenters works correct during development.
+As of `nette/application` version 3.2 it is possible to define a pair of error-presenters:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # for Nette\Application\BadRequestException
+		5xx: Error5xx   # for other exceptions
+```
 
 Option `silentLinks` determines how Nette behaves in developer mode when link generation fails (for example, because there is no presenter, etc). The default value `false` means that Nette triggers `E_USER_WARNING`. Setting to `true` suppresses this error message. In a production environment, `E_USER_WARNING` is always invoked. We can also influence this behavior by setting the presenter variable [$invalidLinkMode |creating-links#Invalid Links].
 
+[Aliases simplify referencing |creating-links#aliases] frequently used presenters.
+
 The [mapping defines the rules |modules#mapping] by which the class name is derived from the presenter name.
 
 
@@ -82,6 +95,9 @@ latte:
 	# enables [checking generated code |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) default is null
 
+	# sets the locale
+	locale: cs_CZ        # (string) default is null
+
 	# class of $this->template
 	templateClass: App\MyTemplateClass # defaults to Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ If you are using Latte version 3, you can add new [extension |latte:creating-ext
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 If you are using Latte version 2, you can register new tags either by entering the class name or by referring to the service. Method `install()` is called by default, but this can be changed by specifying the name of another method:
diff --git a/application/en/creating-links.texy b/application/en/creating-links.texy
index 0fb783c609..f92d2c5894 100644
--- a/application/en/creating-links.texy
+++ b/application/en/creating-links.texy
@@ -38,7 +38,7 @@ It is also possible to pass named parameters. The following link passes paramete
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-If method `ProductPresenter::renderShow()` does not have `$lang` in its signature, it can read the value of the parameter using `$lang = $this->getParameter('lang')`.
+If the method `ProductPresenter::renderShow()` does not have `$lang` in its signature, it can retrieve the value of the parameter using `$lang = $this->getParameter('lang')` or from the [property |presenters#Request Parameters].
 
 If the parameters are stored in an array, they can be expanded with the `...` operator (or `(expand)` operator in Latte 2.x):
 
@@ -140,7 +140,7 @@ The target `this` will create a link to the current page:
 <a n:href="this">refresh</a>
 ```
 
-At the same time, all parameters specified in the signature of the `render<View>()` or `action<Action>()` method are transferred. So if we are on the `Product:show` and `id:123` pages, the link to `this` will also pass this parameter.
+At the same time, all parameters specified in the signature of the `action<Action>()` or `render<View>()` method, if the `action<Action>()` is not defined, are transferred. So if we are on the `Product:show` and `id:123` pages, the link to `this` will also pass this parameter.
 
 Of course, it is possible to specify the parameters directly:
 
@@ -213,7 +213,7 @@ Because [components] are separate reusable units that should have no relations t
 If we want to link to presenters in the component template, we use the tag `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 or in the code
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Aliases .{data-version:v3.2.2}
+==============================
+
+Sometimes it's useful to assign an easily memorable alias to a Presenter:action pair. For example, you could name the homepage `Front:Home:default` simply as `home` or `Admin:Dashboard:default` as `admin`.
+
+Aliases are defined in the [configuration|configuration] under the key `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+In links, they are written using the at symbol, for example:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+They are supported in all methods that work with links, such as `redirect()` and similar.
+
+
 Invalid Links
 =============
 
diff --git a/application/en/how-it-works.texy b/application/en/how-it-works.texy
index 08d7c3eb8b..cb0f291e1b 100644
--- a/application/en/how-it-works.texy
+++ b/application/en/how-it-works.texy
@@ -22,18 +22,18 @@ The directory structure looks something like this:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← basic necessary classes
+│   │   └── <b>RouterFactory.php</b> ← configuration of URL addresses
+│   ├── <b>UI/</b>                   ← presenters, templates & co.
+│   │   ├── <b>@layout.latte</b>     ← template of shared layout
+│   │   └── <b>Home/</b>             ← Home presenter directory
+│   │       ├── <b>HomePresenter.php</b> ← Home presenter class
+│   │       └── <b>default.latte</b> ← template for action default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ Applications written in Nette are divided into many so-called presenters (in oth
 
 The application starts by asking the so-called router to decide which of the presenters to pass the current request for processing. The router decides whose responsibility it is. It looks at the input URL `https://example.com/product/123` and, based on how it is set up, decides that this is a job, for example, for **presenter** `Product`,  who wants to `show` a product with `id: 123` as an action. It is a good habit to write a pairs of presenter + action separated by a colon as `Product:show`.
 
-So the router transformed the URL into a pair `Presenter:action` + parameters, in our case `Product:show` + `id: 123`. You can see how a router looks like in file `app/Router/RouterFactory.php` and we will describe it in detail in chapter [Routing].
+So the router transformed the URL into a pair `Presenter:action` + parameters, in our case `Product:show` + `id: 123`. You can see how a router looks like in file `app/Core/RouterFactory.php` and we will describe it in detail in chapter [Routing].
 
 Let's move on. The application already knows the name of the presenter and can continue. By creating an object `ProductPresenter`, which is the code of presenter `Product`. More precisely, it asks the DI container for creating the presenter, because producting objects is its job.
 
@@ -121,12 +121,9 @@ So, the method `renderShow(123)` was called, whose code is fictional example, bu
 
 Subsequently, the presenter returns the answer. This can be an HTML page, an image, an XML document, sending a file from disk, JSON or redirecting to another page. Importantly, if we do not explicitly say how to respond (which is the case of `ProductPresenter`), the answer will be to render the template with an HTML page. Why? Well, because in 99% of cases we want to draw a template, so the presenter takes this behavior as the default and wants to make our work easier. That's Nette's point.
 
-We don't even have to state which template to draw, he derives the path to it according to simple logic. In the case of presenter `Product` and action `show`, it tries to see if one of these template files exists relative to the directory where class `ProductPresenter` is located:
+We don't even need to specify which template to render; the framework will deduce the path itself. In the case of the `show` action, it simply tries to load the `show.latte` template in the directory with the `ProductPresenter` class. It also attempts to find the layout in the `@layout.latte` file (more about [template searching |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-It will also try to find the layout in file `@layout.latte` and then it renders the template. Now the task of the presenter and the entire application is completed. If the template does not exist, a page with error 404 will be returned. You can read more about presenters on the [Presenters] page.
+Subsequently, the templates are rendered. This completes the task of the presenter and the entire application, and the work is done. If the template did not exist, a 404 error page would be returned. You can read more about presenters on the page [Presenters|presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Just to be sure, let's try to recap the whole process with a slightly different
 3) the router decodes the URL as a pair `Home:default`
 4) an `HomePresenter` object is created
 5) method `renderDefault()` is called (if exists)
-6) a template `templates/Home/default.latte` with a layout `templates/@layout.latte` is rendered
+6) a template `default.latte` with a layout `@layout.latte` is rendered
 
 
 You may have come across a lot of new concepts now, but we believe they make sense. Creating applications in Nette is a breeze.
diff --git a/application/en/modules.texy b/application/en/modules.texy
index 6312143fdd..528cc1600c 100644
--- a/application/en/modules.texy
+++ b/application/en/modules.texy
@@ -2,29 +2,31 @@ Modules
 *******
 
 .[perex]
-In Nette, modules represent the logical units that make up an application. They include presenters, templates, possibly also components and model classes.
+Modules bring clarity to Nette applications by facilitating easy division into logical units.
 
-One directory for presenters and one for templates would not be enough for real projects. Having dozens of files in one folder is at least unorganized. How to get out of it? We simply split them into subdirectories on disk and into namespaces in the code. And that's exactly what the Nette modules do.
-
-So let's forget about a single folder for presenters and templates and instead create modules, for example `Admin` and `Front`.
+Similar to organizing files into folders on a hard drive, in Nette we can divide presenters, templates, and other auxiliary classes into modules. How does this work in practice? Simply by incorporating new subdirectories into the structure. Here’s an example of a structure with two modules, Front and Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-This directory structure will be reflected by the class namespaces, so for example `DashboardPresenter` will be in the `App\Modules\Admin\Presenters` namespace:
+This directory structure is reflected in the namespaces of the classes, so for example, `DashboardPresenter` is located in the namespace `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-The `Dashboard` presenter inside the `Admin` module is referenced within the application using the colon notation as `Admin:Dashboard`, and its `default` action as `Admin:Dashboard:default`.
-And how does Nette proper know that `Admin:Dashboard` represents the `App\Modules\Admin\Presenters\DashboardPresenter` class? This is determined by [#mapping] in the configuration.
-Thus, the given structure is not hard set and you can modify it according to your needs.
+In the application, we refer to the `Dashboard` presenter within the `Admin` module using colon notation as `Admin:Dashboard`. For its `default` action, we refer to it as `Admin:Dashboard:default`.
+
+The structure presented is not rigid; you can [fully customize it to your needs|#mapping] in the configuration. .[tip]
 
-Modules can of course contain all other items besides presenters and templates, such as components, model classes, etc.
+Modules can include all other files, such as components and auxiliary classes, in addition to presenters and templates. If you are considering where to place these, consider using an `Accessory` folder:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Nested Modules
 --------------
 
-Modules don't have to form only a flat structure, you can also create submodules, for example:
+Modules can have multiple levels of nesting, similar to a directory structure on a disk:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Thus, the `Blog` module is divided into `Admin` and `Front` submodules. Again, this will be reflected in the namespaces, which will be `App\Modules\Blog\Admin\Presenters` etc. The presenter `Dashboard` inside the submodule is referred to as `Blog:Admin:Dashboard`.
+The `Blog` module is divided into `Admin` and `Front` submodules. This is also reflected in the namespaces, which then appear as `App\UI\Blog\Admin` and similarly. To refer to the `Dashboard` presenter within the `Admin` submodule, we refer to it as `Blog:Admin:Dashboard`.
+
+Nesting can be as deep as needed, allowing the creation of sub-submodules.
 
-The nesting can go as deep as you like, so sub-submodules can be created.
+For example, if in administration you have many presenters related to order management, such as `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., you might create an `Order` module in which presenters like `Detail`, `Edit`, `Dispatch`, and others will be organized.
 
 
 Creating Links
@@ -102,47 +118,66 @@ See [chapter on routing |routing#Modules].
 Mapping
 -------
 
-Defines the rules by which the class name is derived from the presenter name. We write them in [configuration] under the `application › mapping` key.
+Mapping defines the rules for deriving the class name from the presenter name. These rules are specified in the [configuration|configuration] under the key `application › mapping`.
 
-Let's start with a sample that doesn't use modules. We'll just want the presenter classes to have the `App\Presenters` namespace. That means that a presenter such as `Home` should map to the `App\Presenters\HomePresenter` class. This can be achieved by the following configuration:
+The directory structures mentioned earlier on this page are based on the following mapping:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-The presenter name is replaced with the asterisk in the class mask and the result is the class name. Easy!
+How does the mapping work? For a better understanding, let's first imagine an application without modules. We want the presenter classes to fall under the namespace `App\UI`, so that the `Home` presenter maps to the class `App\UI\HomePresenter`. This can be achieved with this configuration:
 
-If we divide presenters into modules, we can have our own mapping for each module:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+This mapping works by replacing the asterisk in the mask `App\UI\*Presenter` with the presenter name `Home`, resulting in the final class name `App\UI\HomePresenter`. Simple!
+
+However, as you can see in the examples in this and other chapters, we place presenter classes in eponymous subdirectories, e.g., the `Home` presenter is mapped to the class `App\UI\Home\HomePresenter`. This is achieved by doubling the asterisk (requires Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Now, let's move on to mapping presenters into modules. We can define specific mappings for each module:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Now presenter `Front:Home` maps to class `App\Modules\Front\Presenters\HomePresenter` and presenter `Admin:Dashboard` to class `App\Modules\Admin\Presenters\DashboardPresenter`.
+According to this configuration, the presenter `Front:Home` maps to the class `App\UI\Front\Home\HomePresenter`, while the presenter `Api:OAuth` maps to the class `App\Api\OAuthPresenter`.
 
-It is more practical to create a general (star) rule to replace the first two. The extra asterisk will be added to the class mask just for the module:
+Since the `Front` and `Admin` modules have a similar mapping approach and there are likely to be more such modules, it is possible to create a general rule that replaces them. A new asterisk for the module is added to the class mask:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-But what if we use nested modules and have a presenter `Admin:User:Edit`? In this case, the segment with an asterisk representing the module for each level is simply repeated and the result is class `App\Modules\Admin\User\Presenters\EditPresenter`.
+For multi-level nested modules, such as the presenter `Admin:User:Edit`, the asterisk segment repeats for each level, resulting in the class `App\UI\Admin\User\Edit\EditPresenter`.
 
-An alternative notation is to use an array consisting of three segments instead of a string. This notation is equivalent to the previous one:
+An alternative notation is to use an array composed of three segments instead of a string. This notation is equivalent to the previous one:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-The default value is `*: *Module\*Presenter`.
+If we have only one rule in the configuration, the general one, we can write briefly:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/en/presenters.texy b/application/en/presenters.texy
index e653f0945c..2773f8486b 100644
--- a/application/en/presenters.texy
+++ b/application/en/presenters.texy
@@ -60,7 +60,7 @@ Similar to the method `render<View>()`. While `render<View>()` is intended to pr
 
 It is important that `action<Action>()` is called before `render<View>()`, so inside it we can possibly change the next course of life cycle, i.e. change the template that will be rendered and also the method `render<View>()` that will be called, using `setView('otherView')`.
 
-The parameters from the request are passed to the method. It is possible and recommended to specify types for the parameters, e.g. `actionShow(int $id, string $slug = null)` - if parameter `id` is missing or if it is not an integer, the presenter returns [error 404|#Error 404 etc.] and terminates the operation.
+The parameters from the request are passed to the method. It is possible and recommended to specify types for the parameters, e.g. `actionShow(int $id, ?string $slug = null)` - if parameter `id` is missing or if it is not an integer, the presenter returns [error 404|#Error 404 etc.] and terminates the operation.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ In the template, these messages are available in the variable `$flashes` as obje
 Error 404 etc.
 ==============
 
-When we can't fulfill the request because for example the article we want to display does not exist in the database, we will throw out the 404 error using method `error(string $message = null, int $httpCode = 404)`, which represents HTTP error 404:
+When we can't fulfill the request because for example the article we want to display does not exist in the database, we will throw out the 404 error using method `error(?string $message = null, int $httpCode = 404)`, which represents HTTP error 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Request Parameters .{data-version:3.1.14}
+=========================================
+
+The presenter, as well as every component, obtains its parameters from the HTTP request. Their values can be retrieved using the `getParameter($name)` method or `getParameters()`. The values are strings or arrays of strings, essentially raw data obtained directly from the URL.
+
+For added convenience, we recommend making parameters accessible through properties. Simply annotate them with the `#[Parameter]` attribute:
+
+```php
+use Nette\Application\Attributes\Parameter;  // this line is important
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // must be public
+}
+```
+
+For properties, we suggest specifying the data type (e.g., `string`). Nette will then automatically cast the value based on it. Parameter values can be also [validated |#Validation of Parameters].
+
+When creating a link, you can directly set the value for the parameters:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Persistent Parameters
 =====================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 If `$this->lang` has a value such as `'en'`, then links created using `link()` or `n:href` will also contain the `lang=en` parameter. And when the link is clicked, it will again be `$this->lang = 'en'`.
 
-For properties, we recommend that you include the data type (e.g. `string`) and you can also include a default value. Parameter values can be [validated |#Validation of Persistent Parameters].
+For properties, we recommend that you include the data type (e.g. `string`) and you can also include a default value. Parameter values can be [validated |#Validation of Parameters].
 
 Persistent parameters are passed between all actions of a given presenter by default. To pass them between multiple presenters, you need to define them either:
 
@@ -307,18 +333,12 @@ Going Deeper
 What we have shown so far in this chapter will probably suffice. The following lines are intended for those who are interested in presenters in depth and want to know everything.
 
 
-Requirement and Parameters
---------------------------
+Validation of Parameters
+------------------------
 
-The request handled by the presenter is the [api:Nette\Application\Request] object and is returned by the presenter's method `getRequest()`. It includes an array of parameters and each of them belongs either to some of the components or directly to the presenter (which is actually also a component, albeit a special one). So Nette redistributes the parameters and passes between the individual components (and the presenter) by calling the method `loadState(array $params)`. The parameters can be obtained by the method `getParameters(): array`, individually using `getParameter($name)`. Parameter values ​​are strings or arrays of strings, they are basically raw data obtained directly from a URL.
+The values of [#request parameters] and [#persistent parameters] received from URLs are written to properties by the `loadState()` method. It also checks if the data type specified in the property matches, otherwise it will respond with a 404 error and the page will not be displayed.
 
-
-Validation of Persistent Parameters
------------------------------------
-
-The values of [#persistent parameters] received from URLs are written to properties by the `loadState()` method. It also checks if the data type specified in the property matches, otherwise it will respond with a 404 error and the page will not be displayed.
-
-Never blindly trust persistent parameters, as they can easily be overwritten by the user in the URL. For example, this is how we check if `$this->lang` is among the supported languages. A good way to do this is to override the `loadState()` method mentioned above:
+Never blindly trust parameters, as they can easily be overwritten by the user in the URL. For example, this is how we check if `$this->lang` is among the supported languages. A good way to do this is to override the `loadState()` method mentioned above:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,6 +361,8 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Save and Restore the Request
 ----------------------------
 
+The request that the presenter handles is an object [api:Nette\Application\Request] and is returned by the presenter's method `getRequest()`.
+
 You can save the current request to a session or restore it from the session and let the presenter execute it again. This is useful, for example, when a user fills out a form and its login expires. In order not to lose data, before redirecting to the sign-in page, we save the current request to the session using `$reqId = $this->storeRequest()`, which returns an identifier in the form of a short string and passes it as a parameter to the sign-in presenter.
 
 After sign in, we call the method `$this->restoreRequest($reqId)`, which picks up the request from the session and forwards it to it. The method verifies that the request was created by the same user as now logged in is. If another user logs in or the key is invalid, it does nothing and the program continues.
@@ -362,7 +384,7 @@ Redirection does not occur with an AJAX or POST request because it would result
 You can also invoke canonization manually using method `canonicalize()`, which, like method `link()`, receives the presenter, actions, and parameters as arguments. It creates a link and compares it to the current URL. If it is different, it redirects to the generated link.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// redirects if $slug is different from $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Access Restriction Using `#[Requires]` .{data-version:3.2.2}
+------------------------------------------------------------
+
+The `#[Requires]` attribute provides advanced options for restricting access to presenters and their methods. It can be used to specify HTTP methods, require AJAX requests, limit access to the same origin, and restrict access to forwarding only. The attribute can be applied to presenter classes as well as individual methods such as `action<Action>()`, `render<View>()`, `handle<Signal>()`, and `createComponent<Name>()`.
+
+You can specify these restrictions:
+- on HTTP methods: `#[Requires(methods: ['GET', 'POST'])]`
+- requiring an AJAX request: `#[Requires(ajax: true)]`
+- access only from the same origin: `#[Requires(sameOrigin: true)]`
+- access only via forwarding: `#[Requires(forward: true)]`
+- restrictions on specific actions: `#[Requires(actions: 'default')]`
+
+For details, see [How to use the Requires attribute |best-practices:attribute-requires].
+
+
+HTTP Method Check
+-----------------
+
+In Nette, presenters automatically verify the HTTP method of each incoming request primarily for security reasons. By default, the methods `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` are allowed.
+
+If you want to enable additional methods such as `OPTIONS`, you can use the `#[Requires]` attribute (from Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+In version 3.1, the verification is performed in `checkHttpMethod()`, which checks if the method specified in the request is included in the array `$presenter->allowedMethods`. Add a method like this:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+It's crucial to emphasize that if you enable the `OPTIONS` method, you must also properly handle it within your presenter. This method is often used as a so-called preflight request, which browsers automatically send before the actual request when it's necessary to determine if the request is allowed from the standpoint of CORS (Cross-Origin Resource Sharing) policy. If you allow this method but do not implement an appropriate response, it can lead to inconsistencies and potential security issues.
+
+
 Further Reading
 ===============
 
diff --git a/application/en/routing.texy b/application/en/routing.texy
index c35c692adb..f9af18510b 100644
--- a/application/en/routing.texy
+++ b/application/en/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Advanced Notation
 -----------------
 
-The second parameter of the route, which we often write in the format `Presenter:action`, is an abbreviation, which we can also write in the form of a field, where we directly state the (default) values ​​of individual parameters:
+The target of a route, usually written in the form `Presenter:action`, can also be expressed using an array that defines individual parameters and their default values:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Or we can use this form, notice the rewriting of the validation regular expression:
+For a more detailed specification, an even more extended form can be used, where in addition to default values, other parameter properties can be set, such as a validation regular expression (see the `id` parameter):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-These more talkative formats are useful for adding other metadata.
+It is important to note that if the parameters defined in the array are not included in the path mask, their values cannot be changed, not even using query parameters specified after a question mark in the URL.
 
 
 Filters and Translations
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integration
 ===========
 
-In order to connect the our router into the application, we must tell the DI container about it. The easiest way is to prepare the factory that will build the router object and tell the container configuration to use it. So let's say we write a method for this purpose `App\Router\RouterFactory::createRouter()`:
+In order to connect the our router into the application, we must tell the DI container about it. The easiest way is to prepare the factory that will build the router object and tell the container configuration to use it. So let's say we write a method for this purpose `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Then we write in [configuration |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Any dependencies, such as a database connection etc., are passed to the factory method as its parameters using [autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ By separated usage, we mean the use of the router's capabilities in an applicati
 So again we will create a method that will build a router, for example:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Or we will create objects directly:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/en/templates.texy b/application/en/templates.texy
index 5107b4493a..bdc524c4e4 100644
--- a/application/en/templates.texy
+++ b/application/en/templates.texy
@@ -34,35 +34,81 @@ And this might be the action template:
 It defines block `content`, which is inserted in place of `{include content}` in the layout, and also re-defines block `title`, which overwrites `{block title}` in the layout. Try to imagine the result.
 
 
-Search for Templates
---------------------
+Template Lookup
+---------------
 
-The path to the templates is deduced according to simple logic. It tries to see if one of these template files exists relative to the directory where presenter class is located, where `<Presenter>` is the name of the current presenter and `<view>` is the name of the current action:
+In presenters, you don't need to specify which template should be rendered; the framework will automatically determine the path, making coding easier for you.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+If you use a directory structure where each presenter has its own directory, simply place the template in this directory under the name of the action (i.e. view). For example, for the `default` action, use the `default.latte` template:
 
-If the template is not found, it will try to search in the `templates` directory one level up, i.e., at the same level as the directory with the presenter class.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-If the template is not found there either, the response is a [404 error|presenters#Error 404 etc.].
+If you use a structure where presenters are together in one directory and templates in a `templates` folder, save it either in a file `<Presenter>.<view>.latte` or `<Presenter>/<view>.latte`:
 
-You can also change the view using `$this->setView('otherView')`. Or, instead of searching, directly specify the name of the template file using `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+The `templates` directory can also be placed one level higher, at the same level as the directory with presenter classes.
+
+If the template is not found, the presenter responds with [404 - page not found error|presenters#Error 404 etc].
+
+You can change the view using `$this->setView('anotherView')`. It is also possible to directly specify the template file with `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-You can change the paths where templates are searched by overriding the [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] method, which returns an array of possible file paths.
+Files where templates are searched can be changed by overriding the method [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], which returns an array of possible file names.
+
+
+Layout Template Lookup
+----------------------
+
+Nette also automatically searches for the layout file.
+
+If you use a directory structure where each presenter has its own directory, place the layout either in the folder with the presenter, if it is specific only to them, or a level higher if it is common to multiple presenters:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+If you use a structure where presenters are grouped together in one directory and templates are in a `templates` folder, the layout will be expected in the following places:
 
-The layout is expected in the following files:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` layout common to multiple presenters
+If the presenter is in a [module|modules], it will also search further up the directory tree according to the module's nesting.
 
-`<Presenter>` is the name of the current presenter and `<layout>` is the name of the layout, which is by default `'layout'`. The name can be changed with `$this->setLayout('otherLayout')`, so that `@otherLayout.latte` files will be tried.
+The name of the layout can be changed using `$this->setLayout('layoutAdmin')` and then it will be expected in the file `@layoutAdmin.latte`. You can also directly specify the layout template file using `$this->setLayout('/path/to/template.latte')`.
 
-You can also directly specify the file name of the layout template using `$this->setLayout('/path/to/template.latte')`. Using `$this->setLayout(false)` will disable the layout searching.
+Using `$this->setLayout(false)` or the `{layout none}` tag inside the template disables layout search.
 
 .[note]
-You can change the paths where templates are searched by overriding the [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] method, which returns an array of possible file paths.
+Files where layout templates are searched can be changed by overriding the method [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], which returns an array of possible file names.
 
 
 Variables in the Template
@@ -104,7 +150,7 @@ The `@property-read` annotation is for IDE and static analysis, it will make aut
 You can indulge in the luxury of whispering in templates too, just install the Latte plugin in PhpStorm and specify the class name at the beginning of the template, see the article "Latte: how to type system":https://blog.nette.org/en/latte-how-to-use-type-system:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte version 3 offers a more advanced way by creating an [extension |latte:creating-extension] for each web project. Here is a rough example of such a class:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ We register it using [configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternatively, the translator can be set using the [configuration |configuration
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 The translator can then be used, for example, as a filter `|translate`, with additional parameters passed to the `translate()` method (see `foo, bar`):
diff --git a/application/es/@home.texy b/application/es/@home.texy
index b2966f5062..0777da2986 100644
--- a/application/es/@home.texy
+++ b/application/es/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | versión | compatible con PHP
 |-----------|-------------------
-| Aplicación Nette 4.0 | PHP 8.0 - 8.2
-| Aplicación Nette 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Aplicación Nette 3.0 | PHP 7.1 - 8.0
 | Aplicación Nette 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/es/ajax.texy b/application/es/ajax.texy
index 0ba8886dd4..d1414e84c4 100644
--- a/application/es/ajax.texy
+++ b/application/es/ajax.texy
@@ -3,10 +3,10 @@ AJAX y fragmentos
 
 <div class=perex>
 
-Hoy en día, las aplicaciones web modernas se ejecutan mitad en un servidor y mitad en un navegador. AJAX es un factor de unión vital. ¿Qué soporte ofrece Nette Framework?
-- envío de fragmentos de plantillas (los llamados *snippets*)
+En la era de las aplicaciones web modernas, donde la funcionalidad a menudo se extiende entre el servidor y el navegador, AJAX es un elemento de conexión esencial. ¿Qué opciones ofrece Nette Framework en este ámbito?
+- envío de partes de la plantilla, los llamados snippets
 - paso de variables entre PHP y JavaScript
-- depuración de aplicaciones AJAX
+- herramientas para depurar peticiones AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ Hoy en día, las aplicaciones web modernas se ejecutan mitad en un servidor y mi
 Solicitud AJAX .[#toc-ajax-request]
 ===================================
 
-Una petición AJAX no difiere de una petición clásica: se llama al presentador con una vista y unos parámetros específicos. También depende del presentador cómo responder a ella: puede utilizar su propia rutina, que devuelve un fragmento de código HTML (HTML snippet), un documento XML, un objeto JSON o código JavaScript.
+Una petición AJAX fundamentalmente no difiere de una petición HTTP clásica. Se llama a un presentador con parámetros específicos. Depende del presentador cómo responder a la petición - puede devolver datos en formato JSON, enviar una parte de código HTML, un documento XML, etc.
 
-En el lado del servidor, una petición AJAX puede detectarse utilizando el método de servicio [que encapsula la petición HTTP |http:request] `$httpRequest->isAjax()` (detecta basándose en la cabecera HTTP `X-Requested-With`). Dentro del presentador, se dispone de un acceso directo en forma del método `$this->isAjax()`.
+En el navegador, iniciamos una petición AJAX utilizando la función `fetch()`:
 
-Existe un objeto preprocesado llamado `payload` dedicado a enviar datos al navegador en JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// tratamiento de la respuesta
+});
 ```
 
-Para un control total sobre su salida JSON utilice el método `sendJson` en su presentador. Terminará el presentador inmediatamente y prescindirá de una plantilla:
+En el lado del servidor, una petición AJAX es reconocida por el método `$httpRequest->isAjax()` del servicio [que encapsula la petición HTTP |http:request]. Utiliza la cabecera HTTP `X-Requested-With`, por lo que es imprescindible enviarla. Dentro del presentador, puede utilizar el método `$this->isAjax()`.
+
+Si desea enviar datos en formato JSON, utilice el método [`sendJson()` |presenters#Sending a response] método. El método también finaliza la actividad del presentador.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Si queremos enviar HTML, podemos establecer una plantilla especial para peticiones AJAX:
+Si planea responder con una plantilla especial diseñada para AJAX, puede hacerlo de la siguiente manera:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Recortes .[#toc-snippets]
+=========================
+
+La herramienta más potente que ofrece Nette para conectar el servidor con el cliente son los snippets. Con ellos, puedes convertir una aplicación ordinaria en una AJAX con el mínimo esfuerzo y unas pocas líneas de código. El ejemplo Fifteen demuestra cómo funciona todo, y su código puede encontrarse en [GitHub |https://github.com/nette-examples/fifteen].
+
+Los snippets, o recortes, permiten actualizar sólo partes de la página, en lugar de recargarla entera. Esto es más rápido y eficiente, y también proporciona una experiencia de usuario más cómoda. Puede que los snippets te recuerden a Hotwire para Ruby on Rails o a Symfony UX Turbo. Curiosamente, Nette introdujo los snippets 14 años antes.
+
+¿Cómo funcionan los fragmentos? Cuando se carga la página por primera vez (una petición no-AJAX), se carga toda la página, incluidos todos los fragmentos. Cuando el usuario interactúa con la página (por ejemplo, hace clic en un botón, envía un formulario, etc.), en lugar de cargarse toda la página, se realiza una solicitud AJAX. El código del presentador ejecuta la acción y decide qué fragmentos deben actualizarse. Nette renderiza estos fragmentos y los envía en forma de matriz JSON. A continuación, el código de gestión del navegador vuelve a insertar en la página los fragmentos recibidos. Por lo tanto, sólo se transfiere el código de los fragmentos modificados, lo que ahorra ancho de banda y acelera la carga en comparación con la transferencia de todo el contenido de la página.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-K obsluze AJAXových požadavků na straně prohlížeče slouží [knihovna Naja |https://naja.js.org], [instálalo |https://naja.js.org/#/guide/01-install-setup-naja] como un paquete node.js (para usarlo con Webpack, Rollup, Vite, Parcel y más):
+Para manejar snippets en el lado del navegador, se utiliza la [librería Naja |https://naja.js.org]. [Instálala |https://naja.js.org/#/guide/01-install-setup-naja] como un paquete node.js (para usar con aplicaciones como Webpack, Rollup, Vite, Parcel, y otras):
 
 ```shell
 npm install naja
 ```
 
-...o insertarlo directamente en la plantilla de la página:
+... o insértala directamente en la plantilla de la página:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Para crear una solicitud AJAX a partir de un enlace normal (señal) o el envío de un formulario, basta con marcar el enlace, formulario o botón correspondiente con la clase `ajax`:
+Primero hay que [inicializar |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] la biblioteca:
+
+```js
+naja.initialize();
+```
+
+Para convertir un enlace ordinario (señal) o el envío de un formulario en una petición AJAX, basta con marcar el enlace, formulario o botón correspondiente con la clase `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Para crear una solicitud AJAX a partir de un enlace normal (señal) o el envío
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Fragmentos .[#toc-snippets]
-===========================
-
-Existe una herramienta mucho más potente de soporte AJAX integrado: los snippets. Su uso permite convertir una aplicación normal en una aplicación AJAX utilizando sólo unas pocas líneas de código. Cómo funciona todo se demuestra en el ejemplo Fifteen cuyo código también está accesible en la compilación o en [GitHub |https://github.com/nette-examples/fifteen].
-
-La forma en que funcionan los snippets es que toda la página se transfiere durante la petición inicial (es decir, no AJAX) y luego con cada [subpetición |components#signal] AJAX (petición de la misma vista del mismo presentador) sólo se transfiere el código de las partes modificadas en el repositorio `payload` mencionado anteriormente.
-
-Puede que los snippets te recuerden a Hotwire para Ruby on Rails o a Symfony UX Turbo, pero Nette los inventó catorce años antes.
-
+Redibujar fragmentos .[#toc-redrawing-snippets]
+-----------------------------------------------
 
-Invalidación de Snippets .[#toc-invalidation-of-snippets]
-=========================================================
-
-Cada descendiente de la clase [Control |components] (que también es un Presentador) es capaz de recordar si hubo algún cambio durante una petición que requiera que se vuelva a renderizar. Hay un par de métodos para manejar esto: `redrawControl()` y `isControlInvalid()`. Un ejemplo:
+Cada objeto de la clase [Control |components] (incluido el propio Presentador) mantiene un registro de si se han producido cambios que requieran su redibujado. Para ello se emplea el método `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// The object has to re-render after the user has logged in
+	// después de iniciar la sesión, es necesario volver a dibujar la parte pertinente
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette, sin embargo, ofrece una resolución aún más fina que la de los componentes completos. Los métodos mencionados aceptan el nombre de un "fragmento" como parámetro opcional. Un "fragmento" es básicamente un elemento de su plantilla marcado para ese propósito por una tag Latte, más sobre esto más adelante. Así, es posible pedir a un componente que redibuje sólo *partes* de su plantilla. Si se invalida todo el componente, entonces se vuelven a renderizar todos sus fragmentos. Un componente es "inválido" también si cualquiera de sus subcomponentes es inválido.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // invalidates the snippet named 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, at least one snippet is invalid
+Nette también permite un control más preciso de lo que hay que redibujar. El método mencionado puede tomar el nombre del fragmento como argumento. Así, es posible invalidar (es decir: forzar un redibujado) a nivel de la parte de la plantilla. Si se invalida todo el componente, también se redibujan todos sus fragmentos:
 
-$this->redrawControl(); // invalidates the whole component, every snippet
-$this->isControlInvalid('footer'); // -> true
+```php
+// invalida el fragmento de cabecera
+$this->redrawControl('header');
 ```
 
-Un componente que recibe una señal se marca automáticamente para ser redibujado.
-
-Gracias al redibujado de fragmentos, sabemos exactamente qué partes de qué elementos deben redibujarse.
-
-
-Etiqueta `{snippet} … {/snippet}` .{toc: Tag snippet}
-=====================================================
-
-El renderizado de la página procede de forma muy similar a una petición normal: se cargan las mismas plantillas, etc. Sin embargo, lo esencial es dejar fuera las partes que no deben llegar a la salida; las demás partes se asociarán a un identificador y se enviarán al usuario en un formato comprensible para un manipulador JavaScript.
-
 
-Sintaxis .[#toc-syntax]
------------------------
+Fragmentos en Latte .[#toc-snippets-in-latte]
+---------------------------------------------
 
-Si hay un control o un fragmento en la plantilla, tenemos que envolverlo usando la etiqueta `{snippet} ... {/snippet}` pair - se asegurará de que el fragmento renderizado será "recortado" y enviado al navegador. También lo encerrará en una etiqueta helper `<div>` (es posible utilizar otra). En el siguiente ejemplo se define un fragmento llamado `header`. También puede representar la plantilla de un componente:
+Utilizar snippets en Latte es extremadamente fácil. Para definir una parte de la plantilla como fragmento, basta con envolverla en las etiquetas `{snippet}` y `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Si hay un control o un fragmento en la plantilla, tenemos que envolverlo usando
 {/snippet}
 ```
 
-Si desea crear un fragmento con un elemento contenedor distinto de `<div>` o añadir atributos personalizados al elemento, puede utilizar la siguiente definición:
+El fragmento crea un elemento `<div>` en la página HTML con un `id` especialmente generado. Al redibujar un fragmento, se actualiza el contenido de este elemento. Por lo tanto, cuando la página se renderiza inicialmente, también deben renderizarse todos los fragmentos, aunque inicialmente puedan estar vacíos.
+
+También puede crear un fragmento con un elemento distinto de `<div>` mediante un atributo n:attribute:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Si desea crear un fragmento con un elemento contenedor distinto de `<div>` o añ
 ```
 
 
-Fragmentos dinámicos .[#toc-dynamic-snippets]
-=============================================
+Áreas de recortes .[#toc-snippet-areas]
+---------------------------------------
 
-En Nette también puede definir fragmentos con un nombre dinámico basado en un parámetro de tiempo de ejecución. Esto es más adecuado para varias listas en las que necesitamos cambiar sólo una fila pero no queremos transferir toda la lista junto con ella. Un ejemplo de esto sería:
+Los nombres de los recortes también pueden ser expresiones:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Hay un fragmento estático llamado `itemsContainer`, que contiene varios fragmentos dinámicos: `item-0` `item-1` y así sucesivamente.
+De este modo, obtendremos varios fragmentos como `item-0`, `item-1`, etc. Si invalidáramos directamente un fragmento dinámico (por ejemplo, `item-1`), no se volvería a dibujar nada. La razón es que los fragmentos funcionan como verdaderos extractos y sólo ellos mismos se renderizan directamente. Sin embargo, en la plantilla no existe técnicamente un fragmento llamado `item-1`. Sólo aparece cuando se ejecuta el código que rodea al fragmento, en este caso, el bucle foreach. Por lo tanto, marcaremos la parte de la plantilla que necesita ser ejecutada con la etiqueta `{snippetArea}`:
 
-No puedes redibujar un fragmento dinámico directamente (redibujar `item-1` no tiene ningún efecto), tienes que redibujar su fragmento padre (en este ejemplo `itemsContainer`). Esto hace que se ejecute el código del fragmento padre, pero entonces sólo se envían al navegador sus sub fragmentos. Si desea enviar sólo uno de los sub fragmentos, debe modificar la entrada del fragmento padre para que no genere los otros sub fragmentos.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-En el ejemplo anterior tiene que asegurarse de que para una petición AJAX sólo se añadirá un elemento a la matriz `$list`, por lo que el bucle `foreach` sólo imprimirá un fragmento dinámico.
+Y redibujaremos tanto el fragmento individual como toda el área general:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+También es esencial asegurarse de que la matriz `$items` contiene sólo los elementos que deben ser redibujados.
 
-Fragmentos en una plantilla incluida .[#toc-snippets-in-an-included-template]
-=============================================================================
-
-Puede ocurrir que el snippet esté en una plantilla que está siendo incluida desde una plantilla diferente. En ese caso necesitamos envolver el código de inclusión en la segunda plantilla con la tag `snippetArea`, entonces redibujamos tanto el snippetArea como el snippet real.
-
-La tag `snippetArea` garantiza que se ejecute el código que contiene, pero que sólo se envíe al navegador el fragmento real de la plantilla incluida.
+Cuando se inserta otra plantilla en la principal utilizando la etiqueta `{include}`, que tiene fragmentos, es necesario envolver de nuevo la plantilla incluida en un `snippetArea` e invalidar conjuntamente el fragmento y el área:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-También se puede combinar con fragmentos dinámicos.
 
+Fragmentos en componentes .[#toc-snippets-in-components]
+--------------------------------------------------------
 
-Añadir y eliminar .[#toc-adding-and-deleting]
-=============================================
-
-Si añades un nuevo elemento a la lista e invalidas `itemsContainer`, la petición AJAX devuelve fragmentos que incluyen el nuevo, pero el manejador javascript no podrá renderizarlo. Esto se debe a que no hay ningún elemento HTML con el ID recién creado.
-
-En este caso, la forma más sencilla es envolver toda la lista en un fragmento más e invalidarlo todo:
+Puede crear fragmentos dentro de los [componentes |components] y Nette los redibujará automáticamente. Sin embargo, hay una limitación específica: para redibujar fragmentos, llama al método `render()` sin ningún parámetro. Por lo tanto, pasar parámetros en la plantilla no funcionará:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Envío de datos de usuario .[#toc-sending-user-data]
+---------------------------------------------------
+
+Junto con los fragmentos, puede enviar cualquier dato adicional al cliente. Simplemente escríbalos en el objeto `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Lo mismo ocurre con la eliminación de un elemento. Sería posible enviar un fragmento vacío, pero normalmente las listas pueden paginarse y sería complicado implementar la eliminación de un elemento y la carga de otro (que solía estar en una página diferente de la lista paginada).
-
 
-Envío de parámetros al componente .[#toc-sending-parameters-to-component]
-=========================================================================
+Envío de parámetros .[#toc-sending-parameters]
+==============================================
 
 Cuando enviamos parámetros al componente a través de una petición AJAX, ya sean parámetros de señal o parámetros persistentes, debemos proporcionar su nombre global, que también contiene el nombre del componente. El nombre completo del parámetro devuelve el método `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Y manejar el método con s parámetros correspondientes en el componente.
+Un método handle con los parámetros correspondientes en el componente:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/es/bootstrap.texy b/application/es/bootstrap.texy
index 3b67d5c4b9..19bb56c0ba 100644
--- a/application/es/bootstrap.texy
+++ b/application/es/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// El configurador se encarga de configurar el entorno y los servicios de la aplicación.
+		$this->configurator = new Configurator;
+		// Establecer el directorio para los archivos temporales generados por Nette (por ejemplo, plantillas compiladas).
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette es inteligente, y el modo de desarrollo se activa automáticamente,
+		// o puede habilitarlo para una dirección IP específica descomentando la siguiente línea:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Habilita Tracy: la última herramienta de depuración "navaja suiza".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: carga automáticamente todas las clases en el directorio dado
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Carga archivos de configuración
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-En el caso de las aplicaciones web, el archivo inicial es `index.php`, que se encuentra en el directorio público `www/`. Permite a la clase `Bootstrap` inicializar el entorno y devolver el `$configurator` que crea el contenedor DI. Luego obtiene el servicio `Application`, que ejecuta la aplicación web:
+El archivo inicial para aplicaciones web es `index.php`, ubicado en el directorio público `www/`. Utiliza la clase `Bootstrap` para inicializar el entorno y crear un contenedor DI. A continuación, obtiene el servicio `Application` del contenedor, que lanza la aplicación web:
 
 ```php
-// initialize the environment + get Configurator object
-$configurator = App\Bootstrap::boot();
-// create a DI container
-$container = $configurator->createContainer();
-// DI container creates a Nette\Application\Application object
+$bootstrap = new App\Bootstrap;
+// Inicializar el entorno + crear un contenedor DI
+$container = $bootstrap->bootWebApplication();
+// El contenedor DI crea un objeto Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// start Nette application
+// Inicia la aplicación Nette y gestiona la petición entrante
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ La selección del modo se hace por autodetección, por lo que normalmente no hay
 Si desea habilitar el modo de desarrollo en otros casos, por ejemplo, para los programadores que acceden desde una dirección IP específica, puede utilizar `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // one or more IP addresses
+$this->configurator->setDebugMode('23.75.345.200'); // one or more IP addresses
 ```
 
 Recomendamos encarecidamente combinar una dirección IP con una cookie. Almacenaremos un token secreto en la cookie `nette-debug`, por ejemplo `secret1234`, y el modo de desarrollo se activará para los programadores con esta combinación de IP y cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 También podemos desactivar completamente el modo de desarrollo, incluso para localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Nótese que el valor `true` activa el modo desarrollador por fuerza, lo que nunca debería ocurrir en un servidor de producción.
@@ -90,7 +115,7 @@ Herramienta de depuración Tracy .[#toc-debugging-tool-tracy]
 Para facilitar la depuración, activaremos la gran herramienta [Tracy |tracy:]. En modo desarrollador visualiza los errores y en modo producción los registra en el directorio especificado:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Archivos temporales .[#toc-temporary-files]
 Nette utiliza la caché para el contenedor DI, RobotLoader, plantillas, etc. Por lo tanto es necesario establecer la ruta al directorio donde se almacenará la caché:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 En Linux o macOS, establezca los [permisos de escritura |nette:troubleshooting#Setting directory permissions] para los directorios `log/` y `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Normalmente, querremos cargar automáticamente las clases usando [RobotLoader |robot-loader:], así que tenemos que iniciarlo y dejar que cargue las clases desde el directorio donde se encuentra `Bootstrap.php` (es decir, `__DIR__`) y todos sus subdirectorios:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Zona horaria .[#toc-timezone]
 Configurator le permite especificar una zona horaria para su aplicación.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ En el modo de desarrollo, el contenedor se actualiza automáticamente cada vez q
 Los archivos de configuración se cargan utilizando `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 El método `addConfig()` se puede llamar varias veces para añadir varios archivos.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Parámetros estáticos .[#toc-static-parameters]
 Los parámetros utilizados en los archivos de configuración pueden definirse [en la sección `parameters` |dependency-injection:configuration#parameters] y también pasarse (o sobrescribirse) por el método `addStaticParameters()` (tiene el alias `addParameters()`). Es importante que los diferentes valores de los parámetros provoquen la generación de contenedores DI adicionales, es decir, clases adicionales.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Parámetros dinámicos .[#toc-dynamic-parameters]
 También podemos añadir parámetros dinámicos al contenedor, sus diferentes valores, a diferencia de los parámetros estáticos, no provocarán la generación de nuevos contenedores DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Las variables de entorno podrían estar fácilmente disponibles utilizando parámetros dinámicos. Podemos acceder a ellas a través de `%env.variable%` en archivos de configuración.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Puede utilizar los siguientes parámetros estáticos en los archivos de configur
 - `%wwwDir%` es la ruta absoluta al directorio que contiene el archivo de entrada `index.php`
 - `%tempDir%` es la ruta absoluta al directorio para los archivos temporales
 - `%vendorDir%` es la ruta absoluta al directorio donde Composer instala las bibliotecas
+- `%rootDir%` es la ruta absoluta al directorio raíz del proyecto
 - `%debugMode%` indica si la aplicación está en modo depuración
 - `%consoleMode%` indica si la solicitud llegó a través de la línea de comandos
 
@@ -225,7 +252,7 @@ services:
 Creamos una nueva instancia y la insertamos en bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Diferentes entornos .[#toc-different-environments]
 ==================================================
 
-Siéntete libre de personalizar la clase `Bootstrap` para adaptarla a tus necesidades. Puedes añadir parámetros al método `boot()` para diferenciar proyectos web, o añadir otros métodos, como `bootForTests()`, que inicializa el entorno para pruebas unitarias, `bootForCli()` para scripts llamados desde la línea de comandos, etc.
+No dude en personalizar la clase `Bootstrap` según sus necesidades. Puedes añadir parámetros al método `bootWebApplication()` para diferenciar entre proyectos web. Alternativamente, puedes añadir otros métodos, como `bootTestEnvironment()` para inicializar el entorno para pruebas unitarias, `bootConsoleApplication()` para scripts llamados desde la línea de comandos, etc.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Inicialización del comprobador de redes
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Nette Tester initialization
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/es/components.texy b/application/es/components.texy
index 7f736ea960..5e58b7e920 100644
--- a/application/es/components.texy
+++ b/application/es/components.texy
@@ -230,6 +230,28 @@ En la plantilla, estos mensajes están disponibles en la variable `$flashes` com
 ```
 
 
+Redirección tras una señal .[#toc-redirection-after-a-signal]
+=============================================================
+
+Después de procesar una señal de componente, a menudo se produce una redirección. Esta situación es similar a la de los formularios: después de enviar un formulario, también redirigimos para evitar que se vuelvan a enviar los datos cuando se actualiza la página en el navegador.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Dado que un componente es un elemento reutilizable y, por lo general, no debería tener una dependencia directa de presentadores específicos, los métodos `redirect()` y `link()` interpretan automáticamente el parámetro como una señal de componente:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Si necesita redirigir a un presentador o acción diferente, puede hacerlo a través del presentador:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Parámetros persistentes .[#toc-persistent-parameters]
 =====================================================
 
@@ -347,7 +369,7 @@ services:
 Por último, vamos a utilizar esta fábrica en nuestro presentador:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Componentes en profundidad .[#toc-components-in-depth]
 Los componentes en una aplicación Nette son las partes reutilizables de una aplicación web que incrustamos en las páginas, que es el tema de este capítulo. ¿Cuáles son exactamente las capacidades de un componente?
 
 1) es renderizable en una plantilla
-2) sabe qué parte de sí mismo renderizar durante una [petición AJAX |ajax#invalidation] (fragmentos)
+2) sabe [qué parte de sí mismo |ajax#snippets] debe representar durante una petición AJAX (fragmentos)
 3) tiene la capacidad de almacenar su estado en una URL (parámetros persistentes)
 4) tiene la capacidad de responder a las acciones del usuario (señales)
 5) crea una estructura jerárquica (donde la raíz es el presentador)
diff --git a/application/es/configuration.texy b/application/es/configuration.texy
index 5dfa60ab36..aa5273344b 100644
--- a/application/es/configuration.texy
+++ b/application/es/configuration.texy
@@ -14,10 +14,14 @@ application:
 	debugger: ...           # (bool) por defecto true
 
 	# ¿se llamará al presentador de errores en caso de error?
-	catchExceptions: ...    # (bool) por defecto a true en modo producción
+	# sólo tiene efecto en modo desarrollador
+	catchExceptions: ...    # (bool) por defecto true
 
 	# nombre del presentador de errores
-	errorPresenter: Error   # (string) por defecto 'Nette:Error'
+	errorPresenter: Error   # (string|array) por defecto 'Nette:Error'
+
+	# define alias para presentadores y eventos
+	aliases: ...
 
 	# define las reglas para resolver el nombre del presentador a una clase
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) por defecto false
 ```
 
-Debido a que los presentadores de errores no son llamados por defecto en modo desarrollo y los errores son mostrados por Tracy, cambiar el valor `catchExceptions` a `true` ayuda a verificar que los presentadores de errores funcionan correctamente durante el desarrollo.
+A partir de la versión 3.2 de `nette/application` es posible definir un par de presentadores de errores:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # para Nette\Application\BadRequestException
+		5xx: Error5xx   # para otras excepciones
+```
 
 La opción `silentLinks` determina cómo se comporta Nette en modo desarrollo cuando falla la generación de enlaces (por ejemplo, porque no hay presentador, etc). El valor por defecto `false` significa que Nette activa `E_USER_WARNING`. El valor `true` suprime este mensaje de error. En un entorno de producción, siempre se invoca `E_USER_WARNING`. También podemos influir en este comportamiento configurando la variable del presentador [$invalidLinkMode |creating-links#Invalid Links].
 
+[Los alias simplifican las referencias a |creating-links#aliases] los presentadores más utilizados.
+
 El [mapeo define las reglas |modules#mapping] por las cuales el nombre de la clase se deriva del nombre del presentador.
 
 
@@ -82,6 +95,9 @@ latte:
 	# habilita la [comprobación del código generado |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) por defecto es null
 
+	# establece la configuración regional
+	locale: cs_CZ        # (string) por defecto es null
+
 	# clase de $this->plantilla
 	templateClass: App\MyTemplateClass # por defecto Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Si está utilizando la versión 3 de Latte, puede añadir una nueva [extensión
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/es/creating-links.texy b/application/es/creating-links.texy
index cd4645f3a5..d22a004836 100644
--- a/application/es/creating-links.texy
+++ b/application/es/creating-links.texy
@@ -38,7 +38,7 @@ También es posible pasar parámetros con nombre. El siguiente enlace pasa el pa
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Si el método `ProductPresenter::renderShow()` no tiene `$lang` en su firma, puede leer el valor del parámetro usando `$lang = $this->getParameter('lang')`.
+Si el método `ProductPresenter::renderShow()` no tiene `$lang` en su firma, puede recuperar el valor del parámetro utilizando `$lang = $this->getParameter('lang')` o desde la [propiedad |presenters#Request Parameters].
 
 Si los parámetros se almacenan en una matriz, pueden expandirse con el operador `...` (o `(expand)` en Latte 2.x):
 
@@ -140,7 +140,7 @@ El destino `this` creará un enlace a la página actual:
 <a n:href="this">refresh</a>
 ```
 
-Al mismo tiempo, todos los parámetros especificados en la firma de la directiva `render<View>()` o `action<Action>()` se transfieren. Así, si estamos en las páginas `Product:show` y `id:123`, el enlace a `this` también pasará este parámetro.
+Al mismo tiempo, todos los parámetros especificados en la firma de la directiva `action<Action>()` o `render<View>()` si el método `action<Action>()` no está definido, se transfieren. Así, si estamos en las páginas `Product:show` y `id:123`, el enlace a `this` también pasará este parámetro.
 
 Por supuesto, es posible especificar los parámetros directamente:
 
@@ -213,7 +213,7 @@ Dado que los [componentes |components] son unidades reutilizables independientes
 Si queremos enlazar con presentadores en la plantilla de componentes, utilizaremos la etiqueta `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 o en el código
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Alias .[#toc-aliases]{data-version:v3.2.2}
+==========================================
+
+A veces resulta útil asignar un alias fácil de recordar a un par Presentador:acción. Por ejemplo, puede nombrar la página de inicio `Front:Home:default` simplemente como `home` o `Admin:Dashboard:default` como `admin`.
+
+Los alias se definen en la [configuración |configuration] con la clave `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+En los enlaces, se escriben utilizando el símbolo arroba, por ejemplo:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Se admiten en todos los métodos que trabajan con enlaces, como `redirect()` y similares.
+
+
 Enlaces no válidos .[#toc-invalid-links]
 ========================================
 
diff --git a/application/es/how-it-works.texy b/application/es/how-it-works.texy
index c23895a22f..e4e0447853 100644
--- a/application/es/how-it-works.texy
+++ b/application/es/how-it-works.texy
@@ -22,18 +22,18 @@ La estructura de directorios se parece a esto
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directorio con la aplicación
-│   ├── <b>Presenters/</b>           ← clases para presentadores
-│   │   ├── <b>HomePresenter.php</b> ← Home de inicio de la clase de presentador
-│   │   └── <b>templates/</b>        ← directorio de plantillas
-│   │       ├── <b>@layout.latte</b> ← plantilla de diseño compartida
-│   │       └── <b>Home/</b>         ← plantillas para Home presentador de inicio
-│   │           └── <b>default.latte</b>  ← plantilla para la acción `default`
-│   ├── <b>Router/</b>               ← configuración de direcciones URL
+│   ├── <b>Core/</b>                 ← clases básicas necesarias.
+│   │ └── <b>RouterFactory.php</b>   ← configuración de direcciones URL.
+│   ├── <b>UI/</b>                   ← presentadores, plantillas & co.
+│   │   ├── <b>@layout.latte</b>     ← plantilla de maquetación compartida
+│   │   └── <b>Home/</b>             ← Home directorio del presentador
+│   │       ├── <b>HomePresenter.php</b> ← Clase del presentador de inicio
+│   │       └── <b>default.latte</b> ← plantilla para la acción default
 │   └── <b>Bootstrap.php</b>         ← clase de arranque Bootstrap
 ├── <b>bin/</b>                      ← scripts para la línea de comandos
 ├── <b>config/</b>                   ← archivos de configuración
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← registros de errores
 ├── <b>temp/</b>                     ← archivos temporales, caché, ...
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ Las aplicaciones escritas en Nette se dividen en muchos de los llamados presenta
 
 La aplicación comienza pidiendo al llamado enrutador que decida a cuál de los presentadores debe pasar la petición actual para su procesamiento. El enrutador decide de quién es la responsabilidad. Mira la URL de entrada `https://example.com/product/123`, que quiere `show` un producto con `id: 123` como acción. Es una buena costumbre escribir pares de presentador + acción separados por dos puntos como `Product:show`.
 
-Así que el enrutador transforma la URL en un par `Presenter:action` + parámetros, en nuestro caso `Product:show` + `id: 123`. Puedes ver el aspecto de un enrutador en el archivo `app/Router/RouterFactory.php` y lo describiremos en detalle en el capítulo [Enrutamiento |Routing].
+Así que el enrutador transforma la URL en un par `Presenter:action` + parámetros, en nuestro caso `Product:show` + `id: 123`. Puedes ver el aspecto de un enrutador en el archivo `app/Core/RouterFactory.php` y lo describiremos en detalle en el capítulo [Enrutamiento |Routing].
 
 Sigamos. La aplicación ya conoce el nombre del presentador y puede continuar. Creando un objeto `ProductPresenter`, que es el código del presentador `Product`. Más concretamente, le pide al contenedor DI que cree el presentador, porque producir objetos es su trabajo.
 
@@ -121,12 +121,9 @@ Así, se llamó al método `renderShow(123)`, cuyo código es ficticio ejemplo,
 
 Posteriormente, el presentador devuelve la respuesta. Esta puede ser una página HTML, una imagen, un documento XML, el envío de un fichero desde disco, JSON o la redirección a otra página. Es importante destacar que, si no decimos explícitamente cómo responder (que es el caso de `ProductPresenter`), la respuesta será renderizar la plantilla con una página HTML. ¿Por qué? Pues porque en el 99% de los casos queremos dibujar una plantilla, así que el presentador toma este comportamiento por defecto y quiere facilitarnos el trabajo. Ese es el punto de Nette.
 
-Ni siquiera tenemos que indicar qué plantilla dibujar, él deriva la ruta hacia ella según una lógica simple. En el caso del presentador `Product` y la acción `show`, intenta ver si uno de estos archivos de plantilla existe en relación al directorio donde se encuentra la clase `ProductPresenter`:
+Ni siquiera necesitamos especificar qué plantilla renderizar; el framework deducirá la ruta por sí mismo. En el caso de la acción `show`, simplemente intenta cargar la plantilla `show.latte` en el directorio con la clase `ProductPresenter`. También intenta encontrar el diseño en el archivo `@layout.latte` (más información sobre la [búsqueda de plantillas |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-También intentará encontrar el diseño en el archivo `@layout.latte` y luego renderizará la plantilla. Ahora se completa la tarea del presentador y de toda la aplicación. Si la plantilla no existe, se devolverá una página con el error 404. Puedes leer más sobre los presentadores en la página de [Presentadores |Presenters].
+Posteriormente, se renderizan las plantillas. Esto completa la tarea del presentador y de toda la aplicación, y el trabajo está hecho. Si la plantilla no existiera, se devolvería una página de error 404. Puede leer más sobre los presentadores en la página [Presentadores |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Sólo para estar seguros, intentemos recapitular todo el proceso con una URL lig
 3) el router decodifica la URL como un par `Home:default`
 4) se crea un objeto `HomePresenter`
 5) se llama al método `renderDefault()` (si existe)
-6) se renderiza una plantilla `templates/Home/default.latte` con un diseño `templates/@layout.latte`
+6) se renderiza una plantilla `default.latte` con un diseño `@layout.latte`
 
 
 Puede que ahora te hayas encontrado con un montón de conceptos nuevos, pero creemos que tienen sentido. Crear aplicaciones en Nette es pan comido.
diff --git a/application/es/modules.texy b/application/es/modules.texy
index e183346e5f..2827183beb 100644
--- a/application/es/modules.texy
+++ b/application/es/modules.texy
@@ -2,29 +2,31 @@ Módulos
 *******
 
 .[perex]
-En Nette, los módulos representan las unidades lógicas que componen una aplicación. Incluyen presentadores, plantillas, posiblemente también componentes y clases modelo.
+Los módulos aportan claridad a las aplicaciones Nette al facilitar su división en unidades lógicas.
 
-Un directorio para los presentadores y otro para las plantillas no serían suficientes para los proyectos reales. Tener docenas de archivos en una carpeta es, como mínimo, desorganizado. ¿Cómo salir de ello? Simplemente los dividimos en subdirectorios en el disco y en espacios de nombres en el código. Y eso es exactamente lo que hacen los módulos de Nette.
-
-Así que olvidémonos de una única carpeta para presentadores y plantillas y en su lugar creemos módulos, por ejemplo `Admin` y `Front`.
+De forma similar a la organización de archivos en carpetas en un disco duro, en Nette podemos dividir los presentadores, plantillas y otras clases auxiliares en módulos. ¿Cómo funciona esto en la práctica? Simplemente incorporando nuevos subdirectorios a la estructura. He aquí un ejemplo de estructura con dos módulos, Front y Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directorio con módulos
-│   ├── <b>Admin/</b>            ← módulo Admin
-│   │   ├── <b>Presenters/</b>   ← sus presentadores
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← módulo Front
-│       └── <b>Presenters/</b>   ← sus presentadores
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Esta estructura de directorios se reflejará en los espacios de nombres de las clases, así por ejemplo `DashboardPresenter` estará en el espacio de nombres `App\Modules\Admin\Presenters`:
+Esta estructura de directorios se refleja en los espacios de nombres de las clases, así por ejemplo, `DashboardPresenter` se encuentra en el espacio de nombres `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-El presentador `Dashboard` dentro del módulo `Admin` es referenciado dentro de la aplicación usando la notación de dos puntos como `Admin:Dashboard`, y su acción `default` como `Admin:Dashboard:default`.
-¿Y cómo sabe Nette que `Admin:Dashboard` representa la clase `App\Modules\Admin\Presenters\DashboardPresenter`? Esto se determina mediante el [mapeo |#mapping] en la configuración.
-Por lo tanto, la estructura dada no es rígida y puede modificarla según sus necesidades.
+En la aplicación, nos referimos al presentador `Dashboard` dentro del módulo `Admin` utilizando la notación de dos puntos como `Admin:Dashboard`. Para su acción `default`, nos referimos a él como `Admin:Dashboard:default`.
+
+La estructura presentada no es rígida; puede [adaptarla totalmente a sus necesidades |#mapping] en la configuración. .[tip]
 
-Por supuesto, los módulos pueden contener todos los demás elementos además de presentadores y plantillas, como componentes, clases modelo, etc.
+Los módulos pueden incluir todos los demás archivos, como componentes y clases auxiliares, además de presentadores y plantillas. Si está pensando dónde colocarlos, considere la posibilidad de utilizar una carpeta `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Módulos anidados .[#toc-nested-modules]
 ---------------------------------------
 
-Los módulos no tienen por qué formar sólo una estructura plana, también puedes crear submódulos, por ejemplo:
+Los módulos pueden tener múltiples niveles de anidamiento, similar a una estructura de directorios en un disco:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directorio con módulos
-│   ├── <b>Blog/</b>             ← módulo Blog
-│   │   ├── <b>Admin/</b>        ← submódulo Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submódulo Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← módulo Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Así, el módulo `Blog` se divide en los submódulos `Admin` y `Front`. De nuevo, esto se reflejará en los espacios de nombres, que serán `App\Modules\Blog\Admin\Presenters`, etc. El presentador `Dashboard` dentro del submódulo se denomina `Blog:Admin:Dashboard`.
+El módulo `Blog` se divide en los submódulos `Admin` y `Front`. Esto también se refleja en los espacios de nombres, que aparecen como `App\UI\Blog\Admin` y similares. Para referirnos al presentador `Dashboard` dentro del submódulo `Admin`, lo denominamos `Blog:Admin:Dashboard`.
+
+El anidamiento puede ser tan profundo como sea necesario, permitiendo la creación de sub-submódulos.
 
-El anidamiento puede ser tan profundo como se desee, por lo que pueden crearse submódulos.
+Por ejemplo, si en administración tiene muchos presentadores relacionados con la gestión de pedidos, como `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., puede crear un módulo `Order` en el que se organizarán presentadores como `Detail`, `Edit`, `Dispatch`, y otros.
 
 
 Creación de enlaces .[#toc-creating-links]
@@ -99,50 +115,69 @@ Enrutamiento .[#toc-routing]
 Véase el [capítulo sobre en rutamiento|routing#Modules].
 
 
-Mapeo .[#toc-mapping]
----------------------
+Cartografía .[#toc-mapping]
+---------------------------
 
-Define las reglas por las que el nombre de la clase se deriva del nombre del presentador. Las escribimos en [configuración |configuration] bajo la clave `application › mapping`.
+El mapeo define las reglas para derivar el nombre de la clase del nombre del presentador. Estas reglas se especifican en la [configuración |configuration] bajo la clave `application › mapping`.
 
-Empecemos con un ejemplo que no utiliza módulos. Sólo querremos que las clases del presentador tengan el espacio de nombres `App\Presenters`. Eso significa que un presentador como `Home` debe mapearse a la clase `App\Presenters\HomePresenter`. Esto se puede lograr con la siguiente configuración:
+Las estructuras de directorios mencionadas anteriormente en esta página se basan en la siguiente asignación:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-El nombre del presentador se sustituye por el asterisco en la máscara de clase y el resultado es el nombre de la clase. Muy fácil.
+¿Cómo funciona el mapeo? Para entenderlo mejor, imaginemos primero una aplicación sin módulos. Queremos que las clases del presentador pertenezcan al espacio de nombres `App\UI`, de modo que el presentador `Home` se asigne a la clase `App\UI\HomePresenter`. Esto se puede lograr con esta configuración:
 
-Si dividimos a los presentadores en módulos, podemos tener nuestra propia asignación para cada módulo:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Este mapeo funciona reemplazando el asterisco en la máscara `App\UI\*Presenter` con el nombre del presentador `Home`, resultando en el nombre final de la clase `App\UI\HomePresenter`. Es muy sencillo.
+
+Sin embargo, como puede ver en los ejemplos de este y otros capítulos, colocamos las clases de presentador en subdirectorios epónimos, por ejemplo, el presentador `Home` se asigna a la clase `App\UI\Home\HomePresenter`. Esto se consigue duplicando el asterisco (requiere Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Pasemos ahora a la asignación de presentadores a módulos. Podemos definir asignaciones específicas para cada módulo:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Ahora el presentador `Front:Home` se asigna a la clase `App\Modules\Front\Presenters\HomePresenter` y el presentador `Admin:Dashboard` a la clase `App\Modules\Admin\Presenters\DashboardPresenter`.
+Según esta configuración, el presentador `Front:Home` se asigna a la clase `App\UI\Front\Home\HomePresenter`, mientras que el presentador `Api:OAuth` se asigna a la clase `App\Api\OAuthPresenter`.
 
-Es más práctico crear una regla general (estrella) para sustituir a las dos primeras. El asterisco adicional se añadirá a la máscara de clase sólo para el módulo:
+Puesto que los módulos `Front` y `Admin` tienen un enfoque de asignación similar y es probable que haya más módulos de este tipo, es posible crear una regla general que los sustituya. Se añade un nuevo asterisco para el módulo a la máscara de la clase:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Pero, ¿y si utilizamos módulos anidados y tenemos un presentador `Admin:User:Edit`? En este caso, el segmento con un asterisco que representa el módulo para cada nivel simplemente se repite y el resultado es la clase `App\Modules\Admin\User\Presenters\EditPresenter`.
+Para los módulos anidados de varios niveles, como el presentador `Admin:User:Edit`, el segmento del asterisco se repite para cada nivel, lo que da como resultado la clase `App\UI\Admin\User\Edit\EditPresenter`.
 
-Una notación alternativa es utilizar una matriz formada por tres segmentos en lugar de una cadena. Esta notación es equivalente a la anterior:
+Una notación alternativa consiste en utilizar una matriz compuesta por tres segmentos en lugar de una cadena. Esta notación es equivalente a la anterior:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-El valor por defecto es `*: *Module\*Presenter`.
+Si sólo tenemos una regla en la configuración, la general, podemos escribir brevemente:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/es/presenters.texy b/application/es/presenters.texy
index c85c74305c..ee6f551d6c 100644
--- a/application/es/presenters.texy
+++ b/application/es/presenters.texy
@@ -60,7 +60,7 @@ Similar al método `render<View>()`. Mientras que `render<View>()` está destina
 
 Es importante que `action<Action>()` se llame antes que `render<View>()`para que dentro de él podamos posiblemente cambiar el siguiente curso del ciclo de vida, es decir, cambiar la plantilla que será renderizada y también el método `render<View>()` que será llamado, usando `setView('otherView')`.
 
-Los parámetros de la petición se pasan al método. Es posible y recomendable especificar tipos para los parámetros, por ejemplo `actionShow(int $id, string $slug = null)` - si el parámetro `id` falta o si no es un entero, el presentador devuelve [el error 404 |#Error 404 etc.] y termina la operación.
+Los parámetros de la petición se pasan al método. Es posible y recomendable especificar tipos para los parámetros, por ejemplo `actionShow(int $id, ?string $slug = null)` - si el parámetro `id` falta o si no es un entero, el presentador devuelve [el error 404 |#Error 404 etc.] y termina la operación.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ En la plantilla, estos mensajes están disponibles en la variable `$flashes` com
 Error 404 etc. .[#toc-error-404-etc]
 ====================================
 
-Cuando no podamos satisfacer la petición porque por ejemplo el artículo que queremos mostrar no existe en la base de datos, lanzaremos el error 404 utilizando el método `error(string $message = null, int $httpCode = 404)`, que representa el error HTTP 404:
+Cuando no podamos satisfacer la petición porque por ejemplo el artículo que queremos mostrar no existe en la base de datos, lanzaremos el error 404 utilizando el método `error(?string $message = null, int $httpCode = 404)`, que representa el error HTTP 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parámetros de solicitud .[#toc-request-parameters]
+==================================================
+
+El presentador, al igual que todos los componentes, obtiene sus parámetros de la petición HTTP. Sus valores pueden recuperarse utilizando el método `getParameter($name)` o `getParameters()`. Los valores son cadenas o matrices de cadenas, esencialmente datos sin procesar obtenidos directamente de la URL.
+
+Para mayor comodidad, recomendamos que los parámetros sean accesibles a través de propiedades. Basta con anotarlas con el atributo `#[Parameter]` atributo:
+
+```php
+use Nette\Application\Attributes\Parameter;  // esta línea es importante
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // debe ser pública
+}
+```
+
+Para las propiedades, le sugerimos que especifique el tipo de datos (por ejemplo, `string`). A continuación, Nette asignará automáticamente el valor basándose en él. Los valores de los parámetros también pueden [validarse |#Validation of Parameters].
+
+Al crear un enlace, puede establecer directamente el valor de los parámetros:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Parámetros persistentes .[#toc-persistent-parameters]
 =====================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Si `$this->lang` tiene un valor como `'en'`, entonces los enlaces creados usando `link()` o `n:href` también contendrán el parámetro `lang=en`. Y cuando se haga clic en el enlace, volverá a ser `$this->lang = 'en'`.
 
-Para las propiedades, se recomienda incluir el tipo de datos (por ejemplo, `string`) y también se puede incluir un valor por defecto. Los valores de los parámetros se pueden [validar |#Validation of Persistent Parameters].
+Para las propiedades, le recomendamos que incluya el tipo de datos (por ejemplo, `string`) y también puede incluir un valor por defecto. Los valores de los parámetros se pueden [validar |#Validation of Parameters].
 
 Los parámetros persistentes se pasan entre todas las acciones de un presentador determinado por defecto. Para pasarlos entre varios presentadores, es necesario definirlos:
 
@@ -307,18 +333,12 @@ Profundizando .[#toc-going-deeper]
 Lo que hemos mostrado hasta ahora en este capítulo probablemente será suficiente. Las líneas siguientes están pensadas para quienes estén interesados en los presentadores en profundidad y quieran saberlo todo.
 
 
-Requisitos y parámetros .[#toc-requirement-and-parameters]
-----------------------------------------------------------
+Validación de parámetros .[#toc-validation-of-parameters]
+---------------------------------------------------------
 
-La solicitud gestionada por el presentador es el objeto [api:Nette\Application\Request] y es devuelta por el método del presentador `getRequest()`. Incluye una matriz de parámetros y cada uno de ellos pertenece a alguno de los componentes o directamente al presentador (que en realidad también es un componente, aunque especial). Así pues, Nette redistribuye los parámetros y los pasa entre los distintos componentes (y el presentador) llamando al método `loadState(array $params)`. Los parámetros pueden obtenerse mediante el método `getParameters(): array`, individualmente mediante `getParameter($name)`. Los valores de los parámetros son cadenas o matrices de cadenas, son básicamente datos en bruto obtenidos directamente de una URL.
+Los valores de los parámetros de [petición |#request parameters] y [de los parámetros persistentes |#persistent parameters] recibidos de las URLs son escritos en propiedades por el método `loadState()`. También comprueba si el tipo de datos especificado en la propiedad coincide, de lo contrario responderá con un error 404 y la página no se mostrará.
 
-
-Validación de parámetros persistentes .[#toc-validation-of-persistent-parameters]
----------------------------------------------------------------------------------
-
-Los valores de los parámetros [persistentes |#persistent parameters] recibidos de las URLs son escritos en propiedades por el método `loadState()`. También comprueba si el tipo de datos especificado en la propiedad coincide, de lo contrario responderá con un error 404 y no se mostrará la página.
-
-Nunca confíes ciegamente en los parámetros persistentes, ya que pueden ser fácilmente sobrescritos por el usuario en la URL. Por ejemplo, así es como comprobamos si `$this->lang` está entre los idiomas soportados. Una buena forma de hacerlo es sobrescribir el método `loadState()` mencionado anteriormente:
+Nunca confíes ciegamente en los parámetros, ya que pueden ser fácilmente sobrescritos por el usuario en la URL. Por ejemplo, así es como comprobamos si `$this->lang` está entre los idiomas soportados. Una buena forma de hacerlo es sobrescribir el método `loadState()` mencionado anteriormente:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Guardar y restaurar la petición .[#toc-save-and-restore-the-request]
 --------------------------------------------------------------------
 
-Puede guardar la solicitud actual en una sesión o restaurarla desde la sesión y dejar que el presentador la ejecute de nuevo. Esto es útil, por ejemplo, cuando un usuario rellena un formulario y su login expira. Para no perder datos, antes de redirigir a la página de inicio de sesión, guardamos la solicitud actual en la sesión utilizando `$reqId = $this->storeRequest()`, que devuelve un identificador en forma de cadena corta y lo pasa como parámetro al presentador de inicio de sesión.
+La solicitud que gestiona el presentador es un objeto [api:Nette\Application\Request] y la devuelve el método del presentador `getRequest()`.
+
+Puede guardar la solicitud actual en una sesión o restaurarla desde la sesión y dejar que el presentador la ejecute de nuevo. Esto es útil, por ejemplo, cuando un usuario rellena un formulario y su login caduca. Para no perder datos, antes de redirigir a la página de inicio de sesión, guardamos la solicitud actual en la sesión mediante `$reqId = $this->storeRequest()`, que devuelve un identificador en forma de cadena corta y lo pasa como parámetro al presentador de inicio de sesión.
 
 Después de iniciar sesión, llamamos al método `$this->restoreRequest($reqId)`, que recoge la solicitud de la sesión y se la reenvía. El método verifica que la petición ha sido creada por el mismo usuario que ahora ha iniciado la sesión. Si otro usuario inicia sesión o la clave no es válida, no hace nada y el programa continúa.
 
@@ -362,7 +384,7 @@ La redirección no se produce con una solicitud AJAX o POST porque provocaría u
 También puede invocar la canonización manualmente mediante el método `canonicalize()`, que, al igual que el método `link()`, recibe el presentador, las acciones y los parámetros como argumentos. Crea un enlace y lo compara con la URL actual. Si es diferente, redirige al enlace generado.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// redirects if $slug is different from $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Restricción de acceso mediante `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+----------------------------------------------------------------------------------------------------------
+
+El atributo `#[Requires]` ofrece opciones avanzadas para restringir el acceso a los presentadores y sus métodos. Puede utilizarse para especificar métodos HTTP, requerir solicitudes AJAX, limitar el acceso al mismo origen y restringir el acceso sólo al reenvío. El atributo puede aplicarse a clases de presentadores, así como a métodos individuales como `action<Action>()`, `render<View>()`, `handle<Signal>()`y `createComponent<Name>()`.
+
+Puede especificar estas restricciones
+- en los métodos HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- que requieren una petición AJAX: `#[Requires(ajax: true)]`
+- acceso sólo desde el mismo origen: `#[Requires(sameOrigin: true)]`
+- acceso sólo mediante reenvío: `#[Requires(forward: true)]`
+- restricciones sobre acciones específicas: `#[Requires(actions: 'default')]`
+
+Para obtener más información, consulte [Cómo utilizar el atributo Requires atributo |best-practices:attribute-requires].
+
+
+Comprobación del método HTTP .[#toc-http-method-check]
+------------------------------------------------------
+
+En Nette, los presentadores verifican automáticamente el método HTTP de cada solicitud entrante, principalmente por razones de seguridad. Por defecto, se permiten los métodos `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Si desea habilitar métodos adicionales como `OPTIONS`, puede utilizar el atributo `#[Requires]` (a partir de Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+En la versión 3.1, la verificación se realiza en `checkHttpMethod()`, que comprueba si el método especificado en la petición está incluido en el array `$presenter->allowedMethods`. Añade un método como este
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Es crucial enfatizar que si permite el método `OPTIONS`, también debe manejarlo adecuadamente dentro de su presentador. Este método se utiliza a menudo como una solicitud de comprobación previa, que los navegadores envían automáticamente antes de la solicitud real cuando es necesario determinar si la solicitud está permitida desde el punto de vista de la política CORS (Cross-Origin Resource Sharing). Si permite este método pero no implementa una respuesta adecuada, puede provocar incoherencias y posibles problemas de seguridad.
+
+
 Lecturas complementarias .[#toc-further-reading]
 ================================================
 
diff --git a/application/es/routing.texy b/application/es/routing.texy
index c6ed0f3950..417438e650 100644
--- a/application/es/routing.texy
+++ b/application/es/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Notación avanzada .[#toc-advanced-notation]
 -------------------------------------------
 
-El segundo parámetro de la ruta, que a menudo escribimos en el formato `Presenter:action`, es una abreviatura, que también podemos escribir en forma de campo, donde indicamos directamente los valores (por defecto) de los parámetros individuales:
+El objetivo de una ruta, normalmente escrito en la forma `Presenter:action`, también puede expresarse utilizando una matriz que defina parámetros individuales y sus valores por defecto:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-O podemos utilizar esta forma, observe la reescritura de la expresión regular de validación:
+Para una especificación más detallada, se puede utilizar una forma aún más extendida, en la que además de los valores por defecto, se pueden establecer otras propiedades de los parámetros, como una expresión regular de validación (véase el parámetro `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Estos formatos más locuaces son útiles para añadir otros metadatos.
+Es importante señalar que si los parámetros definidos en la matriz no se incluyen en la máscara de ruta, sus valores no podrán modificarse, ni siquiera utilizando parámetros de consulta especificados tras un signo de interrogación en la URL.
 
 
 Filtros y traducciones .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integración .[#toc-integration]
 ===============================
 
-Para conectar nuestro router a la aplicación, debemos informar al contenedor DI sobre él. La forma más sencilla es preparar la fábrica que construirá el objeto router y decirle a la configuración del contenedor que lo utilice. Digamos que escribimos un método para este propósito `App\Router\RouterFactory::createRouter()`:
+Para conectar nuestro router a la aplicación, debemos informar al contenedor DI sobre él. La forma más sencilla es preparar la fábrica que construirá el objeto router y decirle a la configuración del contenedor que lo utilice. Digamos que escribimos un método para este propósito `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Luego escribimos en [configuración |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Cualquier dependencia, como una conexión de base de datos, etc., se pasa al método de fábrica como sus parámetros utilizando [autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Por uso separado, nos referimos al uso de las capacidades del router en una apli
 Así que de nuevo crearemos un método que construirá un enrutador, por ejemplo
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 O crearemos los objetos directamente:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/es/templates.texy b/application/es/templates.texy
index 761f7a648e..af06db6505 100644
--- a/application/es/templates.texy
+++ b/application/es/templates.texy
@@ -34,35 +34,81 @@ Y esta podría ser la plantilla de acción:
 Define el bloque `content`, que se inserta en lugar de `{include content}` en el diseño, y también redefine el bloque `title`, que sobrescribe `{block title}` en el diseño. Intenta imaginar el resultado.
 
 
-Búsqueda de plantillas .[#toc-search-for-templates]
----------------------------------------------------
+Búsqueda de plantillas .[#toc-template-lookup]
+----------------------------------------------
 
-La ruta a las plantillas se deduce según una lógica simple. Se intenta ver si uno de estos archivos de plantilla existe en relación con el directorio donde se encuentra la clase de presentador, donde `<Presenter>` es el nombre del presentador actual y `<view>` es el nombre de la acción actual:
+En los presentadores, no es necesario especificar qué plantilla debe renderizarse; el framework determinará automáticamente la ruta, facilitándole la codificación.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Si utiliza una estructura de directorios donde cada presentador tiene su propio directorio, simplemente coloque la plantilla en este directorio bajo el nombre de la acción (es decir, vista). Por ejemplo, para la acción `default`, utilice la plantilla `default.latte`:
 
-Si no se encuentra la plantilla, se intentará buscar en el directorio `templates` un nivel más arriba, es decir, al mismo nivel que el directorio con la clase presentadora.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Si la plantilla tampoco se encuentra allí, la respuesta es un [error 404 |presenters#Error 404 etc.].
+Si utiliza una estructura en la que los presentadores están juntos en un directorio y las plantillas en una carpeta `templates`, guárdela en un archivo `<Presenter>.<view>.latte` o en `<Presenter>/<view>.latte`:
 
-También puede cambiar la vista utilizando `$this->setView('otherView')`. O, en lugar de buscar, especifique directamente el nombre del archivo de plantilla utilizando `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+El directorio `templates` también puede colocarse un nivel más arriba, al mismo nivel que el directorio con las clases de presentador.
+
+Si no se encuentra la plantilla, el presentador responde con el [error 404 - página no encontrada |presenters#Error 404 etc].
+
+Puede cambiar la vista utilizando `$this->setView('anotherView')`. También es posible especificar directamente el archivo de plantilla con `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Puede cambiar las rutas donde se buscan las plantillas anulando el método [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que devuelve una matriz de posibles rutas de archivo.
+Los archivos en los que se buscan las plantillas pueden cambiarse anulando el método [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que devuelve una matriz de posibles nombres de archivo.
+
+
+Búsqueda de plantillas de diseño .[#toc-layout-template-lookup]
+---------------------------------------------------------------
+
+Nette también busca automáticamente el archivo de diseño.
+
+Si utiliza una estructura de directorios en la que cada presentador tiene su propio directorio, coloque la maqueta en la carpeta con el presentador, si es específica sólo para él, o en un nivel superior si es común a varios presentadores:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Si utiliza una estructura en la que los presentadores están agrupados en un directorio y las plantillas se encuentran en una carpeta `templates`, la maquetación se esperará en los siguientes lugares:
 
-El diseño se espera en los siguientes archivos:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` diseño común a varios presentadores
+Si el presentador está en un [módulo |modules], también buscará más arriba en el árbol de directorios según el anidamiento del módulo.
 
-`<Presenter>` es el nombre del presentador actual y `<layout>` es el nombre de la maquetación, que por defecto es `'layout'`. El nombre puede cambiarse con `$this->setLayout('otherLayout')`, de modo que se intentarán los archivos `@otherLayout.latte`.
+El nombre de la presentación puede cambiarse utilizando `$this->setLayout('layoutAdmin')` y entonces se esperará en el archivo `@layoutAdmin.latte`. También puede especificar directamente el archivo de plantilla de presentación utilizando `$this->setLayout('/path/to/template.latte')`.
 
-También puede especificar directamente el nombre de archivo de la plantilla de maquetación con `$this->setLayout('/path/to/template.latte')`. El uso de `$this->setLayout(false)` desactivará la búsqueda de diseños.
+El uso de `$this->setLayout(false)` o de la etiqueta `{layout none}` dentro de la plantilla desactiva la búsqueda de diseños.
 
 .[note]
-Puede cambiar las rutas donde se buscan las plantillas anulando el método [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que devuelve una matriz de posibles rutas de archivo.
+Los archivos en los que se buscan las plantillas de diseño pueden modificarse modificando el método [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que devuelve una matriz de posibles nombres de archivo.
 
 
 Variables en la plantilla .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ La anotación `@property-read` es para IDE y análisis estático, hará que func
 Puedes permitirte el lujo de susurrar en las plantillas también, simplemente instala el plugin Latte en PhpStorm y especifica el nombre de la clase al principio de la plantilla, ver el artículo "Latte: cómo escribir sistema:https://blog.nette.org/es/latte-como-utilizar-el-sistema-de-tipos":
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 La versión 3 de Latte ofrece una forma más avanzada creando una [extensión |latte:creating-extension] para cada proyecto web. He aquí un ejemplo aproximado de una clase de este tipo:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ La registramos usando [configuration|configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternativamente, el traductor se puede establecer utilizando la [configuración
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 El traductor puede utilizarse, por ejemplo, como un filtro `|translate`, con parámetros adicionales pasados al método `translate()` (véase `foo, bar`):
diff --git a/application/fr/@home.texy b/application/fr/@home.texy
index f0388b9636..9117a6be9c 100644
--- a/application/fr/@home.texy
+++ b/application/fr/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | version | compatible avec PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 - 8.2
-| Nette Application 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/fr/ajax.texy b/application/fr/ajax.texy
index 55c07c6dc6..d93abac2f4 100644
--- a/application/fr/ajax.texy
+++ b/application/fr/ajax.texy
@@ -1,12 +1,12 @@
-AJAX et Snippets
-****************
+AJAX & Snippets
+***************
 
 <div class=perex>
 
-Les applications web modernes fonctionnent aujourd'hui pour moitié sur un serveur et pour moitié dans un navigateur. AJAX est un facteur d'unité essentiel. Quel est le support offert par le Nette Framework ?
-- l'envoi de fragments de modèles (appelés *snippets*)
+À l'ère des applications web modernes, où les fonctionnalités s'étendent souvent entre le serveur et le navigateur, AJAX est un élément de connexion essentiel. Quelles sont les possibilités offertes par le Nette Framework dans ce domaine ?
+- l'envoi de parties du modèle, appelées "snippets
 - le passage de variables entre PHP et JavaScript
-- débogage des applications AJAX
+- outils de débogage des requêtes AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ Les applications web modernes fonctionnent aujourd'hui pour moitié sur un serve
 Demande AJAX .[#toc-ajax-request]
 =================================
 
-Une requête AJAX ne diffère pas d'une requête classique : le diffuseur est appelé avec une vue et des paramètres spécifiques. C'est également au présentateur de décider comment y répondre : il peut utiliser sa propre routine, qui renvoie un fragment de code HTML (extrait HTML), un document XML, un objet JSON ou du code JavaScript.
+Une requête AJAX ne diffère pas fondamentalement d'une requête HTTP classique. Un présentateur est appelé avec des paramètres spécifiques. C'est au présentateur de décider comment répondre à la requête - il peut renvoyer des données au format JSON, envoyer une partie du code HTML, un document XML, etc.
 
-Côté serveur, une requête AJAX peut être détectée à l'aide de la méthode de service [encapsulant la requête HTTP |http:request] `$httpRequest->isAjax()` (détection basée sur l'en-tête HTTP `X-Requested-With`). Dans le présentateur, un raccourci est disponible sous la forme de la méthode `$this->isAjax()`.
+Du côté du navigateur, nous lançons une requête AJAX à l'aide de la fonction `fetch()`:
 
-Il existe un objet prétraité appelé `payload` dédié à l'envoi de données au navigateur en JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// traitement de la réponse
+});
 ```
 
-Pour un contrôle total de votre sortie JSON, utilisez la méthode `sendJson` dans votre présentateur. Elle met immédiatement fin au présentateur et vous vous passerez de modèle :
+Du côté du serveur, une requête AJAX est reconnue par la méthode `$httpRequest->isAjax()` du service [encapsulant la requête HTTP |http:request]. Elle utilise l'en-tête HTTP `X-Requested-With`, qu'il est donc essentiel d'envoyer. Dans le présentateur, vous pouvez utiliser la méthode `$this->isAjax()`.
+
+Si vous souhaitez envoyer des données au format JSON, utilisez la méthode [`sendJson()` |presenters#Sending a response] méthode. La méthode met également fin à l'activité du présentateur.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Si nous voulons envoyer du HTML, nous pouvons soit définir un modèle spécial pour les demandes AJAX :
+Si vous envisagez de répondre avec un modèle spécial conçu pour AJAX, vous pouvez procéder comme suit :
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Bribes .[#toc-snippets]
+=======================
+
+Les snippets sont l'outil le plus puissant offert par Nette pour connecter le serveur au client. Grâce à eux, vous pouvez transformer une application ordinaire en une application AJAX avec un minimum d'effort et quelques lignes de code. L'exemple Fifteen montre comment tout cela fonctionne, et son code peut être trouvé sur [GitHub |https://github.com/nette-examples/fifteen].
+
+Les snippets, ou clippings, vous permettent de ne mettre à jour que certaines parties de la page, au lieu de recharger toute la page. C'est plus rapide et plus efficace, et l'expérience utilisateur est plus confortable. Les snippets peuvent vous rappeler Hotwire pour Ruby on Rails ou Symfony UX Turbo. Il est intéressant de noter que Nette a introduit les snippets 14 ans plus tôt.
+
+Comment fonctionnent les snippets ? Lorsque la page est chargée pour la première fois (requête non-AJAX), la page entière, y compris tous les snippets, est chargée. Lorsque l'utilisateur interagit avec la page (par exemple, lorsqu'il clique sur un bouton, soumet un formulaire, etc.), au lieu de charger la page entière, une requête AJAX est effectuée. Le code du présentateur exécute l'action et décide quels extraits doivent être mis à jour. Nette rend ces extraits et les envoie sous la forme d'un tableau JSON. Le code de traitement du navigateur réintègre alors les extraits reçus dans la page. Par conséquent, seul le code des extraits modifiés est transféré, ce qui permet d'économiser de la bande passante et d'accélérer le chargement par rapport au transfert de l'ensemble du contenu de la page.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-La [bibliothèque Naja |https://naja.js.org] est utilisée pour gérer les requêtes AJAX du côté du navigateur. [Installez-la |https://naja.js.org/#/guide/01-install-setup-naja] en tant que paquet node.js (à utiliser avec Webpack, Rollup, Vite, Parcel et plus) :
+La [bibliothèque Naja |https://naja.js.org] est utilisée pour gérer les snippets du côté du navigateur. [Installez-la |https://naja.js.org/#/guide/01-install-setup-naja] en tant que paquetage node.js (pour une utilisation avec des applications telles que Webpack, Rollup, Vite, Parcel, et d'autres) :
 
 ```shell
 npm install naja
 ```
 
-...ou insérez-la directement dans le modèle de page :
+... ou insérez-la directement dans le modèle de page :
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Pour créer une requête AJAX à partir d'un lien normal (signal) ou d'une soumission de formulaire, il suffit de marquer le lien, le formulaire ou le bouton concerné avec la classe `ajax`:
+Vous devez d'abord [initialiser |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] la bibliothèque :
+
+```js
+naja.initialize();
+```
+
+Pour faire d'un lien ordinaire (signal) ou d'une soumission de formulaire une requête AJAX, il suffit de marquer le lien, le formulaire ou le bouton correspondant avec la classe `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Pour créer une requête AJAX à partir d'un lien normal (signal) ou d'une soumi
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Extraits de texte .[#toc-snippets]
-==================================
-
-Il existe un outil bien plus puissant que le support AJAX intégré : les snippets. Leur utilisation permet de transformer une application ordinaire en une application AJAX en utilisant seulement quelques lignes de code. La façon dont tout cela fonctionne est démontrée dans l'exemple Fifteen dont le code est également accessible dans le build ou sur [GitHub |https://github.com/nette-examples/fifteen].
-
-Le fonctionnement des snippets est le suivant : la page entière est transférée lors de la requête initiale (c'est-à-dire non-AJAX), puis à chaque [sous-requête |components#signal] AJAX (requête de la même vue du même présentateur), seul le code des parties modifiées est transféré dans le dépôt `payload` mentionné précédemment.
-
-Les snippets vous rappellent peut-être Hotwire pour Ruby on Rails ou Symfony UX Turbo, mais Nette les a inventés quatorze ans plus tôt.
-
+Redessiner des extraits .[#toc-redrawing-snippets]
+--------------------------------------------------
 
-Invalidation des Snippets .[#toc-invalidation-of-snippets]
-==========================================================
-
-Chaque descendant de la classe [Control |components] (ce qu'est aussi un Presenter) est capable de se souvenir si des changements sont intervenus au cours d'une requête qui nécessitent un nouveau rendu. Il existe une paire de méthodes pour gérer cela : `redrawControl()` et `isControlInvalid()`. Un exemple :
+Chaque objet de la classe [Control |components] (y compris le Presenter lui-même) garde une trace des changements survenus qui nécessitent son redécoupage. La méthode `redrawControl()` est utilisée à cette fin.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// L'objet doit être rendu à nouveau après que l'utilisateur se soit connecté.
+	// après la connexion, il est nécessaire de redessiner la partie concernée
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette offre cependant une résolution encore plus fine que les composants entiers. Les méthodes listées acceptent le nom d'un "snippet" comme paramètre optionnel. Un "snippet" est en fait un élément de votre modèle marqué à cet effet par une tag Latte, nous y reviendrons plus tard. Il est donc possible de demander à un composant de ne redessiner que des *parties* de son modèle. Si le composant entier est invalidé, tous ses snippets sont redessinés. Un composant est également "invalide" si l'un de ses sous-composants est invalide.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // invalide le snippet nommé 'header'.
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, au moins un extrait est invalide.
+Nette permet également un contrôle plus fin de ce qui doit être redessiné. La méthode susmentionnée peut prendre le nom de l'extrait comme argument. Ainsi, il est possible d'invalider (c'est-à-dire de forcer un nouveau dessin) au niveau de la partie du modèle. Si l'ensemble du composant est invalidé, chaque extrait est également redessiné :
 
-$this->redrawControl(); // invalide l'ensemble du composant, chaque extrait.
-$this->isControlInvalid('footer'); // -> true
+```php
+// invalide l'extrait "header" (en-tête)
+$this->redrawControl('header');
 ```
 
-Un composant qui reçoit un signal est automatiquement marqué pour être redessiné.
-
-Grâce au redessin de snippet, nous savons exactement quelles parties de quels éléments doivent être redessinées.
-
-
-Balise `{snippet} … {/snippet}` .{toc: Tag snippet}
-===================================================
-
-Le rendu de la page se déroule de manière très similaire à une requête ordinaire : les mêmes modèles sont chargés, etc. L'essentiel est toutefois de laisser de côté les parties qui ne sont pas censées atteindre la sortie ; les autres parties doivent être associées à un identifiant et envoyées à l'utilisateur dans un format compréhensible pour un gestionnaire JavaScript.
-
 
-Syntaxe .[#toc-syntax]
-----------------------
+Bribes dans Latte .[#toc-snippets-in-latte]
+-------------------------------------------
 
-Si le modèle contient un contrôle ou un extrait, nous devons l'envelopper à l'aide de la balise de paire `{snippet} ... {/snippet}`. Elle veillera à ce que l'extrait rendu soit "découpé" et envoyé au navigateur. Elle l'enfermera également dans une balise auxiliaire `<div>` (il est possible d'en utiliser une autre). Dans l'exemple suivant, un extrait nommé `header` est défini. Il peut tout aussi bien représenter le modèle d'un composant :
+L'utilisation des snippets dans Latte est extrêmement simple. Pour définir une partie du modèle comme un extrait, il suffit de l'entourer des balises `{snippet}` et `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Si le modèle contient un contrôle ou un extrait, nous devons l'envelopper à l
 {/snippet}
 ```
 
-Si vous souhaitez créer un snippet avec un élément contenant différent de `<div>` ou ajouter des attributs personnalisés à l'élément, vous pouvez utiliser la définition suivante :
+Le snippet crée un élément `<div>` dans la page HTML avec un `id` spécialement généré. Lorsqu'un extrait est redessiné, le contenu de cet élément est mis à jour. Par conséquent, lors du rendu initial de la page, tous les snippets doivent également être rendus, même s'ils sont initialement vides.
+
+Vous pouvez également créer un extrait avec un élément autre que `<div>` à l'aide d'un attribut n: :
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Si vous souhaitez créer un snippet avec un élément contenant différent de `<
 ```
 
 
-Dynamic Snippets .[#toc-dynamic-snippets]
-=========================================
+Zones d'échantillonnage .[#toc-snippet-areas]
+---------------------------------------------
 
-Dans Nette, vous pouvez également définir des snippets avec un nom dynamique basé sur un paramètre d'exécution. C'est la solution la plus appropriée pour les listes diverses où nous devons modifier une seule ligne mais où nous ne voulons pas transférer toute la liste avec elle. Un exemple de ceci serait :
+Les noms des snippets peuvent également être des expressions :
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Il y a un snippet statique appelé `itemsContainer`, contenant plusieurs snippets dynamiques : `item-0`, `item-1` et ainsi de suite.
+De cette manière, nous obtiendrons plusieurs snippets comme `item-0`, `item-1`, etc. Si nous devions invalider directement un extrait dynamique (par exemple, `item-1`), rien ne serait redessiné. La raison en est que les snippets fonctionnent comme de véritables extraits et qu'ils sont les seuls à être rendus directement. Cependant, dans le modèle, il n'y a pas techniquement d'extrait nommé `item-1`. Il n'apparaît que lors de l'exécution du code environnant de l'extrait, dans ce cas, la boucle foreach. Par conséquent, nous marquerons la partie du modèle qui doit être exécutée avec la balise `{snippetArea}`:
 
-Vous ne pouvez pas redessiner un extrait dynamique directement (redessiner `item-1` n'a aucun effet), vous devez redessiner son extrait parent (dans cet exemple `itemsContainer`). Le code du snippet parent est alors exécuté, mais seuls ses sous-snippets sont envoyés au navigateur. Si vous souhaitez n'envoyer qu'un seul des sous-ensembles, vous devez modifier l'entrée du snippet parent pour ne pas générer les autres sous-ensembles.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-Dans l'exemple ci-dessus, vous devez vous assurer que, pour une requête AJAX, un seul élément sera ajouté au tableau `$list`. Par conséquent, la boucle `foreach` n'imprimera qu'un seul extrait dynamique.
+Et nous redessinerons à la fois l'extrait individuel et l'ensemble de la zone globale :
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Il est également essentiel de s'assurer que le tableau `$items` ne contient que les éléments qui doivent être redessinés.
 
-Extraits dans un modèle inclus .[#toc-snippets-in-an-included-template]
-=======================================================================
-
-Il peut arriver que le snippet se trouve dans un modèle qui est inclus à partir d'un autre modèle. Dans ce cas, nous devons envelopper le code d'inclusion dans le second modèle avec la tag `snippetArea`, puis nous redessinons à la fois la snippetArea et le snippet lui-même.
-
-La tag `snippetArea` garantit que le code qu'elle contient est exécuté mais que seul l'extrait réel du modèle inclus est envoyé au navigateur.
+Lors de l'insertion d'un autre modèle dans le modèle principal à l'aide de la balise `{include}`, qui contient des extraits, il est nécessaire d'envelopper à nouveau le modèle inclus dans une balise `snippetArea` et d'invalider à la fois l'extrait et la zone :
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* inclus.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Vous pouvez également la combiner avec des extraits dynamiques.
 
+Les snippets dans les composants .[#toc-snippets-in-components]
+---------------------------------------------------------------
 
-Ajout et suppression .[#toc-adding-and-deleting]
-================================================
-
-Si vous ajoutez un nouvel élément dans la liste et que vous invalidez `itemsContainer`, la requête AJAX renvoie des extraits incluant le nouvel élément, mais le gestionnaire javascript ne sera pas en mesure de le rendre. Cela est dû au fait qu'il n'y a pas d'élément HTML avec l'ID nouvellement créé.
-
-Dans ce cas, le moyen le plus simple est d'envelopper toute la liste dans un autre extrait et de l'invalider :
+Vous pouvez créer des snippets dans les [composants |components], et Nette les redessinera automatiquement. Cependant, il y a une limitation spécifique : pour redessiner les snippets, il faut appeler la méthode `render()` sans aucun paramètre. Par conséquent, passer des paramètres dans le modèle ne fonctionnera pas :
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Envoi de données utilisateur .[#toc-sending-user-data]
+------------------------------------------------------
+
+En plus des snippets, vous pouvez envoyer des données supplémentaires au client. Il suffit de les écrire dans l'objet `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Il en va de même pour la suppression d'un élément. Il serait possible d'envoyer un extrait vide, mais les listes peuvent généralement être paginées et il serait compliqué d'implémenter la suppression d'un élément et le chargement d'un autre (qui se trouvait sur une page différente de la liste paginée).
-
 
-Envoi de paramètres au composant .[#toc-sending-parameters-to-component]
-========================================================================
+Paramètres d'envoi .[#toc-sending-parameters]
+=============================================
 
-Lorsque nous envoyons des paramètres au composant via une requête AJAX, qu'il s'agisse de paramètres de signal ou de paramètres persistants, nous devons fournir leur nom global, qui contient également le nom du composant. Le nom global du paramètre renvoie la méthode `getParameterId()`.
+Lorsque nous envoyons des paramètres au composant via une requête AJAX, qu'il s'agisse de paramètres de signal ou de paramètres persistants, nous devons fournir leur nom global, qui contient également le nom du composant. Le nom complet du paramètre renvoie la méthode `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Et traiter la méthode avec les paramètres correspondants dans le composant.
+Une méthode handle avec les paramètres correspondants dans le composant :
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/fr/bootstrap.texy b/application/fr/bootstrap.texy
index 8bea659e34..32c12e829b 100644
--- a/application/fr/bootstrap.texy
+++ b/application/fr/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Le configurateur est chargé de configurer l'environnement et les services de l'application.
+		$this->configurator = new Configurator;
+		// Définir le répertoire pour les fichiers temporaires générés par Nette (par exemple, les modèles compilés)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette est intelligent, et le mode développement est activé automatiquement,
+		// ou vous pouvez l'activer pour une adresse IP spécifique en décommentant la ligne suivante:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Active Tracy: l'ultime outil de débogage "couteau suisse".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: charge automatiquement toutes les classes dans le répertoire donné
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Chargement des fichiers de configuration
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Dans le cas des applications web, le fichier initial est `index.php`, qui se trouve dans le répertoire public `www/`. Il laisse la classe `Bootstrap` pour initialiser l'environnement et retourne la classe `$configurator` qui crée le conteneur DI. Ensuite, il obtient le service `Application`, qui exécute l'application web :
+Le fichier initial des applications web est `index.php`, situé dans le répertoire public `www/`. Il utilise la classe `Bootstrap` pour initialiser l'environnement et créer un conteneur DI. Ensuite, il obtient le service `Application` du conteneur, ce qui lance l'application web :
 
 ```php
-// initialisation de l'environnement + obtention de l'objet Configurateur
-$configurator = App\Bootstrap::boot();
-// créer un conteneur DI
-$container = $configurator->createContainer();
+$bootstrap = new App\Bootstrap;
+// Initialiser l'environnement + créer un conteneur DI
+$container = $bootstrap->bootWebApplication();
 // Le conteneur DI crée un objet Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// Démarrage de l'application Nette
+// Démarrer l'application Nette et traiter la demande entrante
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ La sélection du mode se fait par autodétection, il n'est donc généralement p
 Si vous souhaitez activer le mode développement dans d'autres cas, par exemple pour les programmeurs accédant depuis une adresse IP spécifique, vous pouvez utiliser `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // une ou plusieurs adresses IP
+$this->configurator->setDebugMode('23.75.345.200'); // une ou plusieurs adresses IP
 ```
 
 Nous recommandons vivement de combiner une adresse IP avec un cookie. Nous stockerons un jeton secret dans le cookie `nette-debug`, par exemple `secret1234`, et le mode de développement sera activé pour les programmeurs avec cette combinaison d'IP et de cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Nous pouvons également désactiver complètement le mode de développement, même pour localhost :
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Notez que la valeur `true` active le mode développeur par défaut, ce qui ne devrait jamais arriver sur un serveur de production.
@@ -90,7 +115,7 @@ Outil de débogage Tracy .[#toc-debugging-tool-tracy]
 Pour faciliter le débogage, nous allons activer l'excellent outil [Tracy |tracy:]. En mode développeur, il visualise les erreurs et en mode production, il enregistre les erreurs dans le répertoire spécifié :
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Fichiers temporaires .[#toc-temporary-files]
 Nette utilise le cache pour le conteneur DI, RobotLoader, les modèles, etc. Il est donc nécessaire de définir le chemin d'accès au répertoire où le cache sera stocké :
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Sous Linux ou macOS, définissez les [droits d'écriture |nette:troubleshooting#Setting directory permissions] pour les répertoires `log/` et `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 En général, nous voulons charger automatiquement les classes à l'aide de [RobotLoader |robot-loader:], nous devons donc le lancer et le laisser charger les classes du répertoire où se trouve `Bootstrap.php` (c'est-à-dire `__DIR__`) et de tous ses sous-répertoires :
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Fuseau horaire .[#toc-timezone]
 Le configurateur vous permet de spécifier un fuseau horaire pour votre application.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ En mode développement, le conteneur est automatiquement mis à jour chaque fois
 Les fichiers de configuration sont chargés à l'aide de `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 La méthode `addConfig()` peut être appelée plusieurs fois pour ajouter plusieurs fichiers.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Paramètres statiques .[#toc-static-parameters]
 Les paramètres utilisés dans les fichiers de configuration peuvent être définis [dans la section `parameters` |dependency-injection:configuration#parameters] et également transmis (ou écrasés) par la méthode `addStaticParameters()` (qui a un alias `addParameters()`). Il est important que les différentes valeurs des paramètres entraînent la génération de conteneurs DI supplémentaires, c'est-à-dire de classes supplémentaires.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Paramètres dynamiques .[#toc-dynamic-parameters]
 Nous pouvons également ajouter des paramètres dynamiques au conteneur, leurs différentes valeurs, contrairement aux paramètres statiques, ne provoqueront pas la génération de nouveaux conteneurs DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Les variables d'environnement peuvent être facilement mises à disposition à l'aide de paramètres dynamiques. Nous pouvons y accéder via `%env.variable%` dans les fichiers de configuration.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Vous pouvez utiliser les paramètres statiques suivants dans les fichiers de con
 - `%wwwDir%` est le chemin absolu vers le répertoire contenant le fichier d'entrée `index.php`
 - `%tempDir%` est le chemin absolu vers le répertoire des fichiers temporaires
 - `%vendorDir%` est le chemin absolu vers le répertoire où Composer installe les bibliothèques
+- `%rootDir%` est le chemin absolu vers le répertoire racine du projet
 - `%debugMode%` indique si l'application est en mode débogage
 - `%consoleMode%` indique si la demande provient de la ligne de commande
 
@@ -225,7 +252,7 @@ services:
 Créez une nouvelle instance et insérez-la dans bootstrap :
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Différents environnements .[#toc-different-environments]
 ========================================================
 
-N'hésitez pas à personnaliser la classe `Bootstrap` en fonction de vos besoins. Vous pouvez ajouter des paramètres à la méthode `boot()` pour différencier les projets Web, ou ajouter d'autres méthodes, comme `bootForTests()`, qui initialise l'environnement pour les tests unitaires, `bootForCli()` pour les scripts appelés depuis la ligne de commande, etc.
+N'hésitez pas à personnaliser la classe `Bootstrap` en fonction de vos besoins. Vous pouvez ajouter des paramètres à la méthode `bootWebApplication()` pour différencier les projets web. Vous pouvez également ajouter d'autres méthodes, telles que `bootTestEnvironment()` pour initialiser l'environnement des tests unitaires, `bootConsoleApplication()` pour les scripts appelés à partir de la ligne de commande, etc.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Initialisation du testeur Nette
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Initialisation du testeur de nappe
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/fr/components.texy b/application/fr/components.texy
index f2bee8ea59..a9472f1af9 100644
--- a/application/fr/components.texy
+++ b/application/fr/components.texy
@@ -230,6 +230,28 @@ Dans le modèle, ces messages sont disponibles dans la variable `$flashes` sous
 ```
 
 
+Redirection après un signal .[#toc-redirection-after-a-signal]
+==============================================================
+
+Le traitement d'un signal de composant est souvent suivi d'une redirection. Cette situation est similaire à celle des formulaires : après avoir soumis un formulaire, nous redirigeons également les données pour éviter qu'elles ne soient soumises à nouveau lorsque la page est rafraîchie dans le navigateur.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Étant donné qu'un composant est un élément réutilisable et qu'il ne doit généralement pas dépendre directement de présentateurs spécifiques, les méthodes `redirect()` et `link()` interprètent automatiquement le paramètre comme un signal de composant :
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Si vous devez rediriger vers un autre présentateur ou une autre action, vous pouvez le faire par l'intermédiaire du présentateur :
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Paramètres persistants .[#toc-persistent-parameters]
 ====================================================
 
@@ -347,7 +369,7 @@ services:
 Enfin, nous allons utiliser cette fabrique dans notre présentateur :
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Les composants en profondeur .[#toc-components-in-depth]
 Les composants d'une application Nette sont les parties réutilisables d'une application Web que nous intégrons dans les pages, ce qui est le sujet de ce chapitre. Quelles sont exactement les capacités d'un tel composant ?
 
 1) il peut être rendu dans un modèle
-2) Il sait quelle partie de lui-même doit être rendue lors d'une [requête AJAX |ajax#invalidation] (snippets).
+2) il sait [quelle partie de lui-même |ajax#snippets] rendre lors d'une requête AJAX (snippets)
 3) il a la capacité de stocker son état dans une URL (paramètres persistants)
 4) il a la capacité de répondre aux actions de l'utilisateur (signaux)
 5) il crée une structure hiérarchique (dont la racine est le présentateur).
diff --git a/application/fr/configuration.texy b/application/fr/configuration.texy
index b358ce1617..d180bce83a 100644
--- a/application/fr/configuration.texy
+++ b/application/fr/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# affiche le panneau "Nette Application" dans Tracy BlueScreen ?
 	debugger: ...           # (bool) par défaut à true
 
-	# le présentateur d'erreur sera-t-il appelé en cas d'erreur ?
-	catchExceptions: ...    # (bool) vaut true par défaut en mode production
+	# le présentateur d'erreurs sera-t-il appelé en cas d'erreur ?
+	# n'a d'effet qu'en mode développeur
+catchExceptions : ...    # (bool) valeur par défaut : true
 
 	# nom du présentateur d'erreur
-	errorPresenter: Error   # (string) vaut par défaut 'Nette:Error'.
+	errorPresenter: Error   # (string|array) vaut par défaut 'Nette:Error'.
+
+	# définit des alias pour les présentateurs et les événements
+	aliases: ...
 
 	# définit les règles pour résoudre le nom du présentateur vers une classe
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) valeur par défaut: false
 ```
 
-Comme les présentateurs d'erreurs ne sont pas appelés par défaut en mode développement et que les erreurs sont affichées par Tracy, le fait de changer la valeur `catchExceptions` en `true` permet de vérifier que les présentateurs d'erreurs fonctionnent correctement pendant le développement.
+Depuis la version 3.2 de `nette/application`, il est possible de définir une paire de présentateurs d'erreurs :
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # pour NetteApplicationBadRequestException
+		5xx: Error5xx   # pour les autres exceptions
+```
 
 L'option `silentLinks` détermine comment Nette se comporte en mode développeur lorsque la génération de liens échoue (par exemple, parce qu'il n'y a pas de présentateur, etc). La valeur par défaut `false` signifie que Nette déclenche `E_USER_WARNING`. Le réglage sur `true` supprime ce message d'erreur. Dans un environnement de production, `E_USER_WARNING` est toujours invoqué. Nous pouvons également influencer ce comportement en définissant la variable du présentateur [$invalidLinkMode |creating-links#Invalid Links].
 
+Les [alias simplifient le référencement des |creating-links#aliases] présentateurs fréquemment utilisés.
+
 Le [mappage définit les règles |modules#mapping] selon lesquelles le nom de la classe est dérivé du nom du présentateur.
 
 
@@ -77,10 +90,13 @@ latte:
 	strictTypes: ...     # (bool) vaut false par défaut
 
 	# active le [mode strict de l'analyseur |latte:develop#strict mode]
-	strictParsing : ...   # (bool) la valeur par défaut est false
+	strictParsing: ...   # (bool) la valeur par défaut est false
 
 	# permet de [vérifier le code généré |latte:develop#Checking Generated Code]
-	phpLinter : ...       # (string) la valeur par défaut est null
+	phpLinter: ...       # (string) la valeur par défaut est null
+
+	# définit la locale
+	locale: cs_CZ        # (string) la valeur par défaut est null
 
 	# classe de $this->template
 	templateClass: App\MyTemplateClass # Valeur par défaut: Nette\Bridges\ApplicationLatte\DefaultTemplate
@@ -91,7 +107,7 @@ Si vous utilisez la version 3 de Latte, vous pouvez ajouter une nouvelle [extens
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/fr/creating-links.texy b/application/fr/creating-links.texy
index c6786ac362..00c87674f1 100644
--- a/application/fr/creating-links.texy
+++ b/application/fr/creating-links.texy
@@ -38,7 +38,7 @@ Il est également possible de passer des paramètres nommés. Le lien suivant pa
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Si la méthode `ProductPresenter::renderShow()` n'a pas `$lang` dans sa signature, elle peut lire la valeur du paramètre en utilisant `$lang = $this->getParameter('lang')`.
+Si la méthode `ProductPresenter::renderShow()` n'a pas `$lang` dans sa signature, elle peut récupérer la valeur du paramètre à l'aide de `$lang = $this->getParameter('lang')` ou de la [propriété |presenters#Request Parameters].
 
 Si les paramètres sont stockés dans un tableau, ils peuvent être développés avec l'opérateur `...` (ou `(expand)` dans Latte 2.x) :
 
@@ -140,7 +140,7 @@ La cible `this` créera un lien vers la page actuelle :
 <a n:href="this">refresh</a>
 ```
 
-En même temps, tous les paramètres spécifiés dans la signature de l'instruction `render<View>()` ou `action<Action>()` sont transférés. Ainsi, si nous sommes sur les pages `Product:show` et `id:123`, le lien vers `this` transmettra également ce paramètre.
+En même temps, tous les paramètres spécifiés dans la signature de l'élément `action<Action>()` ou `render<View>()` si la méthode `action<Action>()` n'est pas défini, sont transférés. Ainsi, si nous nous trouvons sur les pages `Product:show` et `id:123`, le lien vers `this` transmettra également ce paramètre.
 
 Bien sûr, il est possible de spécifier les paramètres directement :
 
@@ -213,7 +213,7 @@ Comme les [composants |components] sont des unités distinctes réutilisables qu
 Si nous voulons créer un lien vers les présentateurs dans le modèle de composant, nous utilisons la balise `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 ou dans le code
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Alias .[#toc-aliases]{data-version:v3.2.2}
+==========================================
+
+Il est parfois utile d'attribuer un alias facilement mémorisable à une paire Présentateur:action. Par exemple, vous pouvez nommer la page d'accueil `Front:Home:default` simplement `home` ou `Admin:Dashboard:default` `admin` .
+
+Les alias sont définis dans la [configuration |configuration] sous la clé `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+Dans les liens, ils sont écrits en utilisant le symbole at, par exemple :
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Ils sont pris en charge dans toutes les méthodes qui fonctionnent avec des liens, telles que `redirect()` et similaires.
+
+
 Liens non valides .[#toc-invalid-links]
 =======================================
 
diff --git a/application/fr/how-it-works.texy b/application/fr/how-it-works.texy
index 09d020332a..57aeb786a4 100644
--- a/application/fr/how-it-works.texy
+++ b/application/fr/how-it-works.texy
@@ -22,18 +22,18 @@ La structure des répertoires ressemble à ceci :
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← répertoire avec application
-│   ├── <b>Presenters/</b>           ← classes d'presenter
-│   │   ├── <b>HomePresenter.php</b> ← Home classe des présentateurs
-│   │   └── <b>templates/</b>        ← répertoire des modèles
-│   │       ├── <b>@layout.latte</b> ← modèle de disposition partagée
-│   │       └── <b>Home/</b>         ← Modèles pour le présentateur de la page d'accueil
-│   │           └── <b>default.latte</b>  ← modèle pour l'action `default`
-│   ├── <b>Router/</b>               ← configuration des adresses URL
+│   ├── <b>Core/</b>                 ← basic necessary classes
+│   │   └── <b>RouterFactory.php</b> ← configuration des adresses URL
+│   ├── <b>UI/</b>                   ← presenters, templates & co.
+│   │   ├─── <b>@layout.latte</b>    ← template of shared layout
+│   │   └── <b>Home/</b>             ← Home presenter directory
+│   │       ├── <b>HomePresenter.php</b> ← Classe Home Presenter
+│   │       └── <b>default.latte</b> ← template for action default
 │   └── <b>Bootstrap.php</b>         ← classe de démarrage Bootstrap
 ├── <b>bin/</b>                      ← scripts pour la ligne de commande
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← journaux d'erreurs
 ├── <b>temp/</b>                     ← fichiers temporaires, cache, …
 ├── <b>vendor/</b>                   ← bibliothèques installées par Composer
@@ -91,7 +91,7 @@ Les applications écrites dans Nette sont divisées en plusieurs présentateurs
 
 L'application commence par demander à ce qu'on appelle le routeur de décider lequel des présentateurs doit transmettre la demande actuelle pour traitement. Le routeur décide de la responsabilité qui lui incombe. Il examine l'URL d'entrée `https://example.com/product/123`, qui veut `show` un produit avec `id: 123` comme action. C'est une bonne habitude d'écrire une paire présentateur + action séparée par un deux-points comme `Product:show`.
 
-Le routeur transforme donc l'URL en une paire `Presenter:action` + paramètres, dans notre cas `Product:show` + `id: 123`. Vous pouvez voir à quoi ressemble un routeur dans le fichier `app/Router/RouterFactory.php` et nous le décrirons en détail dans le chapitre [Routage |Routing].
+Le routeur transforme donc l'URL en une paire `Presenter:action` + paramètres, dans notre cas `Product:show` + `id: 123`. Vous pouvez voir à quoi ressemble un routeur dans le fichier `app/Core/RouterFactory.php` et nous le décrirons en détail dans le chapitre [Routage |Routing].
 
 Continuons. L'application connaît déjà le nom du présentateur et peut continuer. En créant un objet `ProductPresenter`, qui est le code du présentateur `Product`. Plus précisément, elle demande au conteneur DI de créer le présentateur, car la production d'objets est son travail.
 
@@ -121,12 +121,9 @@ Ainsi, la méthode `renderShow(123)` a été appelée, dont le code est un exemp
 
 Ensuite, le présentateur renvoie la réponse. Cela peut être une page HTML, une image, un document XML, l'envoi d'un fichier depuis le disque, JSON ou la redirection vers une autre page. Il est important de noter que si nous ne disons pas explicitement comment répondre (ce qui est le cas de `ProductPresenter`), la réponse sera de rendre le modèle avec une page HTML. Pourquoi ? Eh bien, parce que dans 99% des cas, nous voulons dessiner un modèle, donc le présentateur prend ce comportement par défaut et veut nous faciliter le travail. C'est le point de vue de Nette.
 
-Nous n'avons même pas besoin d'indiquer quel modèle dessiner, il dérive le chemin vers celui-ci selon une logique simple. Dans le cas du présentateur `Product` et de l'action `show`, il essaie de voir si l'un de ces fichiers modèles existe par rapport au répertoire où se trouve la classe `ProductPresenter`:
+Il n'est même pas nécessaire de spécifier le modèle à rendre ; le framework déduira lui-même le chemin d'accès. Dans le cas de l'action `show`, il essaie simplement de charger le modèle `show.latte` dans le répertoire contenant la classe `ProductPresenter`. Il tente également de trouver la mise en page dans le fichier `@layout.latte` (plus d'informations sur la [recherche de modèles |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Il essaiera également de trouver la mise en page dans le fichier `@layout.latte`, puis il effectuera le rendu du modèle. La tâche du présentateur et de l'ensemble de l'application est maintenant terminée. Si le modèle n'existe pas, une page d'erreur 404 sera renvoyée. Vous pouvez en savoir plus sur les présentateurs sur la page [Présentateurs |Presenters].
+Ensuite, les modèles sont rendus. La tâche du présentateur et de l'ensemble de l'application est ainsi achevée et le travail est terminé. Si le modèle n'existait pas, une page d'erreur 404 serait renvoyée. Pour en savoir plus sur les présentateurs, consultez la page [Présentateurs |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Juste pour être sûr, essayons de récapituler l'ensemble du processus avec une
 3) le routeur décode l'URL comme une paire `Home:default`
 4) un objet `HomePresenter` est créé
 5) la méthode `renderDefault()` est appelée (si elle existe)
-6) un modèle `templates/Home/default.latte` avec une mise en page `templates/@layout.latte` est rendu
+6) un modèle `default.latte` avec une mise en page `@layout.latte` est rendu
 
 
 Vous avez peut-être rencontré beaucoup de nouveaux concepts maintenant, mais nous pensons qu'ils ont un sens. Créer des applications dans Nette est un jeu d'enfant.
diff --git a/application/fr/modules.texy b/application/fr/modules.texy
index ade58f61b9..7734341840 100644
--- a/application/fr/modules.texy
+++ b/application/fr/modules.texy
@@ -2,29 +2,31 @@ Modules
 *******
 
 .[perex]
-Dans Nette, les modules représentent les unités logiques qui composent une application. Ils comprennent des présentateurs, des modèles, éventuellement aussi des composants et des classes de modèles.
+Les modules apportent de la clarté aux applications Nette en facilitant la division en unités logiques.
 
-Un répertoire pour les présentateurs et un autre pour les modèles ne seraient pas suffisants pour les projets réels. Avoir des dizaines de fichiers dans un seul dossier est pour le moins inorganisé. Comment s'en sortir ? Il suffit de les répartir en sous-répertoires sur le disque et en espaces de noms dans le code. Et c'est exactement ce que font les modules Nette.
-
-Oublions donc le dossier unique pour les présentateurs et les modèles et créons plutôt des modules, par exemple `Admin` et `Front`.
+À l'instar de l'organisation des fichiers en dossiers sur un disque dur, Nette permet de diviser les présentateurs, les modèles et les autres classes auxiliaires en modules. Comment cela fonctionne-t-il en pratique ? Simplement en incorporant de nouveaux sous-répertoires dans la structure. Voici un exemple de structure avec deux modules, Front et Admin :
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← répertoire avec les modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← ses présentateurs
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← ses présentateurs
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Cette structure de répertoire sera reflétée par les espaces de noms des classes, ainsi par exemple `DashboardPresenter` sera dans l'espace de noms `App\Modules\Admin\Presenters`:
+Cette structure de répertoires se reflète dans les espaces de noms des classes. Ainsi, par exemple, `DashboardPresenter` est situé dans l'espace de noms `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Le présentateur `Dashboard` dans le module `Admin` est référencé dans l'application en utilisant la notation deux points comme `Admin:Dashboard`, et son action `default` comme `Admin:Dashboard:default`.
-Et comment Nette proper sait-elle que `Admin:Dashboard` représente la classe `App\Modules\Admin\Presenters\DashboardPresenter`? Cela est déterminé par le [mappage |#mapping] dans la configuration.
-Ainsi, la structure donnée n'est pas figée et vous pouvez la modifier en fonction de vos besoins.
+Dans l'application, nous faisons référence au présentateur `Dashboard` dans le module `Admin` en utilisant la notation des deux points comme `Admin:Dashboard`. Pour son action `default`, nous l'appelons `Admin:Dashboard:default`.
+
+La structure présentée n'est pas rigide ; vous pouvez [l'adapter entièrement à vos besoins |#mapping] dans la configuration. .[tip]
 
-Les modules peuvent bien sûr contenir tous les éléments autres que les présentateurs et les modèles, tels que les composants, les classes de modèles, etc.
+Les modules peuvent inclure tous les autres fichiers, tels que les composants et les classes auxiliaires, en plus des présentateurs et des modèles. Si vous vous demandez où placer ces derniers, envisagez d'utiliser un dossier `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Modules imbriqués .[#toc-nested-modules]
 ----------------------------------------
 
-Les modules ne doivent pas uniquement former une structure plate, vous pouvez également créer des sous-modules, par exemple :
+Les modules peuvent avoir plusieurs niveaux d'imbrication, comme la structure d'un répertoire sur un disque :
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← répertoire avec les modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← sous-module Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← sous-module Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Ainsi, le module `Blog` est divisé en sous-modules `Admin` et `Front`. Là encore, cela se reflétera dans les espaces de noms, qui seront `App\Modules\Blog\Admin\Presenters` etc. Le présentateur `Dashboard` à l'intérieur du sous-module est désigné par `Blog:Admin:Dashboard`.
+Le module `Blog` est divisé en sous-modules `Admin` et `Front`. Cela se reflète également dans les espaces de noms, qui apparaissent alors comme `App\UI\Blog\Admin` et similaires. Pour désigner le présentateur `Dashboard` au sein du sous-module `Admin`, nous l'appelons `Blog:Admin:Dashboard`.
+
+L'imbrication peut être aussi poussée que nécessaire, ce qui permet de créer des sous-sous-modules.
 
-L'imbrication peut aller aussi loin que vous le souhaitez, de sorte que des sous-sous-modules peuvent être créés.
+Par exemple, si dans l'administration vous avez de nombreux présentateurs liés à la gestion des commandes, tels que `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., vous pouvez créer un module `Order` dans lequel les présentateurs tels que `Detail`, `Edit`, `Dispatch`, et d'autres seront organisés.
 
 
 Création de liens .[#toc-creating-links]
@@ -102,47 +118,66 @@ Voir le [chapitre sur le routage |routing#Modules].
 Cartographie .[#toc-mapping]
 ----------------------------
 
-Définit les règles par lesquelles le nom de la classe est dérivé du nom du présentateur. On les inscrit dans la [configuration] sous la clé `application › mapping`.
+Le mappage définit les règles permettant de dériver le nom de la classe à partir du nom du présentateur. Ces règles sont spécifiées dans la [configuration |configuration] sous la clé `application › mapping`.
 
-Commençons par un exemple qui n'utilise pas de modules. Nous voulons simplement que les classes du présentateur aient l'espace de nom `App\Presenters`. Cela signifie qu'un présentateur tel que `Home` doit correspondre à la classe `App\Presenters\HomePresenter`. Ceci peut être réalisé par la configuration suivante :
+Les structures de répertoire mentionnées plus haut sur cette page sont basées sur la correspondance suivante :
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Le nom du présentateur est remplacé par l'astérisque dans le masque de classe et le résultat est le nom de la classe. Facile !
+Comment fonctionne la cartographie ? Pour mieux comprendre, imaginons d'abord une application sans modules. Nous voulons que les classes de présentateurs relèvent de l'espace de noms `App\UI`, de sorte que le présentateur `Home` soit associé à la classe `App\UI\HomePresenter`. Cette configuration permet d'atteindre cet objectif :
 
-Si nous divisons les présentateurs en modules, nous pouvons avoir notre propre mappage pour chaque module :
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Ce mappage fonctionne en remplaçant l'astérisque du masque `App\UI\*Presenter` par le nom du présentateur `Home`, ce qui donne le nom de classe final `App\UI\HomePresenter`. C'est simple !
+
+Cependant, comme vous pouvez le voir dans les exemples de ce chapitre et d'autres chapitres, nous plaçons les classes de présentateurs dans des sous-répertoires éponymes, par exemple, le présentateur `Home` est associé à la classe `App\UI\Home\HomePresenter`. Pour ce faire, il suffit de doubler l'astérisque (Nette Application 3.2 requise) :
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Passons maintenant au mappage des présentateurs dans les modules. Nous pouvons définir des correspondances spécifiques pour chaque module :
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Maintenant, le présentateur `Front:Home` correspond à la classe `App\Modules\Front\Presenters\HomePresenter` et le présentateur `Admin:Dashboard` à la classe `App\Modules\Admin\Presenters\DashboardPresenter`.
+Selon cette configuration, le présentateur `Front:Home` correspond à la classe `App\UI\Front\Home\HomePresenter`, tandis que le présentateur `Api:OAuth` correspond à la classe `App\Api\OAuthPresenter`.
 
-Il est plus pratique de créer une règle générale (étoile) pour remplacer les deux premières. L'astérisque supplémentaire sera ajouté au masque de classe uniquement pour le module :
+Étant donné que les modules `Front` et `Admin` ont une approche de mappage similaire et qu'il est probable qu'il y ait d'autres modules de ce type, il est possible de créer une règle générale qui les remplace. Un nouvel astérisque pour le module est ajouté au masque de classe :
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Mais qu'en est-il si nous utilisons des modules imbriqués et que nous avons un présentateur `Admin:User:Edit`? Dans ce cas, le segment avec un astérisque représentant le module pour chaque niveau est simplement répété et le résultat est la classe `App\Modules\Admin\User\Presenters\EditPresenter`.
+Pour les modules imbriqués à plusieurs niveaux, tels que le présentateur `Admin:User:Edit`, le segment astérisque se répète pour chaque niveau, ce qui donne la classe `App\UI\Admin\User\Edit\EditPresenter`.
 
-Une notation alternative consiste à utiliser un tableau composé de trois segments au lieu d'une chaîne de caractères. Cette notation est équivalente à la précédente :
+Une autre notation consiste à utiliser un tableau composé de trois segments au lieu d'une chaîne. Cette notation est équivalente à la précédente :
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-La valeur par défaut est `*: *Module\*Presenter`.
+Si nous n'avons qu'une seule règle dans la configuration, la règle générale, nous pouvons l'écrire brièvement :
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/fr/presenters.texy b/application/fr/presenters.texy
index b6a772400e..538f20ab44 100644
--- a/application/fr/presenters.texy
+++ b/application/fr/presenters.texy
@@ -60,7 +60,7 @@ Similaire à la méthode `render<View>()`. Alors que `render<View>()` a pour but
 
 Il est important que `action<Action>()` soit appelé avant `render<View>()`afin qu'à l'intérieur de celui-ci, nous puissions éventuellement modifier le cours suivant du cycle de vie, c'est-à-dire changer le modèle qui sera rendu et également la méthode `render<View>()` qui sera appelée, en utilisant `setView('otherView')`.
 
-Les paramètres de la requête sont transmis à la méthode. Il est possible et recommandé de spécifier des types pour les paramètres, par exemple `actionShow(int $id, string $slug = null)` - si le paramètre `id` est manquant ou s'il ne s'agit pas d'un nombre entier, le présentateur renvoie l'[erreur 404 |#Error 404 etc.] et met fin à l'opération.
+Les paramètres de la requête sont transmis à la méthode. Il est possible et recommandé de spécifier des types pour les paramètres, par exemple `actionShow(int $id, ?string $slug = null)` - si le paramètre `id` est manquant ou s'il ne s'agit pas d'un nombre entier, le présentateur renvoie l'[erreur 404 |#Error 404 etc.] et met fin à l'opération.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ Dans le modèle, ces messages sont disponibles dans la variable `$flashes` en ta
 Erreur 404 etc. .[#toc-error-404-etc]
 =====================================
 
-Lorsque nous ne pouvons pas répondre à la demande, par exemple parce que l'article que nous voulons afficher n'existe pas dans la base de données, nous envoyons l'erreur 404 en utilisant la méthode `error(string $message = null, int $httpCode = 404)`, qui représente l'erreur HTTP 404 :
+Lorsque nous ne pouvons pas répondre à la demande, par exemple parce que l'article que nous voulons afficher n'existe pas dans la base de données, nous envoyons l'erreur 404 en utilisant la méthode `error(?string $message = null, int $httpCode = 404)`, qui représente l'erreur HTTP 404 :
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Paramètres de la demande .[#toc-request-parameters]
+===================================================
+
+Le présentateur, ainsi que chaque composant, obtient ses paramètres à partir de la demande HTTP. Leurs valeurs peuvent être récupérées à l'aide de la méthode `getParameter($name)` ou `getParameters()`. Les valeurs sont des chaînes ou des tableaux de chaînes, essentiellement des données brutes obtenues directement à partir de l'URL.
+
+Pour plus de commodité, nous recommandons de rendre les paramètres accessibles par le biais de propriétés. Il suffit de les annoter avec l'attribut `#[Parameter]` attribut :
+
+```php
+use Nette\Application\Attributes\Parameter;  // cette ligne est importante
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // doit être publique
+}
+```
+
+Pour les propriétés, nous suggérons de spécifier le type de données (par exemple, `string`). Nette va alors automatiquement calculer la valeur en fonction de ce type de données. Les valeurs des paramètres peuvent également être [validées |#Validation of Parameters].
+
+Lors de la création d'un lien, vous pouvez directement définir la valeur des paramètres :
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Paramètres persistants .[#toc-persistent-parameters]
 ====================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Si `$this->lang` a une valeur telle que `'en'`, les liens créés à l'aide de `link()` ou `n:href` contiendront également le paramètre `lang=en`. Et lorsque le lien sera cliqué, il s'agira à nouveau de `$this->lang = 'en'`.
 
-Pour les propriétés, nous vous recommandons d'indiquer le type de données (par exemple `string`) et vous pouvez également inclure une valeur par défaut. Les valeurs des paramètres peuvent être [validées |#Validation of Persistent Parameters].
+Pour les propriétés, nous vous recommandons d'indiquer le type de données (par exemple `string`) et vous pouvez également inclure une valeur par défaut. Les valeurs des paramètres peuvent être [validées |#Validation of Parameters].
 
 Les paramètres persistants sont transmis par défaut entre toutes les actions d'un présentateur donné. Pour les transmettre entre plusieurs présentateurs, vous devez les définir :
 
@@ -307,18 +333,12 @@ Pour aller plus loin .[#toc-going-deeper]
 Ce que nous avons montré jusqu'à présent dans ce chapitre suffira probablement. Les lignes suivantes sont destinées à ceux qui s'intéressent aux présentateurs en profondeur et veulent tout savoir.
 
 
-Exigences et paramètres .[#toc-requirement-and-parameters]
+Validation des paramètres .[#toc-validation-of-parameters]
 ----------------------------------------------------------
 
-La requête traitée par le présentateur est l'objet [api:Nette\Application\Request] et est renvoyée par la méthode du présentateur `getRequest()`. Elle comprend un tableau de paramètres et chacun d'entre eux appartient soit à l'un des composants, soit directement au présentateur (qui est également un composant, bien qu'il soit spécial). Nette redistribue donc les paramètres et les transmet entre les différents composants (et le présentateur) en appelant la méthode `loadState(array $params)`. Les paramètres peuvent être obtenus par la méthode `getParameters(): array`, individuellement en utilisant `getParameter($name)`. Les valeurs des paramètres sont des chaînes ou des tableaux de chaînes, il s'agit essentiellement de données brutes obtenues directement à partir d'une URL.
+Les valeurs des [paramètres de requête |#request parameters] et des [paramètres persistants |#persistent parameters] reçus des URL sont écrites dans les propriétés par la méthode `loadState()`. Elle vérifie également si le type de données spécifié dans la propriété correspond, sinon elle répondra par une erreur 404 et la page ne sera pas affichée.
 
-
-Validation des paramètres persistants .[#toc-validation-of-persistent-parameters]
----------------------------------------------------------------------------------
-
-Les valeurs des [paramètres persistants |#persistent parameters] reçus des URL sont écrites dans les propriétés par la méthode `loadState()`. Elle vérifie également si le type de données spécifié dans la propriété correspond, sinon elle répondra par une erreur 404 et la page ne sera pas affichée.
-
-Ne faites jamais aveuglément confiance aux paramètres persistants, car ils peuvent facilement être remplacés par l'utilisateur dans l'URL. Par exemple, voici comment nous vérifions si `$this->lang` fait partie des langues prises en charge. Une bonne façon de le faire est de surcharger la méthode `loadState()` mentionnée ci-dessus :
+Ne faites jamais aveuglément confiance aux paramètres, car ils peuvent facilement être remplacés par l'utilisateur dans l'URL. Par exemple, voici comment nous vérifions si `$this->lang` fait partie des langues prises en charge. Une bonne façon de le faire est de surcharger la méthode `loadState()` mentionnée ci-dessus :
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Sauvegarde et restauration de la demande .[#toc-save-and-restore-the-request]
 -----------------------------------------------------------------------------
 
-Vous pouvez enregistrer la demande en cours dans une session ou la restaurer à partir de la session et laisser le présentateur l'exécuter à nouveau. Ceci est utile, par exemple, lorsqu'un utilisateur remplit un formulaire et que sa connexion expire. Afin de ne pas perdre de données, avant de rediriger l'utilisateur vers la page de connexion, nous sauvegardons la demande actuelle dans la session à l'aide de `$reqId = $this->storeRequest()`, qui renvoie un identifiant sous la forme d'une chaîne courte et le transmet comme paramètre au présentateur de connexion.
+La demande traitée par le présentateur est un objet [api:Nette\Application\Request] et est renvoyée par la méthode du présentateur `getRequest()`.
+
+Vous pouvez enregistrer la requête en cours dans une session ou la restaurer à partir de la session et laisser le présentateur l'exécuter à nouveau. Ceci est utile, par exemple, lorsqu'un utilisateur remplit un formulaire et que son login expire. Afin de ne pas perdre de données, avant de rediriger l'utilisateur vers la page de connexion, nous sauvegardons la demande en cours dans la session à l'aide de la méthode `$reqId = $this->storeRequest()`, qui renvoie un identifiant sous la forme d'une chaîne courte et le transmet en tant que paramètre au présentateur de connexion.
 
 Après l'ouverture de session, nous appelons la méthode `$this->restoreRequest($reqId)`, qui récupère la demande de la session et la lui transmet. La méthode vérifie que la requête a été créée par le même utilisateur que celui qui est maintenant connecté. Si un autre utilisateur se connecte ou si la clé n'est pas valide, elle ne fait rien et le programme continue.
 
@@ -362,7 +384,7 @@ La redirection ne se produit pas avec une demande AJAX ou POST, car elle entraî
 Vous pouvez également invoquer la canonisation manuellement à l'aide de la méthode `canonicalize()`, qui, comme la méthode `link()`, reçoit le présentateur, les actions et les paramètres comme arguments. Elle crée un lien et le compare à l'URL actuelle. Si elle est différente, elle redirige vers le lien généré.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// redirige si $slug est différent de $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Restriction d'accès à l'aide de `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+-----------------------------------------------------------------------------------------------------------
+
+L'attribut `#[Requires]` fournit des options avancées pour restreindre l'accès aux présentateurs et à leurs méthodes. Il peut être utilisé pour spécifier des méthodes HTTP, exiger des requêtes AJAX, limiter l'accès à la même origine et restreindre l'accès à la transmission uniquement. L'attribut peut être appliqué aux classes de présentateurs ainsi qu'aux méthodes individuelles telles que `action<Action>()`, `render<View>()`, `handle<Signal>()`, et `createComponent<Name>()`.
+
+Vous pouvez spécifier ces restrictions :
+- sur les méthodes HTTP : `#[Requires(methods: ['GET', 'POST'])]`
+- nécessitant une requête AJAX : `#[Requires(ajax: true)]`
+- accès uniquement à partir de la même origine : `#[Requires(sameOrigin: true)]`
+- accès uniquement par le biais d'une redirection : `#[Requires(forward: true)]`
+- restrictions sur des actions spécifiques : `#[Requires(actions: 'default')]`
+
+Pour plus de détails, voir [Comment utiliser l'attribut Requires |best-practices:attribute-requires].
+
+
+Vérification de la méthode HTTP .[#toc-http-method-check]
+---------------------------------------------------------
+
+Dans Nette, les présentateurs vérifient automatiquement la méthode HTTP de chaque requête entrante, principalement pour des raisons de sécurité. Par défaut, les méthodes `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` sont autorisées.
+
+Si vous souhaitez activer d'autres méthodes telles que `OPTIONS`, vous pouvez utiliser l'attribut `#[Requires]` (à partir de Nette Application v3.2) :
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Dans la version 3.1, la vérification est effectuée dans `checkHttpMethod()`, qui vérifie si la méthode spécifiée dans la requête est incluse dans le tableau `$presenter->allowedMethods`. Ajouter une méthode comme celle-ci :
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Il est essentiel de souligner que si vous autorisez la méthode `OPTIONS`, vous devez également la gérer correctement dans votre présentateur. Cette méthode est souvent utilisée comme une requête dite "preflight", que les navigateurs envoient automatiquement avant la requête réelle lorsqu'il est nécessaire de déterminer si la requête est autorisée du point de vue de la politique CORS (Cross-Origin Resource Sharing). Si vous autorisez cette méthode mais ne mettez pas en œuvre une réponse appropriée, cela peut entraîner des incohérences et des problèmes de sécurité potentiels.
+
+
 Autres lectures .[#toc-further-reading]
 =======================================
 
diff --git a/application/fr/routing.texy b/application/fr/routing.texy
index 9fe5d5e4a6..29541d7fb9 100644
--- a/application/fr/routing.texy
+++ b/application/fr/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Notation avancée .[#toc-advanced-notation]
 ------------------------------------------
 
-Le deuxième paramètre de la route, que nous écrivons souvent sous le format `Presenter:action`, est une abréviation, que nous pouvons également écrire sous la forme d'un champ, où nous indiquons directement les valeurs (par défaut) des différents paramètres :
+La cible d'un itinéraire, généralement écrite sous la forme `Presenter:action`, peut également être exprimée à l'aide d'un tableau qui définit les paramètres individuels et leurs valeurs par défaut :
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Ou nous pouvons utiliser cette forme, remarquez la réécriture de l'expression régulière de validation :
+Pour une spécification plus détaillée, une forme encore plus étendue peut être utilisée, où en plus des valeurs par défaut, d'autres propriétés de paramètres peuvent être définies, telles qu'une expression régulière de validation (voir le paramètre `id` ) :
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Ces formats plus bavards sont utiles pour ajouter d'autres métadonnées.
+Il est important de noter que si les paramètres définis dans le tableau ne sont pas inclus dans le masque de chemin, leurs valeurs ne peuvent pas être modifiées, même en utilisant des paramètres de requête spécifiés après un point d'interrogation dans l'URL.
 
 
 Filtres et traductions .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Intégration .[#toc-integration]
 ===============================
 
-Afin de connecter notre routeur à l'application, nous devons en informer le conteneur DI. Le moyen le plus simple est de préparer la fabrique qui construira l'objet routeur et de dire à la configuration du conteneur de l'utiliser. Disons que nous écrivons une méthode dans ce but `App\Router\RouterFactory::createRouter()`:
+Afin de connecter notre routeur à l'application, nous devons en informer le conteneur DI. Le moyen le plus simple est de préparer la fabrique qui construira l'objet routeur et de dire à la configuration du conteneur de l'utiliser. Disons que nous écrivons une méthode dans ce but `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Puis nous écrivons dans la [configuration |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Toutes les dépendances, telles qu'une connexion à une base de données, etc., sont transmises à la méthode factory en tant que paramètres en utilisant le [câblage automatique |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Par utilisation séparée, nous entendons l'utilisation des capacités du routeu
 Donc encore une fois nous allons créer une méthode qui va construire un routeur, par exemple :
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Ou bien nous créerons directement des objets :
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/fr/templates.texy b/application/fr/templates.texy
index 8ecd733495..494ea2da09 100644
--- a/application/fr/templates.texy
+++ b/application/fr/templates.texy
@@ -34,35 +34,81 @@ Et ceci pourrait être le modèle d'action :
 Il définit le bloc `content`, qui est inséré à la place de `{include content}` dans la mise en page, et redéfinit également le bloc `title`, qui écrase `{block title}` dans la mise en page. Essayez d'imaginer le résultat.
 
 
-Recherche de modèles .[#toc-search-for-templates]
--------------------------------------------------
+Recherche de modèles .[#toc-template-lookup]
+--------------------------------------------
 
-Le chemin vers les modèles est déduit selon une logique simple. Il essaie de voir si l'un de ces fichiers modèles existe par rapport au répertoire où se trouve la classe du présentateur, où `<Presenter>` est le nom du présentateur actuel et `<view>` est le nom de l'action en cours :
+Dans les présentateurs, vous n'avez pas besoin de spécifier quel modèle doit être rendu ; le cadre détermine automatiquement le chemin, ce qui facilite le codage.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Si vous utilisez une structure de répertoires dans laquelle chaque présentateur a son propre répertoire, placez simplement le modèle dans ce répertoire sous le nom de l'action (c'est-à-dire de la vue). Par exemple, pour l'action `default`, utilisez le modèle `default.latte`:
 
-Si le modèle n'est pas trouvé, il essaiera de chercher dans le répertoire `templates` au niveau supérieur, c'est-à-dire au même niveau que le répertoire contenant la classe du présentateur.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Si le modèle n'y est pas trouvé non plus, la réponse est une [erreur 404 |presenters#Error 404 etc.].
+Si vous utilisez une structure dans laquelle les présentateurs sont regroupés dans un répertoire et les modèles dans un dossier `templates`, enregistrez-les dans un fichier `<Presenter>.<view>.latte` soit dans un fichier `<Presenter>/<view>.latte`:
 
-Vous pouvez également changer la vue en utilisant `$this->setView('otherView')`. Ou, au lieu de chercher, spécifiez directement le nom du fichier de modèle en utilisant `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+Le répertoire `templates` peut également être placé un niveau plus haut, au même niveau que le répertoire des classes de présentateurs.
+
+Si le modèle n'est pas trouvé, le présentateur répond par l'[erreur 404 - page non trouvée |presenters#Error 404 etc].
+
+Vous pouvez changer la vue en utilisant `$this->setView('anotherView')`. Il est également possible de spécifier directement le fichier de modèle avec `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Vous pouvez modifier les chemins dans lesquels les modèles sont recherchés en remplaçant la méthode [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], qui renvoie un tableau de chemins de fichiers possibles.
+Les fichiers dans lesquels les modèles sont recherchés peuvent être modifiés en remplaçant la méthode [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], qui renvoie un tableau de noms de fichiers possibles.
+
+
+Recherche de modèles de mise en page .[#toc-layout-template-lookup]
+-------------------------------------------------------------------
+
+Nette recherche également automatiquement le fichier de mise en page.
+
+Si vous utilisez une structure de répertoires dans laquelle chaque présentateur a son propre répertoire, placez le modèle soit dans le dossier du présentateur, s'il lui est propre, soit à un niveau supérieur s'il est commun à plusieurs présentateurs :
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Si vous utilisez une structure dans laquelle les présentateurs sont regroupés dans un répertoire et les modèles dans un dossier `templates`, la mise en page sera attendue aux endroits suivants :
 
-Le modèle est attendu dans les fichiers suivants :
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` mise en page commune à plusieurs présentateurs
+Si le présentateur se trouve dans un [module |modules], il cherchera également plus haut dans l'arborescence du répertoire en fonction de l'imbrication du module.
 
-`<Presenter>` est le nom du présentateur actuel et `<layout>` est le nom de la mise en page, qui est par défaut `'layout'`. Le nom peut être modifié avec `$this->setLayout('otherLayout')`, de sorte que les fichiers `@otherLayout.latte` seront essayés.
+Le nom de la présentation peut être modifié à l'aide de `$this->setLayout('layoutAdmin')` et sera alors attendu dans le fichier `@layoutAdmin.latte`. Vous pouvez également spécifier directement le fichier de modèle de présentation en utilisant `$this->setLayout('/path/to/template.latte')`.
 
-Vous pouvez également spécifier directement le nom du fichier du modèle de présentation en utilisant `$this->setLayout('/path/to/template.latte')`. L'utilisation de `$this->setLayout(false)` désactivera la recherche de la mise en page.
+L'utilisation de `$this->setLayout(false)` ou de la balise `{layout none}` à l'intérieur du modèle désactive la recherche de modèle.
 
 .[note]
-Vous pouvez modifier les chemins dans lesquels les modèles sont recherchés en remplaçant la méthode [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], qui renvoie un tableau de chemins de fichiers possibles.
+Les fichiers dans lesquels les modèles de présentation sont recherchés peuvent être modifiés en remplaçant la méthode [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], qui renvoie un tableau de noms de fichiers possibles.
 
 
 Variables dans le modèle .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ L'annotation `@property-read` est pour les IDE et l'analyse statique, elle fera
 Vous pouvez aussi vous offrir le luxe de chuchoter dans les templates, il suffit d'installer le plugin Latte dans PhpStorm et de spécifier le nom de la classe au début du template, voir l'article "Latte : how to type system":https://blog.nette.org/fr/latte-comment-utiliser-le-systeme-de-type:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte version 3 propose un moyen plus avancé en créant une [extension |latte:creating-extension] pour chaque projet web. Voici un exemple approximatif d'une telle classe :
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ Nous l'enregistrons en utilisant la [configuration |configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternativement, le traducteur peut être défini à l'aide de la [configuration
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Le traducteur peut alors être utilisé, par exemple, comme un filtre `|translate`, avec des paramètres supplémentaires transmis à la méthode `translate()` (voir `foo, bar`) :
diff --git a/application/hu/@home.texy b/application/hu/@home.texy
index 49f809ce72..f49e983b61 100644
--- a/application/hu/@home.texy
+++ b/application/hu/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | verzió | kompatibilis a PHP-vel
 |-----------|-------------------
-| Nette alkalmazás 4.0 | PHP 8.0 - 8.2
-| Nette alkalmazás 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette alkalmazás 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/hu/ajax.texy b/application/hu/ajax.texy
index fb0a6e08b8..b2a6f90cc9 100644
--- a/application/hu/ajax.texy
+++ b/application/hu/ajax.texy
@@ -3,10 +3,10 @@ AJAX & Snippetek
 
 <div class=perex>
 
-A modern webes alkalmazások manapság félig a szerveren, félig a böngészőben futnak. Az AJAX létfontosságú egyesítő tényező. Milyen támogatást nyújt a Nette Framework?
-- sablonrészletek küldése (ún. *snippetek*)
-- változók átadása PHP és JavaScript között
-- AJAX-alkalmazások hibakeresése
+A modern webes alkalmazások korában, ahol a funkciók gyakran a szerver és a böngésző között helyezkednek el, az AJAX elengedhetetlen összekötő elem. Milyen lehetőségeket kínál a Nette Framework ezen a területen?
+- A sablon részeinek, az ún. snippeteknek a küldése.
+- változók átadása a PHP és a JavaScript között
+- AJAX-kérések hibakeresésére szolgáló eszközök
 
 </div>
 
@@ -14,29 +14,32 @@ A modern webes alkalmazások manapság félig a szerveren, félig a böngészőb
 AJAX kérés .[#toc-ajax-request]
 ===============================
 
-Az AJAX-kérés nem különbözik a klasszikus kéréstől - a bemutatót egy adott nézettel és paraméterekkel hívják meg. Az is a prezenteren múlik, hogyan válaszol rá: használhat saját rutint, amely egy HTML kódrészletet (HTML snippet), egy XML-dokumentumot, egy JSON-objektumot vagy JavaScript-kódot ad vissza.
+Az AJAX-kérés alapvetően nem különbözik a klasszikus HTTP-kéréstől. Egy bemutatót hívunk meg bizonyos paraméterekkel. A bemutatótól függ, hogyan válaszol a kérésre - adhat vissza adatokat JSON formátumban, küldhet egy HTML kódrészt, egy XML-dokumentumot stb.
 
-Kiszolgálói oldalon az AJAX-kérés a [HTTP-kérést kapszulázó |http:request] szolgáltatási módszerrel detektálható `$httpRequest->isAjax()` (a HTTP fejléc alapján detektál `X-Requested-With`). A prezenteren belül a `$this->isAjax()` metódus formájában egy rövidítés áll rendelkezésre.
+A böngésző oldalán AJAX-kérést kezdeményezünk a `fetch()` funkcióval:
 
-Létezik egy `payload` nevű előfeldolgozott objektum, amely arra szolgál, hogy az adatokat JSON-ban küldje el a böngészőnek.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// a válasz feldolgozása
+});
 ```
 
-A JSON kimenet teljes ellenőrzéséhez használja a `sendJson` metódust a prezenterben. Ez azonnal befejezi a prezentert, és sablon nélkül is boldogulsz:
+A szerveroldalon az AJAX-kérést a [HTTP-kérést kapszulázó |http:request] szolgáltatás `$httpRequest->isAjax()` módszere ismeri fel. Ez a `X-Requested-With` HTTP fejlécet használja, ezért elengedhetetlen a küldése. A prezenteren belül a `$this->isAjax()` metódust használhatja.
+
+Ha JSON formátumban szeretne adatokat küldeni, használja a [`sendJson()` |presenters#Sending a response] módszert. A metódus a prezenter tevékenységét is befejezi.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Ha HTML-t szeretnénk küldeni, akkor vagy beállíthatunk egy speciális sablont az AJAX-kérésekhez:
+Ha azt tervezi, hogy egy speciális, AJAX-hoz tervezett sablonnal válaszol, akkor azt a következőképpen teheti meg:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Snippets .[#toc-snippets]
+=========================
+
+A Nette által kínált leghatékonyabb eszköz a szerver és az ügyfél összekapcsolására a snippetek. Segítségükkel egy közönséges alkalmazásból minimális erőfeszítéssel és néhány sornyi kóddal AJAX-alkalmazássá alakítható. A Fifteen példája bemutatja, hogyan működik mindez, és a kódja megtalálható a [GitHubon |https://github.com/nette-examples/fifteen].
+
+A snippetek, vagyis a kivágások lehetővé teszik, hogy az oldalnak csak egyes részeit frissítsük, ahelyett, hogy az egész oldalt újratöltenénk. Ez gyorsabb és hatékonyabb, és kényelmesebb felhasználói élményt is nyújt. A snippetek a Ruby on Rails Hotwire vagy a Symfony UX Turbo programjára emlékeztethetnek. Érdekes módon a Nette 14 évvel korábban vezette be a snippeteket.
+
+Hogyan működnek a snippetek? Az oldal első betöltésekor (egy nem-AJAX kérés) a teljes oldal betöltődik, beleértve az összes snippetet is. Amikor a felhasználó interakcióba lép az oldallal (pl. rákattint egy gombra, elküld egy űrlapot stb.), a teljes oldal betöltése helyett AJAX-kérés történik. A prezenterben lévő kód végzi el a műveletet, és dönti el, hogy mely snippetek igényelnek frissítést. A Nette rendereli ezeket a részleteket, és egy JSON tömb formájában elküldi őket. A böngészőben lévő kezelő kód ezután visszahelyezi a kapott részleteket az oldalba. Ezért csak a módosított snippetek kódja kerül átvitelre, ami a teljes oldaltartalom átviteléhez képest sávszélességet takarít meg és gyorsítja a betöltést.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-A [Naja könyvtár |https://naja.js.org] az AJAX kérések kezelésére szolgál a böngésző oldalán. [Telepítsd |https://naja.js.org/#/guide/01-install-setup-naja] node.js csomagként (Webpack, Rollup, Vite, Parcel és más csomagokkal való használathoz):
+A snippetek böngészőoldali kezeléséhez a [Naja könyvtárat |https://naja.js.org] használjuk. [Telepítse |https://naja.js.org/#/guide/01-install-setup-naja] node.js csomagként (olyan alkalmazásokkal használható, mint a Webpack, Rollup, Vite, Parcel és mások):
 
 ```shell
 npm install naja
 ```
 
-...vagy illessze be közvetlenül az oldal sablonjába:
+... vagy illessze be közvetlenül az oldal sablonjába:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Ahhoz, hogy AJAX-kérést hozzon létre egy hagyományos linkből (jel) vagy űrlapküldésből, egyszerűen jelölje meg az adott linket, űrlapot vagy gombot a `ajax` osztállyal:
+Először [inicializálni |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] kell a könyvtárat:
+
+```js
+naja.initialize();
+```
+
+Ahhoz, hogy egy közönséges linket (jelet) vagy űrlapküldést AJAX-kérelemmé tegyen, egyszerűen jelölje meg az adott linket, űrlapot vagy gombot a `ajax` osztállyal:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Ahhoz, hogy AJAX-kérést hozzon létre egy hagyományos linkből (jel) vagy űr
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippets .[#toc-snippets]
-=========================
-
-A beépített AJAX-támogatásnak van egy sokkal hatékonyabb eszköze - a snippetek. Használatuk lehetővé teszi, hogy egy hagyományos alkalmazásból AJAX-alkalmazássá váljon mindössze néhány sornyi kóddal. Hogy mindez hogyan működik, azt a Fifteen példa mutatja be, amelynek kódja a buildben vagy a [GitHubon |https://github.com/nette-examples/fifteen] is elérhető.
-
-A snippetek úgy működnek, hogy a kezdeti (azaz nem AJAX) kérés során a teljes oldal átkerül, majd minden AJAX [alkérésnél |components#signal] (ugyanazon bemutató azonos nézetének kérése) csak a módosított részek kódja kerül át a már említett `payload` tárolóba.
+Snippetek újrarajzolása .[#toc-redrawing-snippets]
+--------------------------------------------------
 
-A Snippetek a Ruby on Rails Hotwire vagy a Symfony UX Turbo-ra emlékeztethetnek, de Nette tizennégy évvel korábban találta ki őket.
-
-
-A Snippetek érvénytelenítése .[#toc-invalidation-of-snippets]
-=============================================================
-
-A [Control |components] osztály minden leszármazottja (ami egy Presenter is) képes megjegyezni, hogy egy kérés során történt-e olyan változás, ami miatt újra kell rendeznie. Van egy pár módszer ennek kezelésére: `redrawControl()` és `isControlInvalid()`. Egy példa:
+A [Control |components] osztály minden objektuma (beleértve magát a Presentert is) nyilvántartást vezet arról, hogy történtek-e olyan változások, amelyek miatt újra kell rajzolni. Erre a célra a `redrawControl()` metódus szolgál.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Az objektumot újra kell renderelni, miután a felhasználó bejelentkezett.
+	// a bejelentkezés után újra kell rajzolni a vonatkozó részt
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-A Nette azonban még finomabb felbontást kínál, mint az egész komponensek. A felsorolt módszerek opcionális paraméterként elfogadják egy úgynevezett "snippet" nevét. A "snippet" alapvetően a sablonod egy eleme, amelyet erre a célra egy Latte makróval jelöltél meg, erről később. Így lehetőség van arra, hogy egy komponenst arra kérjünk, hogy csak a sablonjának *részeit* rajzolja újra. Ha a teljes komponens érvénytelenítésre kerül, akkor az összes snippetje újrarendezésre kerül. Egy komponens akkor is "érvénytelen", ha bármelyik alkomponense érvénytelen.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // érvényteleníti a 'header' nevű snippet-t.
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, legalább egy snippet érvénytelen.
+A Nette lehetővé teszi annak finomabb ellenőrzését is, hogy mit kell átrajzolni. A fent említett módszer argumentumként elfogadhatja a snippet nevét. Így lehetséges a sablonrész szintjén érvényteleníteni (azaz: újrarajzolást kikényszeríteni). Ha a teljes komponens érvénytelenítése megtörténik, akkor annak minden egyes részlete is újrarajzolásra kerül:
 
-$this->redrawControl(); // érvényteleníti az egész komponenst, minden egyes snippet-tel együtt.
-$this->isControlInvalid('footer'); // -> true
+```php
+// érvényteleníti a "fejléc"-részletet.
+$this->redrawControl('header');
 ```
 
-A jelzést kapó komponens automatikusan újrarajzolásra kerül.
-
-A snippet-újrarajzolásnak köszönhetően pontosan tudjuk, hogy mely elemek mely részeit kell újrarajzolni.
-
-
-Tag `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
 
-Az oldal megjelenítése nagyon hasonlóan zajlik, mint egy normál kérésnél: ugyanazok a sablonok töltődnek be stb. A lényeges rész azonban az, hogy a kimenetre nem szánt részek kimaradnak; a többi részhez egy azonosítót kell társítani, és egy JavaScript kezelő számára érthető formátumban kell elküldeni a felhasználónak.
+Szemelvények a Latte-ban .[#toc-snippets-in-latte]
+--------------------------------------------------
 
-
-Szintaxis .[#toc-syntax]
-------------------------
-
-Ha a sablonban van egy vezérlőelem vagy egy snippet, akkor azt a `{snippet} ... {/snippet}` páros taggel kell becsomagolnunk - ez biztosítja, hogy a renderelt snippet "kivágásra" kerüljön, és elküldjük a böngészőnek. Ez is egy segítőbe fogja beburkolni. `<div>` tagbe (lehet másikat is használni). A következő példában egy `header` nevű snippet van definiálva. Ez akár egy komponens sablonját is jelentheti:
+A snippetek használata a Latte-ban rendkívül egyszerű. Ha a sablon egy részét snippetként szeretné definiálni, egyszerűen csomagolja be a `{snippet}` és `{/snippet}` címkékbe:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Ha a sablonban van egy vezérlőelem vagy egy snippet, akkor azt a `{snippet} ..
 {/snippet}
 ```
 
-A snippet egy más típusú snippet, mint a `<div>` vagy egy további HTML-attribútumokkal ellátott snippet az attribútumváltozat használatával érhető el:
+A snippet létrehoz egy elemet `<div>` a HTML-oldalon egy speciálisan generált `id` címmel. A snippet újrarajzolásakor ennek az elemnek a tartalma frissül. Ezért az oldal kezdeti megjelenítésekor az összes snippetet is meg kell jeleníteni, még akkor is, ha azok kezdetben üresek lehetnek.
+
+A snippet létrehozható egy másik elemmel is, mint a `<div>` n:attribútummal:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ A snippet egy más típusú snippet, mint a `<div>` vagy egy további HTML-attri
 ```
 
 
-Dynamic Snippets .[#toc-dynamic-snippets]
-=========================================
+Snippet területek .[#toc-snippet-areas]
+---------------------------------------
 
-A Nette-ben egy futásidejű paraméter alapján dinamikus névvel ellátott snippeteket is definiálhat. Ez leginkább olyan különböző listákhoz alkalmas, ahol csak egy sort kell megváltoztatnunk, de nem akarjuk vele együtt az egész listát is átvinni. Egy példa erre a következő lenne:
+A snippet nevek kifejezések is lehetnek:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Van egy statikus snippet, a `itemsContainer`, amely több dinamikus snippet tartalmaz: `item-0`, `item-1` és így tovább.
+ `item-0`, `item-1`, stb. Ha közvetlenül érvénytelenítenénk egy dinamikus snippetet (pl. `item-1`), akkor semmi sem rajzolódna újra. A snippetek ugyanis valódi részletként működnek, és csak maguk a snippetek kerülnek közvetlenül megjelenítésre. A sablonban azonban technikailag nincs `item-1` nevű snippet. Ez csak a snippet környező kódjának, jelen esetben a foreach ciklusnak a végrehajtásakor jelenik meg. Ezért a sablon azon részét, amelyet végre kell hajtani, a `{snippetArea}` címkével jelöljük:
 
-Egy dinamikus snippet közvetlenül nem rajzolható újra (a `item-1` újrarajzolásának nincs hatása), a szülő snippetjét (ebben a példában `itemsContainer`) kell újrarajzolni. Ennek hatására a szülő snippet kódja végrehajtódik, de ezután csak az alszippetjei kerülnek elküldésre a böngészőnek. Ha csak az egyik alrészletet szeretné átküldeni, akkor a szülő részlet bemenetét úgy kell módosítania, hogy a többi alrészletet ne generálja.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-A fenti példában gondoskodnia kell arról, hogy egy AJAX-kérés esetén csak egy elem kerüljön a `$list` tömbhöz, ezért a `foreach` ciklus csak egy dinamikus snippetet fog kiírni.
+És újrarajzoljuk mind az egyes snippetet, mind a teljes átfogó területet:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Lényeges annak biztosítása is, hogy a `$items` tömb csak azokat az elemeket tartalmazza, amelyeket újra kell rajzolni.
 
-Snippetek egy belefoglalt sablonban .[#toc-snippets-in-an-included-template]
-============================================================================
-
-Előfordulhat, hogy a snippet egy olyan sablonban van, amely egy másik sablonból van beépítve. Ebben az esetben a második sablonban a `snippetArea` makróval be kell csomagolnunk a beillesztési kódot, majd újra kell rajzolnunk mind a snippetArea-t, mind a tényleges snippetet.
-
-A `snippetArea` makró biztosítja, hogy a benne lévő kód végrehajtásra kerül, de csak a tényleges snippet kerül a böngészőhöz a bevont sablonban.
+Ha a `{include}` tag segítségével egy másik sablont illesztünk be a fő sablonba, amely szeleteket tartalmaz, akkor a bevont sablont ismét be kell csomagolni a `snippetArea` címkébe, és a szeletet és a területet együttesen érvényteleníteni kell:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Dinamikus snippetekkel is kombinálható.
-
-
-Hozzáadás és törlés .[#toc-adding-and-deleting]
-===============================================
 
-Ha új elemet adsz hozzá a listához, és érvényteleníted a `itemsContainer` címet, az AJAX-kérés az új elemet is tartalmazó részleteket küldi vissza, de a javascript kezelő nem tudja megjeleníteni azt. Ennek oka, hogy nincs olyan HTML-elem, amely az újonnan létrehozott azonosítóval rendelkezik.
+Snippetek az összetevőkben .[#toc-snippets-in-components]
+---------------------------------------------------------
 
-Ebben az esetben a legegyszerűbb megoldás, ha az egész listát még egy snippetbe csomagoljuk, és az egészet érvénytelenítjük:
+ [Komponenseken |components] belül is létrehozhat snippeteket, amelyeket a Nette automatikusan átrajzol. Van azonban egy sajátos korlátozás: a snippetek újrarajzolásához paraméterek nélkül hívja meg a `render()` metódust. Így a paraméterek átadása a sablonban nem fog működni:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Felhasználói adatok küldése .[#toc-sending-user-data]
+-----------------------------------------------------
+
+A snippetek mellett bármilyen további adatot is küldhet az ügyfélnek. Egyszerűen írja őket a `payload` objektumba:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Ugyanez vonatkozik egy elem törlésére is. Lehetséges lenne üres snippet küldése, de általában a listák lehetnek oldalszámozottak, és bonyolult lenne megvalósítani egy elem törlését és egy másik betöltését (amely korábban a oldalszámozott lista egy másik oldalán volt).
-
 
-Paraméterek küldése a komponensnek .[#toc-sending-parameters-to-component]
-==========================================================================
+Küldési paraméterek .[#toc-sending-parameters]
+==============================================
 
 Amikor AJAX-kérésen keresztül paramétereket küldünk a komponensnek, legyenek azok jelparaméterek vagy állandó paraméterek, meg kell adnunk a globális nevüket, amely tartalmazza a komponens nevét is. A paraméter teljes nevét a `getParameterId()` metódus adja vissza.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-És kezelje a módszert s megfelelő paraméterekkel a komponensben.
+A komponensben lévő megfelelő paraméterekkel rendelkező handle metódust:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/hu/bootstrap.texy b/application/hu/bootstrap.texy
index 5d0a614439..a05ab01083 100644
--- a/application/hu/bootstrap.texy
+++ b/application/hu/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// A konfigurátor felelős az alkalmazási környezet és a szolgáltatások beállításáért.
+		$this->configurator = new Configurator;
+		// A Nette által generált ideiglenes fájlok (pl. lefordított sablonok) könyvtárának beállítása.
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// A Nette intelligens, és a fejlesztői üzemmód automatikusan bekapcsol,
+		// vagy engedélyezheti egy adott IP-címre a következő sor megjegyzésének feloldásával:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Bekapcsolja a Tracy-t: a végső "svájci bicska" hibakeresési eszköz.
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: automatikusan feltölti az összes osztályt a megadott könyvtárban.
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Konfigurációs fájlok betöltése
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-A webes alkalmazások esetében a kezdő fájl a `index.php`, amely a `www/` nyilvános könyvtárban található. Ez lehetővé teszi a `Bootstrap` osztály számára, hogy inicializálja a környezetet, és visszaadja a `$configurator`, amely létrehozza a DI konténert. Ezután megszerzi a `Application` szolgáltatást, amely a webalkalmazást futtatja:
+A webes alkalmazások kezdőfájlja a `index.php`, amely a `www/` nyilvános könyvtárban található. A `Bootstrap` osztályt használja a környezet inicializálásához és a DI konténer létrehozásához. Ezután megszerzi a `Application` szolgáltatást a konténerből, amely elindítja a webalkalmazást:
 
 ```php
-// a környezet inicializálása + konfigurátor objektum kinyerése
-$configurator = App\Bootstrap::boot();
-// DI konténer létrehozása
-$container = $configurator->createContainer();
+$bootstrap = new App\Bootstrap;
+// A környezet inicializálása + DI konténer létrehozása
+$container = $bootstrap->bootWebApplication();
 // A DI konténer létrehoz egy Nette\Application\Application objektumot.
 $application = $container->getByType(Nette\Application\Application::class);
-// Nette alkalmazás indítása
+// A Nette-alkalmazás elindítása és a bejövő kérések kezelése.
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ A mód kiválasztása automatikus felismeréssel történik, így általában ne
 Ha más esetekben, például egy adott IP-címről hozzáférő programozók számára szeretné engedélyezni a fejlesztési üzemmódot, akkor a `setDebugMode()` címet használhatja:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // egy vagy több IP-cím
+$this->configurator->setDebugMode('23.75.345.200'); // egy vagy több IP-cím
 ```
 
 Mindenképpen javasoljuk az IP-cím és a cookie kombinálását. A `nette-debug` cookie-ban tárolunk egy titkos tokent, pl. `secret1234`, és a fejlesztési mód az IP és a cookie ilyen kombinációjával rendelkező programozók számára aktiválódik.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 A fejlesztői módot teljesen ki is kapcsolhatjuk, akár a localhost esetében is:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 A `true` érték keményen bekapcsolja a fejlesztői módot, ami soha nem történhet meg egy termelő szerveren.
@@ -90,7 +115,7 @@ Hibakereső eszköz Tracy .[#toc-debugging-tool-tracy]
 Az egyszerű hibakeresés érdekében bekapcsoljuk a [Tracy |tracy:] nevű nagyszerű eszközt. Fejlesztői módban megjeleníti a hibákat, termelési módban pedig a megadott könyvtárba naplózza a hibákat:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Ideiglenes fájlok .[#toc-temporary-files]
 A Nette a DI konténer, a RobotLoader, a sablonok stb. számára használja a gyorsítótárat. Ezért szükséges annak a könyvtárnak az elérési útvonalát beállítani, ahol a gyorsítótár tárolásra kerül:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Linuxon vagy macOS-en állítsa be a `log/` és a `temp/` könyvtárak [írási engedélyeit |nette:troubleshooting#Setting directory permissions].
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Általában a [RobotLoader |robot-loader:] segítségével szeretnénk automatikusan betölteni az osztályokat, ezért el kell indítanunk, és hagynunk kell, hogy betöltse az osztályokat abból a könyvtárból, ahol a `Bootstrap.php` található (azaz `__DIR__`) és annak összes alkönyvtárából:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Időzóna .[#toc-timezone]
 A Configurator lehetővé teszi, hogy megadjon egy időzónát az alkalmazásához.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ Fejlesztői üzemmódban a konténer automatikusan frissül minden alkalommal, a
 A konfigurációs fájlok betöltése a `addConfig()` segítségével történik:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 A `addConfig()` metódus többször is meghívható több fájl hozzáadásához.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Statikus paraméterek .[#toc-static-parameters]
 A konfigurációs fájlokban használt paramétereket a [`parameters` szakaszban |dependency-injection:configuration#parameters] lehet definiálni, és a `addStaticParameters()` metódus (amelynek alias neve `addParameters()`) is átadhatja (vagy felülírhatja). Fontos, hogy a különböző paraméterértékek további DI-konténerek, azaz további osztályok generálását okozzák.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Dinamikus paraméterek .[#toc-dynamic-parameters]
 A konténerhez dinamikus paramétereket is hozzáadhatunk, ezek eltérő értékei a statikus paraméterekkel ellentétben nem okoznak új DI-konténerek generálását.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 A környezeti változókat könnyen elérhetővé tehetnénk dinamikus paraméterek segítségével. A konfigurációs fájlokban a `%env.variable%` címen keresztül érhetjük el őket.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ A konfigurációs fájlokban a következő statikus paramétereket használhatja
 - `%wwwDir%` a `index.php` beviteli fájlt tartalmazó könyvtár abszolút elérési útja.
 - `%tempDir%` az ideiglenes fájlok könyvtárának abszolút elérési útja.
 - `%vendorDir%` az abszolút elérési út a könyvtárak Composer általi telepítésének könyvtárához.
+- `%rootDir%` a projekt gyökérkönyvtárának abszolút elérési útvonala.
 - `%debugMode%` jelzi, hogy az alkalmazás hibakeresési módban van-e.
 - `%consoleMode%` jelzi, hogy a kérés a parancssoron keresztül érkezett-e.
 
@@ -225,7 +252,7 @@ services:
 Hozzunk létre egy új példányt, és illesszük be a bootstrapbe:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Különböző környezetek .[#toc-different-environments]
 ====================================================
 
-Nyugodtan testre szabhatja a `Bootstrap` osztályt, hogy megfeleljen az igényeinek. A `boot()` metódushoz paramétereket adhat a webes projektek megkülönböztetéséhez, vagy más metódusokat is hozzáadhat, például a `bootForTests()`, amely inicializálja a környezetet a unit tesztekhez, a `bootForCli()` a parancssorból hívott szkriptekhez, és így tovább.
+Ne habozzon, ha a `Bootstrap` osztályt saját igényei szerint alakíthatja. A `bootWebApplication()` metódushoz paramétereket adhat hozzá a webes projektek megkülönböztetése érdekében. Alternatívaként más metódusokat is hozzáadhat, például a `bootTestEnvironment()` a környezet inicializálásához a unit tesztekhez, a `bootConsoleApplication()` a parancssorból hívott szkriptekhez stb.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
 {
-	$configurator = self::boot();
 	Tester\Environment::setup(); // Nette Tester inicializálása
-	return $configurator;
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
+{
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/hu/components.texy b/application/hu/components.texy
index 410cca3a9e..0e10d16126 100644
--- a/application/hu/components.texy
+++ b/application/hu/components.texy
@@ -230,6 +230,28 @@ A sablonban ezek az üzenetek a `$flashes` változóban állnak rendelkezésre,
 ```
 
 
+Átirányítás jelzést követően .[#toc-redirection-after-a-signal]
+===============================================================
+
+Egy komponensjel feldolgozása után gyakran következik az átirányítás. Ez a helyzet hasonló az űrlapokhoz - egy űrlap elküldése után mi is átirányítunk, hogy megakadályozzuk az adatok újbóli elküldését, amikor az oldal frissül a böngészőben.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Mivel a komponens egy újrafelhasználható elem, és általában nem szabad, hogy közvetlen függőségben álljon az egyes prezenterektől, a `redirect()` és a `link()` metódusok automatikusan komponensjelként értelmezik a paramétert:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Ha át kell irányítani egy másik prezenterre vagy műveletre, akkor ezt a prezenteren keresztül teheti meg:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Állandó paraméterek .[#toc-persistent-parameters]
 =================================================
 
@@ -347,7 +369,7 @@ services:
 Végül ezt a gyárat fogjuk használni a prezenterünkben:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ A komponensek mélysége .[#toc-components-in-depth]
 A komponensek egy Nette alkalmazásban a webalkalmazás újrafelhasználható részei, amelyeket oldalakba ágyazunk be, ez a fejezet témája. Pontosan milyen képességekkel rendelkezik egy ilyen komponens?
 
 1) egy sablonban megjeleníthető.
-2) tudja, hogy egy [AJAX-kérés |ajax#invalidation] során melyik részét kell renderelni (snippet)
+2) tudja, hogy egy AJAX-kérés során [melyik |ajax#snippets] részét kell megjelenítenie (snippetek).
 3) képes az állapotát egy URL-ben tárolni (állandó paraméterek).
 4) képes reagálni a felhasználói műveletekre (jelek)
 5) hierarchikus struktúrát hoz létre (ahol a gyökér a bemutató)
diff --git a/application/hu/configuration.texy b/application/hu/configuration.texy
index fc96b2a039..8c07c79a3a 100644
--- a/application/hu/configuration.texy
+++ b/application/hu/configuration.texy
@@ -14,10 +14,14 @@ application:
 	debugger: ...           # (bool) alapértelmezett értéke true
 
 	# error-presenter meghívásra kerül hiba esetén?
-	catchExceptions: ...    # (bool) alapértelmezés szerint true termelési üzemmódban.
+	# csak fejlesztői módban van hatása
+	catchExceptions: ...    # (bool) alapértelmezés szerint true
 
 	# error-presenter neve
-	errorPresenter: Error   # (string) alapértelmezett értéke 'Nette:Error'.
+	errorPresenter: Error   # (string|array) alapértelmezett értéke 'Nette:Error'.
+
+	# aliasokat definiál az előadókhoz és eseményekhez
+	aliases: ...
 
 	# meghatározza a prezenter nevének egy osztályra való feloldására vonatkozó szabályokat.
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) alapértelmezett értéke false
 ```
 
-Mivel a hiba-bemutatókat alapértelmezés szerint nem hívja meg a program fejlesztési módban, és a hibákat a Tracy jeleníti meg, a `catchExceptions` érték `true` -re történő módosítása segít ellenőrizni, hogy a hiba-bemutatók helyesen működnek-e a fejlesztés során.
+A `nette/application` 3.2-es verziójától kezdve lehetőség van hiba-bemutatók párjának definiálására:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # Nette\Application\BadRequestException esetében
+		5xx: Error5xx   # egyéb kivételek esetén
+```
 
 A `silentLinks` opció határozza meg, hogy a Nette hogyan viselkedjen fejlesztői módban, ha a linkgenerálás sikertelen (például mert nincs prezenter stb.). Az alapértelmezett `false` érték azt jelenti, hogy a Nette a `E_USER_WARNING` opciót váltja ki. A `true` beállítása elnyomja ezt a hibaüzenetet. Gyártási környezetben a `E_USER_WARNING` mindig meghívásra kerül. Ezt a viselkedést a [$invalidLinkMode |creating-links#Invalid Links] prezenter változó beállításával is befolyásolhatjuk.
 
+Az [álnevek leegyszerűsítik a |creating-links#aliases] gyakran használt [előadókra való hivatkozást |creating-links#aliases].
+
 A [leképezés meghatározza azokat a szabályokat |modules#mapping], amelyek alapján az osztály neve a prezenter nevéből származik.
 
 
@@ -82,6 +95,9 @@ latte:
 	# engedélyezi a [generált kód ellenőrzését |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) alapértelmezett a null
 
+	# beállítja a nyelvjárást
+	locale: cs_CZ        # (string) alapértelmezett érték nulla
+
 	# $this->template osztálya
 	templateClass:       # alapértelmezett értéke Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Ha a Latte 3. verzióját használja, akkor új [bővítményt |latte:creating-e
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/hu/creating-links.texy b/application/hu/creating-links.texy
index 8f7c11af58..97cc830cf5 100644
--- a/application/hu/creating-links.texy
+++ b/application/hu/creating-links.texy
@@ -38,7 +38,7 @@ Lehetőség van nevesített paraméterek átadására is. A következő hivatkoz
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Ha a `ProductPresenter::renderShow()` metódus szignatúrájában nem szerepel a `$lang`, akkor a paraméter értékét a `$lang = $this->getParameter('lang')` segítségével tudja beolvasni.
+Ha a `ProductPresenter::renderShow()` metódus aláírásában nem szerepel a `$lang`, akkor a paraméter értékét a `$lang = $this->getParameter('lang')` segítségével vagy a [tulajdonságból |presenters#Request Parameters] tudja lekérdezni.
 
 Ha a paraméterek egy tömbben vannak tárolva, akkor a `...` operátorral (vagy a Latte 2.x-ben a `(expand)` operátorral) bővíthetők:
 
@@ -140,7 +140,7 @@ A cél `this` létrehoz egy linket az aktuális oldalra:
 <a n:href="this">refresh</a>
 ```
 
-Ugyanakkor az összes, az aláírásában megadott paramétert a `render<View>()` vagy `action<Action>()` metódusban megadott paraméterek átadásra kerülnek. Tehát ha a `Product:show` és a `id:123` oldalakon vagyunk, akkor a `this` link is átadja ezt a paramétert.
+Ugyanakkor az összes paraméter, amelyet a `action<Action>()` vagy a `render<View>()` metódusban megadott paraméterek, ha a `action<Action>()` nincs definiálva, átadásra kerül. Tehát ha a `Product:show` és a `id:123` oldalakon vagyunk, akkor a `this` linkje is átadja ezt a paramétert.
 
 Természetesen lehetőség van a paraméterek közvetlen megadására is:
 
@@ -213,7 +213,7 @@ Mivel a [komponensek |components] különálló, újrafelhasználható egységek
 Ha a komponenssablonban előadókra akarunk hivatkozni, akkor a `{plink}` címkét használjuk:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 vagy a kódban
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Álnevek .[#toc-aliases]{data-version:v3.2.2}
+============================================
+
+Néha hasznos, ha egy könnyen megjegyezhető álnevet rendelünk egy Presenter:action pároshoz. Például a `Front:Home:default` honlapot egyszerűen elnevezheti `home` -nek, vagy a `Admin:Dashboard:default` -t `admin`-nak.
+
+Az aliasok a [konfigurációban |configuration] a `application › aliases` kulcs alatt kerülnek meghatározásra:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+A hivatkozásokban az at szimbólummal íródnak, például:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+A linkekkel dolgozó összes módszer támogatja őket, például a `redirect()` és hasonlók.
+
+
 Érvénytelen hivatkozások .[#toc-invalid-links]
 ==============================================
 
diff --git a/application/hu/how-it-works.texy b/application/hu/how-it-works.texy
index f7503c9ef1..24d0e0cba1 100644
--- a/application/hu/how-it-works.texy
+++ b/application/hu/how-it-works.texy
@@ -22,18 +22,18 @@ A könyvtárszerkezet valahogy így néz ki:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← alapvető szükséges osztályok
+│   │ └── <b>RouterFactory.php</b>   ← URL címek konfigurálása
+│   ├── <b>UI/</b>                   ← prezenterek, sablonok és társai.
+│   │   ├── <b>@layout.latte</b>     ← a megosztott elrendezés sablonja
+│   │   └── <b>Home/</b>             ← Főoldal bemutatókönyvtár
+│   │       ├── <b>HomePresenter.php</b> ← Home prezenter osztály
+│   │       └── <b>default.latte</b> ← cselekvési sablon default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ A Nette-ben írt alkalmazások sok úgynevezett prezenterre oszlanak (más keret
 
 Az alkalmazás azzal indul, hogy az ún. routertől kéri, hogy döntse el, hogy az aktuális kérést melyik prezenternek adja át feldolgozásra. A router dönti el, hogy kinek a felelőssége. Megnézi a bemeneti URL-t `https://example.com/product/123`, aki a `show` egy terméket `id: 123` művelettel akarja ellátni. Jó szokás a prezenter + akció párokat kettősponttal elválasztva `Product:show`-ként írni.
 
-Tehát a router az URL-t átalakította `Presenter:action` + paraméterek párrá, esetünkben `Product:show` + `id: 123`. A `app/Router/RouterFactory.php` fájlban láthatjuk, hogyan néz ki egy útválasztó, és ezt részletesen az [Útválasztás |Routing] fejezetben fogjuk leírni.
+Tehát a router az URL-t átalakította `Presenter:action` + paraméterek párrá, esetünkben `Product:show` + `id: 123`. A `app/Core/RouterFactory.php` fájlban láthatjuk, hogyan néz ki egy útválasztó, és ezt részletesen az [Útválasztás |Routing] fejezetben fogjuk leírni.
 
 Lépjünk tovább. Az alkalmazás már ismeri a bemutató nevét, és folytathatja. Egy `ProductPresenter` objektum létrehozásával, amely a `Product` bemutató kódja. Pontosabban megkéri a DI konténert a prezenter létrehozására, mert az objektumok előállítása az ő feladata.
 
@@ -121,12 +121,9 @@ Tehát a `renderShow(123)` metódust hívtuk meg, amelynek kódja fiktív példa
 
 Ezt követően a prezenter visszaadja a választ. Ez lehet egy HTML oldal, egy kép, egy XML dokumentum, egy fájl elküldése a lemezről, JSON vagy egy másik oldalra való átirányítás. Fontos, hogy ha nem mondjuk meg kifejezetten, hogyan kell válaszolni (ami a `ProductPresenter` esetében a helyzet), akkor a válasz az lesz, hogy a sablon egy HTML-oldallal jeleníti meg a sablont. Hogy miért? Nos, mert az esetek 99%-ában egy sablont szeretnénk kirajzolni, így a prezentáló ezt a viselkedést veszi alapértelmezettnek, és a mi munkánkat akarja megkönnyíteni. Ez a Nette lényege.
 
-Még csak meg sem kell adnunk, hogy melyik sablont rajzoljuk ki, egyszerű logika szerint levezeti az oda vezető utat. A presenter `Product` és az action `show` esetében megnézi, hogy létezik-e valamelyik sablonfájl a `ProductPresenter` osztály könyvtárához képest, ahol a osztály található:
+Még azt sem kell megadnunk, hogy melyik sablont kell megjelenítenünk; a keretrendszer magától levonja az útvonalat. A `show` akció esetében egyszerűen megpróbálja betölteni a `show.latte` sablont a `ProductPresenter` osztályt tartalmazó könyvtárban. Megpróbálja megtalálni az elrendezést is a `@layout.latte` fájlban (a [sablonkeresésről |templates#Template Lookup] bővebben).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Megpróbálja megtalálni az elrendezést is a `@layout.latte` fájlban, majd rendereli a sablont. Ezzel a prezenter és az egész alkalmazás feladata befejeződött. Ha a sablon nem létezik, akkor egy 404-es hibaüzenetű oldal fog visszakerülni. A prezenterekről bővebben a [Prezenterek |Presenters] oldalon olvashat.
+Ezt követően a sablonok megjelenítésre kerülnek. Ezzel a bemutató és az egész alkalmazás feladata befejeződik, és a munka elvégeztetett. Ha a sablon nem létezne, akkor egy 404-es hibaoldalt kapna vissza. A prezenterekről bővebben a [Prezenterek |presenters] oldalon olvashat.
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ A biztonság kedvéért próbáljuk meg az egész folyamatot egy kicsit más URL
 3) a router dekódolja az URL-t, mint egy párat `Home:default`
 4) létrejön egy `HomePresenter` objektum
 5) a `renderDefault()` metódust meghívjuk (ha létezik)
-6) egy `templates/Home/default.latte` sablon `templates/@layout.latte` elrendezéssel megjelenik.
+6) egy `default.latte` sablon `@layout.latte` elrendezéssel megjelenik.
 
 
 Lehet, hogy most sok új fogalommal találkoztál, de úgy gondoljuk, hogy van értelme. Az alkalmazások létrehozása a Nette-ben gyerekjáték.
diff --git a/application/hu/modules.texy b/application/hu/modules.texy
index 5dde2d1a36..a44b6ec874 100644
--- a/application/hu/modules.texy
+++ b/application/hu/modules.texy
@@ -2,29 +2,31 @@ Modulok
 *******
 
 .[perex]
-A Nette-ben a modulok az alkalmazást alkotó logikai egységeket jelentik. Ide tartoznak a prezenterek, sablonok, esetleg komponensek és modellosztályok.
+A modulok a Nette-alkalmazások áttekinthetőségét segítik elő azáltal, hogy megkönnyítik a logikai egységekre való egyszerű felosztást.
 
-Egy könyvtár a bemutatóknak és egy a sablonoknak nem lenne elég a valódi projektekhez. Több tucat fájl egy mappában való elhelyezése legalábbis rendezetlen. Hogyan szabadulhatunk meg ettől? Egyszerűen felosztjuk őket alkönyvtárakra a lemezen és névterekre a kódban. És pontosan ezt teszik a Nette modulok.
-
-Felejtsük el tehát az egyetlen mappát az előadóknak és a sablonoknak, és helyette hozzunk létre modulokat, például a `Admin` és a `Front`.
+Hasonlóan a fájlok mappákba rendezéséhez a merevlemezen, a Nette-ben modulokba oszthatjuk a prezentereket, sablonokat és más segédosztályokat. Hogyan működik ez a gyakorlatban? Egyszerűen úgy, hogy új alkönyvtárakat építünk be a struktúrába. Íme egy példa egy struktúrára két modullal, a Front és az Admin modulokkal:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Ezt a könyvtárszerkezetet az osztályok névterei is tükrözni fogják, így például a `DashboardPresenter` a `App\Modules\Admin\Presenters` névtérben lesz:
+Ez a könyvtárszerkezet tükröződik az osztályok névterében, így például a `DashboardPresenter` a `App\UI\Admin\Dashboard` névtérben található:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-A `Dashboard` prezenterre a `Admin` modulon belül az alkalmazáson belül a kettőspont jelöléssel `Admin:Dashboard`, a `default` műveletre pedig `Admin:Dashboard:default` néven hivatkozunk.
-És honnan tudja a Nette proper, hogy a `Admin:Dashboard` a `App\Modules\Admin\Presenters\DashboardPresenter` osztályt képviseli? Ezt a konfigurációban történő [leképezéssel |#mapping] határozzuk meg.
-A megadott struktúra tehát nem keményen meghatározott, és Ön az igényeinek megfelelően módosíthatja.
+Az alkalmazásban a `Dashboard` bemutatóra a `Admin` modulon belül a `Admin:Dashboard` kettőspont jelöléssel hivatkozunk a . A `default` műveletére `Admin:Dashboard:default` néven hivatkozunk.
+
+A bemutatott struktúra nem merev; a konfigurációban [teljes mértékben az igényeihez igazíthatja |#mapping]. .[tip]
 
-A modulok természetesen a prezentereken és sablonokon kívül minden más elemet is tartalmazhatnak, például komponenseket, modellosztályokat stb.
+A modulok a prezentereken és sablonokon kívül minden más fájlt, például komponenseket és segédosztályokat is tartalmazhatnak. Ha mérlegeli, hogy hol helyezze el ezeket, fontolja meg a `Accessory` mappa használatát:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Beágyazott modulok .[#toc-nested-modules]
 -----------------------------------------
 
-A moduloknak nem kell csak sima struktúrát alkotniuk, létrehozhatunk például almodulokat is:
+A modulok több szinten is egymásba ágyazhatók, hasonlóan a lemezen lévő könyvtárstruktúrához:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Így a `Blog` modul `Admin` és `Front` almodulokra oszlik. Ez ismét tükröződik a névterekben, amelyek a `App\Modules\Blog\Admin\Presenters` stb. lesznek. Az almodulon belüli `Dashboard` bemutatót `Blog:Admin:Dashboard` néven említjük.
+A `Blog` modul `Admin` és `Front` almodulokra oszlik. Ez tükröződik a névterekben is, amelyek aztán `App\UI\Blog\Admin` és hasonló módon jelennek meg. A `Dashboard` bemutatóra a `Admin` almodulon belül `Blog:Admin:Dashboard` néven hivatkozunk.
+
+A beágyazás olyan mély lehet, amilyen mélyre csak szükséges, lehetővé téve al-almodulok létrehozását.
 
-A beágyazás tetszőlegesen mélyre mehet, így al-almodulok hozhatók létre.
+Például, ha az adminisztrációban sok, a rendeléskezeléshez kapcsolódó prezenter van, mint például `OrderDetail`, `OrderEdit`, `OrderDispatch`, stb., létrehozhat egy `Order` modult, amelyben a `Detail`, `Edit`, `Dispatch`, stb. típusú prezentereket szervezi.
 
 
 Linkek létrehozása .[#toc-creating-links]
@@ -99,50 +115,69 @@ Hogy megtudjuk, hogy egy adott modulban vagy annak almoduljában vagyunk-e, hasz
 Lásd [az útválasztásról szóló fejezetet |routing#Modules].
 
 
-Feltérképezés .[#toc-mapping]
------------------------------
+A  feltérképezése .[#toc-mapping]
+---------------------------------
 
-Meghatározza azokat a szabályokat, amelyek alapján az osztály neve az előadó nevéből származik. Ezeket a [konfigurációban |configuration] a `application › mapping` kulcs alatt írjuk le.
+A leképezés határozza meg az osztálynévnek a bemutató nevéből való származtatásának szabályait. Ezek a szabályok a [konfigurációban |configuration] a `application › mapping` kulcs alatt vannak megadva.
 
-Kezdjük egy olyan példával, amely nem használ modulokat. Csak azt akarjuk, hogy a prezenter osztályok a `App\Presenters` névtérrel rendelkezzenek. Ez azt jelenti, hogy egy olyan prezenternek, mint a `Home`, a `App\Presenters\HomePresenter` osztályhoz kell kapcsolódnia. Ezt a következő konfigurációval érhetjük el:
+Az ezen az oldalon korábban említett könyvtárszerkezetek a következő leképezésen alapulnak:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Az osztálymaszkban a prezenter nevét csillaggal helyettesítjük, és az eredmény az osztály neve lesz. Easy!
+Hogyan működik a térképezés? A jobb megértés érdekében először képzeljünk el egy modulok nélküli alkalmazást. Szeretnénk, ha a prezenter osztályok a `App\UI` névtérbe tartoznának, így a `Home` prezenter a `App\UI\HomePresenter` osztályhoz tartozik. Ezt a következő konfigurációval érhetjük el:
 
-Ha az előadókat modulokra osztjuk, akkor minden modulhoz saját leképezésünk lehet:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Ez a leképezés úgy működik, hogy a `App\UI\*Presenter` maszkban a csillagot a `Home` prezenter névvel helyettesítjük, így kapjuk a `App\UI\HomePresenter` végső osztálynevet. Egyszerű!
+
+Azonban, ahogyan azt az ebben és más fejezetekben található példákban láthatjuk, a prezenter osztályokat névadó alkönyvtárakba helyezzük, például a `Home` prezenter a `App\UI\Home\HomePresenter` osztályra van leképezve. Ezt a csillag megduplázásával érjük el (Nette Application 3.2 szükséges):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Most pedig térjünk rá az előadók modulokba való leképezésére. Minden egyes modulhoz sajátos hozzárendeléseket határozhatunk meg:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Most a `Front:Home` bemutatót a `App\Modules\Front\Presenters\HomePresenter` osztályra, a `Admin:Dashboard` bemutatót pedig a `App\Modules\Admin\Presenters\DashboardPresenter` osztályra képezzük le.
+E konfiguráció szerint a `Front:Home` bemutató a `App\UI\Front\Home\HomePresenter` osztályhoz, míg a `Api:OAuth` bemutató a `App\Api\OAuthPresenter` osztályhoz tartozik.
 
-Praktikusabb egy általános (csillag) szabályt létrehozni az első kettő helyett. Az extra csillagot csak a modul számára adjuk hozzá az osztálymaszkhoz:
+Mivel a `Front` és a `Admin` modulok hasonló leképezési megközelítéssel rendelkeznek, és valószínűleg több ilyen modul is létezik, létrehozható egy általános szabály, amely ezeket helyettesíti. Az osztálymaszkhoz egy új csillagot adunk a modulhoz:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-De mi van akkor, ha egymásba ágyazott modulokat használunk, és van egy bemutató `Admin:User:Edit`? Ebben az esetben a modult jelképező csillaggal ellátott szegmens minden szinten egyszerűen megismétlődik, és az eredmény a `App\Modules\Admin\User\Presenters\EditPresenter` osztály lesz.
+A többszintű, egymásba ágyazott modulok esetében, mint például a `Admin:User:Edit` bemutató, a csillagszegmens minden szinten megismétlődik, így a `App\UI\Admin\User\Edit\EditPresenter` osztály lesz az eredmény.
 
-Egy alternatív jelölés az, hogy a karakterlánc helyett egy három szegmensből álló tömböt használunk. Ez a jelölés egyenértékű az előzővel:
+Egy alternatív jelölés a karakterlánc helyett egy három szegmensből álló tömb használata. Ez a jelölés egyenértékű az előzővel:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Az alapértelmezett érték a `*: *Module\*Presenter`.
+Ha csak egy szabály van a konfigurációban, az általános szabály, akkor röviden leírhatjuk:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/hu/presenters.texy b/application/hu/presenters.texy
index 3dadaaf424..076c632a4c 100644
--- a/application/hu/presenters.texy
+++ b/application/hu/presenters.texy
@@ -60,7 +60,7 @@ Hasonlóan a módszerhez `render<View>()`. Míg a `render<View>()` célja, hogy
 
 Fontos, hogy `action<Action>()` előbb hívódik meg, mint a `render<View>()`, így ezen belül esetleg megváltoztathatjuk az életciklus következő menetét, azaz megváltoztathatjuk a megjelenítendő sablont és a metódust is. `render<View>()` ami meghívásra kerül, a `setView('otherView')` segítségével.
 
-A kérésből származó paramétereket átadjuk a metódusnak. Lehetséges és ajánlott a paraméterek típusainak megadása, pl. `actionShow(int $id, string $slug = null)` - ha a `id` paraméter hiányzik, vagy nem egész szám, a prezenter [404-es hibát |#Error 404 etc.] ad vissza, és megszakítja a műveletet.
+A kérésből származó paramétereket átadjuk a metódusnak. Lehetséges és ajánlott a paraméterek típusainak megadása, pl. `actionShow(int $id, ?string $slug = null)` - ha a `id` paraméter hiányzik, vagy nem egész szám, a prezenter [404-es hibát |#Error 404 etc.] ad vissza, és megszakítja a műveletet.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ A sablonban ezek az üzenetek a `$flashes` változóban `stdClass` objektumként
 404-es hiba stb. .[#toc-error-404-etc]
 ======================================
 
-Ha nem tudjuk teljesíteni a kérést, mert például a megjeleníteni kívánt cikk nem létezik az adatbázisban, akkor a 404-es hibát dobjuk ki a `error(string $message = null, int $httpCode = 404)` módszerrel, amely a 404-es HTTP hibát jelenti:
+Ha nem tudjuk teljesíteni a kérést, mert például a megjeleníteni kívánt cikk nem létezik az adatbázisban, akkor a 404-es hibát dobjuk ki a `error(?string $message = null, int $httpCode = 404)` módszerrel, amely a 404-es HTTP hibát jelenti:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Kérési paraméterek .[#toc-request-parameters]
+=============================================
+
+A bemutató, valamint minden komponens a HTTP-kérésből kapja a paramétereit. Értékeik a `getParameter($name)` módszerrel vagy a `getParameters()` segítségével kérhetők le. Az értékek karakterláncok vagy karakterláncok tömbjei, lényegében közvetlenül az URL-ből nyert nyers adatok.
+
+A további kényelem érdekében javasoljuk, hogy a paraméterek tulajdonságokon keresztül legyenek elérhetők. Egyszerűen jegyzeteljük őket a `#[Parameter]` attribútummal:
+
+```php
+use Nette\Application\Attributes\Parameter;  // ez a sor fontos
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // nyilvánosnak kell lennie
+}
+```
+
+A tulajdonságok esetében javasoljuk, hogy adja meg az adattípust (pl. `string`). A Nette ezután automatikusan ennek alapján alakítja ki az értéket. A paraméterek értékei is [érvényesíthetők |#Validation of Parameters].
+
+A hivatkozás létrehozásakor közvetlenül megadhatja a paraméterek értékét:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Tartós paraméterek .[#toc-persistent-parameters]
 ================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Ha a `$this->lang` értéke például `'en'`, akkor a `link()` vagy `n:href` használatával létrehozott linkek a `lang=en` paramétert is tartalmazni fogják. És amikor a linkre kattintunk, akkor ismét a `$this->lang = 'en'` lesz.
 
-A tulajdonságok esetében javasoljuk, hogy adja meg az adattípust (pl. `string`), és egy alapértelmezett értéket is megadhat. A paraméterek értékei [érvényesíthetők |#Validation of Persistent Parameters].
+A tulajdonságok esetében javasoljuk, hogy adja meg az adattípust (pl. `string`), és megadhatja az alapértelmezett értéket is. A paraméterek értékei [érvényesíthetők |#Validation of Parameters].
 
 A perzisztens paraméterek alapértelmezés szerint egy adott bemutató összes művelete között átadásra kerülnek. Több prezenter között történő átadásukhoz vagy meg kell határozni őket:
 
@@ -307,18 +333,12 @@ Mélyebbre ásva .[#toc-going-deeper]
 Amit eddig ebben a fejezetben bemutattunk, valószínűleg elegendő lesz. A következő sorok azoknak szólnak, akiket a prezenterek mélységében érdekelnek, és mindent tudni akarnak.
 
 
-Követelmények és paraméterek .[#toc-requirement-and-parameters]
----------------------------------------------------------------
-
-A bemutató által kezelt kérés a [api:Nette\Application\Request] objektum, amelyet a bemutató `getRequest()` metódusa ad vissza. Ez paraméterek tömbjét tartalmazza, és mindegyik paraméter vagy valamelyik komponenshez, vagy közvetlenül a prezentálóhoz tartozik (amely valójában szintén egy komponens, bár egy speciális komponens). A Nette tehát a `loadState(array $params)` metódus meghívásával újraosztja a paramétereket és átadja az egyes komponensek (és a prezenter) között. A paramétereket a `getParameters(): array` metódussal lehet megszerezni, egyenként a `getParameter($name)` segítségével. A paraméterek értékei karakterláncok vagy karakterláncok tömbjei, alapvetően közvetlenül az URL-ből nyert nyers adatok.
+A paraméterek validálása .[#toc-validation-of-parameters]
+---------------------------------------------------------
 
+Az URL-ekből kapott [kérési paraméterek |#request parameters] és [állandó paraméterek |#persistent parameters] értékeit a `loadState()` módszer írja a tulajdonságokba. Azt is ellenőrzi, hogy a tulajdonságban megadott adattípus megfelel-e, ellenkező esetben 404-es hibával válaszol, és az oldal nem jelenik meg.
 
-A tartós paraméterek validálása .[#toc-validation-of-persistent-parameters]
----------------------------------------------------------------------------
-
-Az URL-ekből kapott [állandó paraméterek |#persistent parameters] értékeit a `loadState()` módszer írja a tulajdonságokba. A módszer azt is ellenőrzi, hogy a tulajdonságban megadott adattípus megfelel-e, ellenkező esetben 404-es hibával válaszol, és az oldal nem jelenik meg.
-
-Soha ne bízzunk vakon a perzisztens paraméterekben, mivel azokat a felhasználó könnyen felülírhatja az URL-ben. Például így ellenőrizzük, hogy a `$this->lang` szerepel-e a támogatott nyelvek között. Jó megoldás erre a fent említett `loadState()` metódus felülírása:
+Soha ne bízzon vakon a paraméterekben, mert azokat a felhasználó könnyen felülírhatja az URL-ben. Például így ellenőrizzük, hogy a `$this->lang` szerepel-e a támogatott nyelvek között. Ennek jó módja a fent említett `loadState()` metódus felülírása:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 A kérelem mentése és visszaállítása .[#toc-save-and-restore-the-request]
 ------------------------------------------------------------------------
 
-Az aktuális kérést elmentheti egy munkamenetbe, vagy visszaállíthatja a munkamenetből, és hagyhatja, hogy az előadó újra végrehajtsa azt. Ez például akkor hasznos, ha egy felhasználó kitölt egy űrlapot, és a bejelentkezése lejár. Annak érdekében, hogy ne veszítsünk el adatokat, a bejelentkezési oldalra való átirányítás előtt az aktuális kérést a munkamenetbe mentjük a `$reqId = $this->storeRequest()` segítségével, amely egy rövid karakterlánc formájában visszaad egy azonosítót, és paraméterként átadja a bejelentkezési prezenternek.
+A kérés, amelyet a bemutató kezel, egy objektum [api:Nette\Application\Request] és a bemutató `getRequest()` metódusa adja vissza.
+
+Az aktuális kérést elmentheti egy munkamenetbe, vagy visszaállíthatja a munkamenetből, és hagyhatja, hogy a prezenter ismét futtassa. Ez például akkor hasznos, ha egy felhasználó kitölt egy űrlapot, és a bejelentkezése lejár. Annak érdekében, hogy ne veszítsünk el adatokat, a bejelentkezési oldalra való átirányítás előtt az aktuális kérést a munkamenetbe mentjük a `$reqId = $this->storeRequest()` segítségével, amely egy rövid karakterlánc formájában visszaad egy azonosítót, és paraméterként átadja a bejelentkezési prezenternek.
 
 A bejelentkezés után meghívjuk a `$this->restoreRequest($reqId)` metódust, amely átveszi a kérést a munkamenetből, és továbbítja azt. A módszer ellenőrzi, hogy a kérést ugyanaz a felhasználó hozta-e létre, mint aki most bejelentkezett. Ha egy másik felhasználó jelentkezik be, vagy a kulcs érvénytelen, akkor nem tesz semmit, és a program folytatódik.
 
@@ -362,7 +384,7 @@ Az átirányítás nem történik AJAX vagy POST kérés esetén, mivel az adatv
 A kanonizálás manuálisan is meghívható a `canonicalize()` módszerrel, amely a `link()` módszerhez hasonlóan a prezentálót, a műveleteket és a paramétereket kapja argumentumként. Létrehoz egy linket, és összehasonlítja azt az aktuális URL-lel. Ha eltér, akkor átirányít a létrehozott linkre.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// átirányít, ha a $slug különbözik a $realSlug-tól.
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Hozzáférés korlátozása `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+--------------------------------------------------------------------------------------------------
+
+A `#[Requires]` attribútum speciális lehetőségeket biztosít az előadókhoz és módszereikhez való hozzáférés korlátozására. Használható HTTP-módszerek megadására, AJAX-kérések megkövetelésére, az azonos eredetű hozzáférések korlátozására és a hozzáférésnek csak a továbbításra való korlátozására. Az attribútum alkalmazható a prezenter osztályokra, valamint az egyes metódusokra, mint például a `action<Action>()`, `render<View>()`, `handle<Signal>()`, és `createComponent<Name>()`.
+
+Ezeket a korlátozásokat megadhatja:
+- a HTTP-módszerekre: `#[Requires(methods: ['GET', 'POST'])]`
+- AJAX-kérést igényel: `#[Requires(ajax: true)]`
+- hozzáférés csak ugyanabból az eredetből: `#[Requires(sameOrigin: true)]`
+- hozzáférés csak továbbítással: `#[Requires(forward: true)]`
+- korlátozások bizonyos műveletekre: `#[Requires(actions: 'default')]`
+
+A részletekért lásd [Hogyan használjuk a Requires attribútum használata |best-practices:attribute-requires].
+
+
+HTTP módszer ellenőrzése .[#toc-http-method-check]
+--------------------------------------------------
+
+A Nette rendszerben az előadók elsősorban biztonsági okokból automatikusan ellenőrzik minden bejövő kérés HTTP-módszerét. Alapértelmezés szerint a `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` módszerek engedélyezettek.
+
+Ha további módszereket, például a `OPTIONS`, szeretne engedélyezni, akkor használhatja a `#[Requires]` attribútumot (a Nette Application v3.2-től):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+A 3.1-es verzióban az ellenőrzést a `checkHttpMethod()` végzi, amely ellenőrzi, hogy a kérelemben megadott módszer szerepel-e a `$presenter->allowedMethods` tömbben. Adjon hozzá egy ilyen módszert:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Fontos hangsúlyozni, hogy ha engedélyezi a `OPTIONS` módszert, akkor azt megfelelően kell kezelnie a prezenteren belül is. Ezt a módszert gyakran használják úgynevezett preflight-kérelemként, amelyet a böngészők automatikusan elküldenek a tényleges kérés előtt, amikor meg kell határozni, hogy a kérés engedélyezett-e a CORS (Cross-Origin Resource Sharing) irányelv szempontjából. Ha engedélyezi ezt a módszert, de nem valósít meg megfelelő választ, az következetlenségekhez és potenciális biztonsági problémákhoz vezethet.
+
+
 További olvasmányok .[#toc-further-reading]
 ===========================================
 
diff --git a/application/hu/routing.texy b/application/hu/routing.texy
index 5cf399296b..bb4a347148 100644
--- a/application/hu/routing.texy
+++ b/application/hu/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Speciális jelölés .[#toc-advanced-notation]
 -------------------------------------------
 
-Az útvonal második paramétere, amelyet gyakran a `Presenter:action` formátumban írunk, egy rövidítés, amelyet mező formájában is írhatunk, ahol közvetlenül az egyes paraméterek (alapértelmezett) értékeit adjuk meg:
+Az útvonal célját, amelyet általában a `Presenter:action` formában írunk le, egy olyan tömb segítségével is ki lehet fejezni, amely meghatározza az egyes paramétereket és azok alapértelmezett értékeit:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Vagy használhatjuk ezt a formát, vegyük észre az érvényesítési reguláris kifejezés átírását:
+Részletesebb specifikációhoz egy még bővebb formát lehet használni, ahol az alapértelmezett értékek mellett más paramétertulajdonságok is megadhatók, például egy érvényesítési reguláris kifejezés (lásd a `id` paramétert):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Ezek a beszédesebb formátumok hasznosak más metaadatok hozzáadásához.
+Fontos megjegyezni, hogy ha a tömbben definiált paraméterek nem szerepelnek az elérési útvonal maszkjában, akkor értékük nem módosítható, még az URL-ben kérdőjel után megadott lekérdezési paraméterekkel sem.
 
 
 Szűrők és fordítások .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integráció .[#toc-integration]
 ==============================
 
-Ahhoz, hogy a routerünket az alkalmazásba kapcsoljuk, tájékoztatnunk kell róla a DI konténert. A legegyszerűbb, ha elkészítjük a gyárat, amely a router objektumot fogja felépíteni, és megmondjuk a konténer konfigurációjának, hogy használja azt. Tegyük fel, hogy írunk egy metódust erre a célra `App\Router\RouterFactory::createRouter()`:
+Ahhoz, hogy a routerünket az alkalmazásba kapcsoljuk, tájékoztatnunk kell róla a DI konténert. A legegyszerűbb, ha elkészítjük a gyárat, amely a router objektumot fogja felépíteni, és megmondjuk a konténer konfigurációjának, hogy használja azt. Tegyük fel, hogy írunk egy metódust erre a célra `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Ezután beírjuk a [konfigurációba |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Az esetleges függőségeket, például az adatbázis-kapcsolatot stb., az [autowiring |dependency-injection:autowiring] segítségével paraméterként átadjuk a gyári metódusnak:
@@ -663,7 +663,7 @@ A szeparált használat alatt a router képességeinek olyan alkalmazásban tör
 Tehát ismét létrehozunk egy metódust, amely létrehoz egy útválasztót, például:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Vagy közvetlenül hozzuk létre az objektumokat:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/hu/templates.texy b/application/hu/templates.texy
index 71b205b7d1..3f46d2d377 100644
--- a/application/hu/templates.texy
+++ b/application/hu/templates.texy
@@ -34,35 +34,81 @@ Az a szokásos, hogy az oldal az elrendezési sablonból + az akció sablonból
 Meghatározza a `content` blokkot, amely az elrendezésben a `{include content}` helyére kerül, és újra definiálja a `title` blokkot is, amely felülírja az elrendezésben a `{block title}` blokkot. Próbálja meg elképzelni az eredményt.
 
 
-Sablonok keresése .[#toc-search-for-templates]
-----------------------------------------------
+Sablon keresés .[#toc-template-lookup]
+--------------------------------------
 
-A sablonok elérési útvonalát egyszerű logika szerint vezetjük le. Megpróbálja megnézni, hogy létezik-e valamelyik sablonfájl ahhoz a könyvtárhoz képest, ahol a prezenter osztály található, ahol a `<Presenter>` az aktuális prezenter neve és `<view>` az aktuális művelet neve:
+A prezenterekben nem kell megadnia, hogy melyik sablont kell megjeleníteni; a keretrendszer automatikusan meghatározza az útvonalat, megkönnyítve ezzel a kódolást.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Ha olyan könyvtárstruktúrát használ, ahol minden prezenternek saját könyvtára van, egyszerűen helyezze el a sablont ebben a könyvtárban az akció (pl. nézet) neve alatt. Például a `default` művelethez használja a `default.latte` sablont:
 
-Ha a sablon nem található, a program megpróbál a `templates` könyvtárban keresni egy szinttel feljebb, azaz ugyanazon a szinten, mint a bemutató osztályt tartalmazó könyvtár.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Ha a sablon ott sem található, a válasz [404-es hiba |presenters#Error 404 etc.].
+Ha olyan struktúrát használ, ahol az előadók együttesen egy könyvtárban vannak, a sablonok pedig a `templates` mappában, mentse el vagy egy fájlban `<Presenter>.<view>.latte` vagy a `<Presenter>/<view>.latte`:
 
-A nézetet a `$this->setView('otherView')` segítségével is megváltoztathatja. Vagy a keresés helyett közvetlenül megadhatja a sablonfájl nevét a `$this->template->setFile('/path/to/template.latte')` segítségével.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+A `templates` könyvtár egy szinttel feljebb is elhelyezhető, ugyanazon a szinten, mint az előadói osztályokat tartalmazó könyvtár.
+
+Ha a sablon nem található, a prezenter [404 - page not found hibával |presenters#Error 404 etc] válaszol.
+
+A nézetet a `$this->setView('anotherView')` segítségével lehet megváltoztatni. Lehetőség van a sablonfájl közvetlen megadására is a `$this->template->setFile('/path/to/template.latte')` segítségével.
 
 .[note]
-A [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] metódus felülbírálásával módosíthatja azokat az elérési utakat, ahol a sablonok keresése történik, amely a lehetséges fájl elérési utak tömbjét adja vissza.
+A fájlokat, amelyekben a sablonok keresése történik, a [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()] metódus felülbírálásával lehet megváltoztatni, amely a lehetséges fájlnevek tömbjét adja vissza.
+
+
+Layout sablon keresés .[#toc-layout-template-lookup]
+----------------------------------------------------
+
+A Nette automatikusan megkeresi az elrendezési fájlt is.
+
+Ha olyan könyvtárstruktúrát használ, ahol minden előadónak saját könyvtára van, akkor az elrendezést vagy az előadóval közös mappába helyezze el, ha csak rá jellemző, vagy egy szinttel feljebb, ha több előadó számára közös:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Ha olyan struktúrát használ, ahol az előadók egy könyvtárban vannak csoportosítva, a sablonok pedig a `templates` mappában találhatók, az elrendezés a következő helyeken várható:
 
-Az elrendezés a következő fájlokban várható:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` több előadónál közös elrendezés
+Ha a bemutató egy [modulban |modules] van, akkor a modul beágyazottságának megfelelően a könyvtárfában feljebb is keresni fog.
 
-`<Presenter>` az aktuális előadó neve és `<layout>` az elrendezés neve, amely alapértelmezés szerint `'layout'`. A név megváltoztatható a `$this->setLayout('otherLayout')` segítségével, így a `@otherLayout.latte` fájlokat próbálja meg.
+Az elrendezés nevét a `$this->setLayout('layoutAdmin')` segítségével lehet megváltoztatni, majd a `@layoutAdmin.latte` fájlban várjuk el. Az elrendezés sablonfájlt közvetlenül is megadhatja a `$this->setLayout('/path/to/template.latte')` segítségével.
 
-Az elrendezéssablon fájlnevét közvetlenül is megadhatja a `$this->setLayout('/path/to/template.latte')` segítségével. A `$this->setLayout(false)` használata letiltja az elrendezés keresését.
+A `$this->setLayout(false)` vagy a `{layout none}` címke használata a sablonon belül kikapcsolja az elrendezéskeresést.
 
 .[note]
-A [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] metódus felülbírálásával módosíthatja a sablonok keresési útvonalait, amely a lehetséges fájlútvonalak tömbjét adja vissza.
+A fájlok, amelyekben az elrendezési sablonok keresése történik, megváltoztathatók a [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] metódus felülbírálásával, amely a lehetséges fájlnevek tömbjét adja vissza.
 
 
 Változók a sablonban .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ A `@property-read` annotáció az IDE és a statikus elemzés számára készül
 A sablonokban is megengedheted magadnak a suttogás luxusát, csak telepítsd a Latte plugint a PhpStormban, és add meg az osztály nevét a sablon elején, lásd a "Latte: hogyan kell tipizálni a rendszert":https://blog.nette.org/hu/latte-hogyan-kell-hasznalni-a-tipusrendszert című cikket:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 A Latte 3. verziója egy fejlettebb módszert kínál, amely minden egyes webes projekthez egy [bővítményt |latte:creating-extension] hoz létre. Íme egy durva példa egy ilyen osztályra:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ A [configuration |configuration#Latte] segítségével regisztráljuk:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternatívaként a fordítót a [konfiguráció |configuration#Latte] segítsé
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 A fordító ekkor például a `|translate` szűrőként használható, a `translate()` metódusnak átadott további paraméterekkel (lásd `foo, bar`):
diff --git a/application/it/@home.texy b/application/it/@home.texy
index 6c54a56fdd..b747c11f9f 100644
--- a/application/it/@home.texy
+++ b/application/it/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | versione | compatibile con PHP
 |-----------|-------------------
-| Applicazione Nette 4.0 | PHP 8.0 - 8.2
-| Applicazione Nette 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Applicazione Nette 3.0 | PHP 7.1 - 8.0
 | Applicazione Nette 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/it/ajax.texy b/application/it/ajax.texy
index 61d7bcd9ca..f15f19b518 100644
--- a/application/it/ajax.texy
+++ b/application/it/ajax.texy
@@ -3,10 +3,10 @@ AJAX e Snippet
 
 <div class=perex>
 
-Le moderne applicazioni web oggi vengono eseguite per metà su un server e per metà in un browser. AJAX è un fattore di unione vitale. Quale supporto offre il Nette Framework?
-- invio di frammenti di template (i cosiddetti *snippet*)
+Nell'era delle moderne applicazioni web, in cui le funzionalità si estendono spesso tra il server e il browser, AJAX è un elemento di connessione essenziale. Quali opzioni offre Nette Framework in questo ambito?
+- invio di parti del modello, i cosiddetti snippet
 - passaggio di variabili tra PHP e JavaScript
-- debug delle applicazioni AJAX
+- strumenti per il debug delle richieste AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ Le moderne applicazioni web oggi vengono eseguite per metà su un server e per m
 Richiesta AJAX .[#toc-ajax-request]
 ===================================
 
-Una richiesta AJAX non differisce da una richiesta classica: il presentatore viene chiamato con una vista e dei parametri specifici. Il presentatore può anche decidere come rispondere: può usare la propria routine, che restituisce un frammento di codice HTML (snippet HTML), un documento XML, un oggetto JSON o codice JavaScript.
+Una richiesta AJAX fondamentalmente non differisce da una richiesta HTTP classica. Un presentatore viene chiamato con parametri specifici. Spetta al presentatore rispondere alla richiesta: può restituire dati in formato JSON, inviare una parte di codice HTML, un documento XML, ecc.
 
-Sul lato server, una richiesta AJAX può essere rilevata utilizzando il metodo di servizio [che incapsula la richiesta HTTP |http:request] `$httpRequest->isAjax()` (rileva in base all'intestazione HTTP `X-Requested-With`). All'interno del presentatore, è disponibile una scorciatoia sotto forma del metodo `$this->isAjax()`.
+Dal lato del browser, si avvia una richiesta AJAX utilizzando la funzione `fetch()`:
 
-Esiste un oggetto pre-elaborato chiamato `payload`, dedicato all'invio di dati al browser in JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// elaborazione della risposta
+});
 ```
 
-Per un controllo completo sull'output JSON, utilizzare il metodo `sendJson` nel presenter. Il metodo termina immediatamente il presentatore e si può fare a meno di un template:
+Sul lato server, una richiesta AJAX viene riconosciuta dal metodo `$httpRequest->isAjax()` del servizio [che incapsula la richiesta HTTP |http:request]. Utilizza l'intestazione HTTP `X-Requested-With`, quindi è essenziale inviarla. All'interno del presenter, è possibile utilizzare il metodo `$this->isAjax()`.
+
+Se si desidera inviare dati in formato JSON, utilizzare il metodo [`sendJson()` |presenters#Sending a response] . Il metodo termina anche l'attività del presentatore.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Se vogliamo inviare HTML, possiamo impostare un modello speciale per le richieste AJAX:
+Se si intende rispondere con un modello speciale progettato per AJAX, si può procedere come segue:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Frammenti .[#toc-snippets]
+==========================
+
+Lo strumento più potente offerto da Nette per collegare il server al client sono gli snippet. Con essi, è possibile trasformare un'applicazione ordinaria in una AJAX con il minimo sforzo e poche righe di codice. L'esempio di Fifteen ne dimostra il funzionamento e il suo codice è disponibile su [GitHub |https://github.com/nette-examples/fifteen].
+
+Gli snippet, o ritagli, consentono di aggiornare solo alcune parti della pagina, invece di ricaricare l'intera pagina. Questo è più veloce ed efficiente e offre anche un'esperienza d'uso più confortevole. Gli snippet potrebbero ricordare Hotwire per Ruby on Rails o Symfony UX Turbo. È interessante notare che Nette ha introdotto gli snippet 14 anni prima.
+
+Come funzionano gli snippet? Quando la pagina viene caricata per la prima volta (una richiesta non-AJAX), viene caricata l'intera pagina, compresi tutti gli snippet. Quando l'utente interagisce con la pagina (ad esempio, fa clic su un pulsante, invia un modulo, ecc.), invece di caricare l'intera pagina, viene effettuata una richiesta AJAX. Il codice del presentatore esegue l'azione e decide quali snippet devono essere aggiornati. Nette esegue il rendering di questi frammenti e li invia sotto forma di array JSON. Il codice di gestione del browser inserisce quindi gli snippet ricevuti nella pagina. Pertanto, viene trasferito solo il codice degli snippet modificati, risparmiando larghezza di banda e velocizzando il caricamento rispetto al trasferimento dell'intero contenuto della pagina.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-La [libreria Naja |https://naja.js.org] è usata per gestire le richieste AJAX sul lato browser. [Installarla |https://naja.js.org/#/guide/01-install-setup-naja] come pacchetto node.js (da usare con Webpack, Rollup, Vite, Parcel e altri):
+Per gestire gli snippet sul lato browser, si usa la [libreria Naja |https://naja.js.org]. [Installarla |https://naja.js.org/#/guide/01-install-setup-naja] come pacchetto node.js (da usare con applicazioni come Webpack, Rollup, Vite, Parcel e altre):
 
 ```shell
 npm install naja
 ```
 
-... o inserirla direttamente nel modello della pagina:
+... o inserirla direttamente nel modello di pagina:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Per creare una richiesta AJAX da un normale link (segnale) o dall'invio di un modulo, è sufficiente contrassegnare il relativo link, modulo o pulsante con la classe `ajax`:
+Per prima cosa è necessario [inizializzare |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] la libreria:
+
+```js
+naja.initialize();
+```
+
+Per rendere un normale link (segnale) o l'invio di un modulo una richiesta AJAX, è sufficiente contrassegnare il rispettivo link, modulo o pulsante con la classe `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Per creare una richiesta AJAX da un normale link (segnale) o dall'invio di un mo
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippet .[#toc-snippets]
-========================
-
-Esiste uno strumento molto più potente del supporto AJAX integrato: gli snippet. Il loro utilizzo consente di trasformare una normale applicazione in un'applicazione AJAX utilizzando solo poche righe di codice. Il funzionamento è dimostrato nell'esempio di Fifteen, il cui codice è accessibile nella build o su [GitHub |https://github.com/nette-examples/fifteen].
-
-Il modo in cui funzionano gli snippet è che l'intera pagina viene trasferita durante la richiesta iniziale (cioè non AJAX) e poi a ogni [sotto-richiesta |components#signal] AJAX (richiesta della stessa vista dello stesso presentatore) viene trasferito solo il codice delle parti modificate nel repository `payload` menzionato in precedenza.
-
-Gli snippet possono ricordare Hotwire per Ruby on Rails o Symfony UX Turbo, ma Nette li ha ideati quattordici anni prima.
-
+Ridisegno degli snippet .[#toc-redrawing-snippets]
+--------------------------------------------------
 
-Invalidazione degli Snippet .[#toc-invalidation-of-snippets]
-============================================================
-
-Ogni discendente della classe [Control |components] (di cui fa parte anche un Presentatore) è in grado di ricordare se durante una richiesta sono state apportate modifiche che richiedono un nuovo rendering. Esistono due metodi per gestire questo aspetto: `redrawControl()` e `isControlInvalid()`. Un esempio:
+Ogni oggetto della classe [Control |components] (compreso il Presentatore stesso) registra se sono avvenuti cambiamenti che richiedono il suo ridisegno. A tale scopo viene utilizzato il metodo `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// L'oggetto deve essere ri-renderizzato dopo che l'utente ha effettuato il login
+	// dopo l'accesso, è necessario ridisegnare la parte pertinente
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette offre tuttavia una risoluzione ancora più fine rispetto ai componenti interi. I metodi elencati accettano il nome di un cosiddetto "snippet" come parametro opzionale. Uno "snippet" è fondamentalmente un elemento del modello contrassegnato a tale scopo da una tag di Latte, di cui si parlerà più avanti. In questo modo è possibile chiedere a un componente di ridisegnare solo *parti* del suo modello. Se l'intero componente viene invalidato, tutti i suoi frammenti vengono ridisegnati. Un componente è "invalido" anche se uno qualsiasi dei suoi sottocomponenti è invalido.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // invalida lo snippet denominato 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, almeno uno snippet non è valido
+Nette consente anche un controllo più preciso di ciò che deve essere ridisegnato. Il metodo summenzionato può accettare il nome dello snippet come argomento. In questo modo, è possibile invalidare (cioè forzare un ridisegno) a livello di parte del modello. Se l'intero componente viene invalidato, anche ogni frammento viene ridisegnato:
 
-$this->redrawControl(); // invalida l'intero componente, ogni snippet
-$this->isControlInvalid('footer'); // -> true
+```php
+// invalida lo snippet "header
+$this->redrawControl('header');
 ```
 
-Un componente che riceve un segnale viene automaticamente contrassegnato per essere ridisegnato.
-
-Grazie allo snippet redrawing sappiamo esattamente quali parti di quali elementi devono essere ridisegnate.
-
-
-Tag `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
-
-Il rendering della pagina procede in modo molto simile a una normale richiesta: vengono caricati gli stessi template, ecc. La parte fondamentale è, tuttavia, lasciare fuori le parti che non devono raggiungere l'output; le altre parti devono essere associate a un identificatore e inviate all'utente in un formato comprensibile per un gestore JavaScript.
-
 
-Sintassi .[#toc-syntax]
------------------------
+Frammenti in Latte .[#toc-snippets-in-latte]
+--------------------------------------------
 
-Se c'è un controllo o uno snippet nel template, dobbiamo avvolgerlo usando il tag di coppia `{snippet} ... {/snippet}` - che farà in modo che lo snippet reso venga "tagliato" e inviato al browser. Lo racchiuderà anche in un tag di aiuto `<div>` (è possibile utilizzarne uno diverso). Nell'esempio seguente viene definito uno snippet chiamato `header`. Può anche rappresentare il modello di un componente:
+L'uso degli snippet in Latte è estremamente semplice. Per definire una parte del modello come snippet, è sufficiente avvolgerla nei tag `{snippet}` e `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Se c'è un controllo o uno snippet nel template, dobbiamo avvolgerlo usando il t
 {/snippet}
 ```
 
-Uno snippet di tipo diverso da `<div>` o uno snippet con attributi HTML aggiuntivi si ottiene utilizzando la variante dell'attributo:
+Lo snippet crea un elemento `<div>` nella pagina HTML con un elemento `id` appositamente generato. Quando si ridisegna uno snippet, il contenuto di questo elemento viene aggiornato. Pertanto, quando la pagina viene inizialmente resa, devono essere resi anche tutti gli snippet, anche se inizialmente possono essere vuoti.
+
+È anche possibile creare uno snippet con un elemento diverso da `<div>` utilizzando l'attributo n:n:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Uno snippet di tipo diverso da `<div>` o uno snippet con attributi HTML aggiunti
 ```
 
 
-Snippet dinamici .[#toc-dynamic-snippets]
-=========================================
+Aree Snippet .[#toc-snippet-areas]
+----------------------------------
 
-In Nette è possibile definire snippet con un nome dinamico basato su un parametro di runtime. Ciò è particolarmente indicato per vari elenchi in cui è necessario modificare una sola riga, ma non si vuole trasferire l'intero elenco. Un esempio potrebbe essere:
+I nomi dei frammenti possono anche essere espressioni:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Esiste uno snippet statico chiamato `itemsContainer`, che contiene diversi snippet dinamici: `item-0`, `item-1` e così via.
+In questo modo si otterranno diversi snippet come `item-0`, `item-1`, ecc. Se si invalidasse direttamente uno snippet dinamico (ad esempio, `item-1`), non verrebbe ridisegnato nulla. Il motivo è che gli snippet funzionano come veri e propri estratti e solo essi vengono resi direttamente. Tuttavia, nel template non esiste tecnicamente uno snippet chiamato `item-1`. Emerge solo quando si esegue il codice circostante lo snippet, in questo caso il ciclo foreach. Pertanto, contrassegneremo la parte del template che deve essere eseguita con il tag `{snippetArea}`:
 
-Non è possibile ridisegnare direttamente uno snippet dinamico (il ridisegno di `item-1` non ha alcun effetto), ma è necessario ridisegnare il suo snippet padre (in questo esempio `itemsContainer`). Questo provoca l'esecuzione del codice dello snippet padre, ma poi solo i suoi sotto-snippet vengono inviati al browser. Se si vuole inviare solo uno dei sotto-nippet, è necessario modificare l'input dello snippet padre per non generare gli altri sotto-nippet.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-Nell'esempio precedente, bisogna assicurarsi che per una richiesta AJAX venga aggiunto un solo elemento all'array `$list`, quindi il ciclo `foreach` stamperà un solo frammento dinamico.
+E ridisegneremo sia il singolo snippet che l'intera area circostante:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+È inoltre essenziale assicurarsi che l'array `$items` contenga solo gli elementi che devono essere ridisegnati.
 
-Snippet in un template incluso .[#toc-snippets-in-an-included-template]
-=======================================================================
-
-Può accadere che lo snippet si trovi in un template che viene incluso da un template diverso. In questo caso, occorre avvolgere il codice di inclusione nel secondo template con la tag `snippetArea`, quindi ridisegnare sia la snippetArea che lo snippet vero e proprio.
-
-La tag `snippetArea` assicura che il codice all'interno venga eseguito, ma che al browser venga inviato solo lo snippet effettivo nel modello incluso.
+Quando si inserisce un altro modello in quello principale usando il tag `{include}`, che ha degli snippet, è necessario avvolgere nuovamente il modello incluso in un `snippetArea` e invalidare sia lo snippet che l'area insieme:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* incluso.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Si può anche combinare con gli snippet dinamici.
 
+Snippet nei componenti .[#toc-snippets-in-components]
+-----------------------------------------------------
 
-Aggiunta e cancellazione .[#toc-adding-and-deleting]
-====================================================
-
-Se si aggiunge un nuovo elemento all'elenco e si invalida `itemsContainer`, la richiesta AJAX restituisce gli snippet che includono il nuovo elemento, ma il gestore javascript non sarà in grado di renderlo. Questo perché non esiste un elemento HTML con l'ID appena creato.
-
-In questo caso, il modo più semplice è avvolgere l'intero elenco in un altro frammento e invalidare il tutto:
+È possibile creare snippet all'interno dei [componenti |components] e Nette li ridisegna automaticamente. Tuttavia, c'è una limitazione specifica: per ridisegnare gli snippet, viene chiamato il metodo `render()` senza alcun parametro. Pertanto, il passaggio di parametri nel modello non funziona:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Invio di dati utente .[#toc-sending-user-data]
+----------------------------------------------
+
+Oltre agli snippet, è possibile inviare qualsiasi altro dato al client. È sufficiente scriverli nell'oggetto `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Lo stesso vale per la cancellazione di un elemento. Sarebbe possibile inviare uno snippet vuoto, ma di solito gli elenchi possono essere paginati e sarebbe complicato implementare la cancellazione di un elemento e il caricamento di un altro (che si trovava in una pagina diversa dell'elenco paginato).
-
 
-Invio di parametri al componente .[#toc-sending-parameters-to-component]
-========================================================================
+Parametri di invio .[#toc-sending-parameters]
+=============================================
 
 Quando si inviano parametri al componente tramite una richiesta AJAX, sia che si tratti di parametri di segnale che di parametri persistenti, occorre fornire il loro nome globale, che contiene anche il nome del componente. Il nome completo del parametro restituisce il metodo `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-E gestire il metodo con i parametri corrispondenti nel componente.
+Un metodo handle con i parametri corrispondenti nel componente:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/it/bootstrap.texy b/application/it/bootstrap.texy
index 4efbe28af1..b338b46064 100644
--- a/application/it/bootstrap.texy
+++ b/application/it/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Il configuratore è responsabile dell'impostazione dell'ambiente applicativo e dei servizi.
+		$this->configurator = new Configurator;
+		// Impostare la directory per i file temporanei generati da Nette (ad esempio, i modelli compilati).
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette è intelligente e la modalità di sviluppo si attiva automaticamente,
+		// oppure si può attivare per un indirizzo IP specifico decommentando la seguente riga:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Abilita Tracy: lo strumento di debug per eccellenza, il "coltellino svizzero".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: carica automaticamente tutte le classi nella cartella data
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Carica i file di configurazione
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Nel caso delle applicazioni web, il file iniziale è `index.php`, che si trova nella cartella pubblica `www/`. Permette alla classe `Bootstrap` di inizializzare l'ambiente e restituisce la classe `$configurator` che crea il contenitore DI. Quindi ottiene il servizio `Application`, che esegue l'applicazione web:
+Il file iniziale per le applicazioni web è `index.php`, situato nella cartella pubblica `www/`. Utilizza la classe `Bootstrap` per inizializzare l'ambiente e creare un contenitore DI. Quindi, ottiene il servizio `Application` dal contenitore, che lancia l'applicazione web:
 
 ```php
-// inizializzare l'ambiente + ottenere l'oggetto Configuratore
-$configurator = App\Bootstrap::boot();
-// creare un contenitore DI
-$container = $configurator->createContainer();
-// Il contenitore DI crea un oggetto Nette\Application\Application
+$bootstrap = new App\Bootstrap;
+// Inizializzare l'ambiente + creare un contenitore DI
+$container = $bootstrap->bootWebApplication();
+// Il contenitore DI crea un oggetto NetteApplicationApplication
 $application = $container->getByType(Nette\Application\Application::class);
-// avvia l'applicazione Nette
+// Avviare l'applicazione Nette e gestire la richiesta in arrivo
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ La selezione della modalità avviene tramite il rilevamento automatico, quindi d
 Se si vuole abilitare la modalità di sviluppo in altri casi, ad esempio per i programmatori che accedono da un indirizzo IP specifico, si può usare `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // uno o più indirizzi IP
+$this->configurator->setDebugMode('23.75.345.200'); // uno o più indirizzi IP
 ```
 
 Consigliamo assolutamente di combinare un indirizzo IP con un cookie. Nel cookie `nette-debug` verrà memorizzato un token segreto, ad esempio `secret1234`, e la modalità di sviluppo verrà attivata per i programmatori con questa combinazione di IP e cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Possiamo anche disattivare completamente la modalità sviluppatore, anche per localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Si noti che il valore `true` attiva la modalità sviluppatore, cosa che non dovrebbe mai accadere su un server di produzione.
@@ -90,7 +115,7 @@ Strumento di debug Tracy .[#toc-debugging-tool-tracy]
 Per facilitare il debug, attiviamo l'ottimo strumento [Tracy |tracy:]. In modalità sviluppatore visualizza gli errori e in modalità produzione li registra nella directory specificata:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ File temporanei .[#toc-temporary-files]
 Nette utilizza la cache per il contenitore DI, il RobotLoader, i modelli, ecc. Per questo motivo è necessario impostare il percorso della cartella in cui verrà memorizzata la cache:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Su Linux o macOS, impostare i [permessi di scrittura |nette:troubleshooting#Setting directory permissions] per le directory `log/` e `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Di solito, vogliamo caricare automaticamente le classi usando [RobotLoader |robot-loader:], quindi dobbiamo avviarlo e fargli caricare le classi dalla directory in cui si trova `Bootstrap.php` (cioè `__DIR__`) e da tutte le sue sottodirectory:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Fuso orario .[#toc-timezone]
 Il configuratore consente di specificare un fuso orario per l'applicazione.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ In modalità di sviluppo, il contenitore viene aggiornato automaticamente ogni v
 I file di configurazione vengono caricati usando `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Il metodo `addConfig()` può essere richiamato più volte per aggiungere più file.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Parametri statici .[#toc-static-parameters]
 I parametri usati nei file di configurazione possono essere definiti [nella sezione `parameters` |dependency-injection:configuration#parameters] e anche passati (o sovrascritti) dal metodo `addStaticParameters()` (ha l'alias `addParameters()`). È importante che valori diversi dei parametri causino la generazione di contenitori DI aggiuntivi, cioè di classi aggiuntive.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Parametri dinamici .[#toc-dynamic-parameters]
 Possiamo anche aggiungere parametri dinamici al contenitore; i loro diversi valori, a differenza dei parametri statici, non causeranno la generazione di nuovi contenitori DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Le variabili d'ambiente possono essere facilmente rese disponibili usando parametri dinamici. Possiamo accedervi tramite `%env.variable%` nei file di configurazione.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Parametri predefiniti .[#toc-default-parameters]
 - `%wwwDir%` è il percorso assoluto della directory contenente il file di ingresso `index.php`
 - `%tempDir%` è il percorso assoluto della directory per i file temporanei
 - `%vendorDir%` è il percorso assoluto della directory in cui Composer installa le librerie
+- `%rootDir%` è il percorso assoluto della directory principale del progetto
 - `%debugMode%` indica se l'applicazione è in modalità debug
 - `%consoleMode%` indica se la richiesta è arrivata attraverso la riga di comando
 
@@ -225,7 +252,7 @@ services:
 Creare una nuova istanza e inserirla in bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Ambienti diversi .[#toc-different-environments]
 ===============================================
 
-Sentitevi liberi di personalizzare la classe `Bootstrap` in base alle vostre esigenze. Si possono aggiungere parametri al metodo `boot()` per differenziare i progetti web, oppure aggiungere altri metodi, come `bootForTests()`, che inizializza l'ambiente per i test unitari, `bootForCli()` per gli script chiamati dalla riga di comando e così via.
+Non esitate a personalizzare la classe `Bootstrap` in base alle vostre esigenze. Si possono aggiungere parametri al metodo `bootWebApplication()` per differenziare i progetti web. In alternativa, si possono aggiungere altri metodi, come `bootTestEnvironment()` per inizializzare l'ambiente per i test unitari, `bootConsoleApplication()` per gli script chiamati dalla riga di comando e così via.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Inizializzazione del tester Nette
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Nette Tester initialization
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/it/components.texy b/application/it/components.texy
index ad8d123bb0..a4198af736 100644
--- a/application/it/components.texy
+++ b/application/it/components.texy
@@ -230,6 +230,28 @@ Nel modello, questi messaggi sono disponibili nella variabile `$flashes` come og
 ```
 
 
+Reindirizzamento dopo un segnale .[#toc-redirection-after-a-signal]
+===================================================================
+
+Dopo l'elaborazione di un segnale di un componente, spesso segue un reindirizzamento. Questa situazione è simile a quella dei moduli: dopo l'invio di un modulo, si effettua un reindirizzamento per evitare che i dati vengano inviati nuovamente quando la pagina viene aggiornata nel browser.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Poiché un componente è un elemento riutilizzabile e di solito non dovrebbe avere una dipendenza diretta da presentatori specifici, i metodi `redirect()` e `link()` interpretano automaticamente il parametro come un segnale di componente:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Se è necessario reindirizzare a un presentatore o a un'azione diversa, lo si può fare attraverso il presentatore:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Parametri persistenti .[#toc-persistent-parameters]
 ===================================================
 
@@ -347,7 +369,7 @@ services:
 Infine, utilizzeremo questo factory nel nostro presenter:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Componenti in profondità .[#toc-components-in-depth]
 I componenti di un'applicazione Nette sono le parti riutilizzabili di un'applicazione Web che vengono incorporate nelle pagine, argomento di questo capitolo. Quali sono esattamente le funzionalità di un componente?
 
 1) è renderizzabile in un modello
-2) sa quale parte di sé rendere durante una [richiesta AJAX |ajax#invalidation] (snippet)
+2) sa [quale parte di se stesso |ajax#snippets] rendere durante una richiesta AJAX (snippet)
 3) ha la capacità di memorizzare il proprio stato in un URL (parametri persistenti)
 4) ha la capacità di rispondere alle azioni dell'utente (segnali)
 5) crea una struttura gerarchica (dove la radice è il presenter)
diff --git a/application/it/configuration.texy b/application/it/configuration.texy
index 2fc47b2fab..c4703d5632 100644
--- a/application/it/configuration.texy
+++ b/application/it/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# mostra il pannello "Applicazione Nette" in Tracy BlueScreen?
 	debugger: ...           # (bool) predefinito a true
 
-	# Il presentatore di errori sarà chiamato in caso di errore?
-	catchExceptions: ...    # (bool) predefinito a true in modalità di produzione
+	# Il presentatore di errori sarà chiamato su un errore?
+	# ha effetto solo in modalità sviluppatore
+	catchExceptions: ...    # (bool) predefinito a true
 
 	# nome del presentatore di errori
-	errorPresenter: Error   # (string) predefinito a 'Nette:Error'.
+	errorPresenter: Error   # (string|array) predefinito a 'Nette:Error'.
+
+	# definisce gli alias per i presentatori e gli eventi
+	aliases: ...
 
 	# definisce le regole per risolvere il nome del presentatore in una classe
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) predefinito a false
 ```
 
-Poiché i presentatori di errori non vengono richiamati per impostazione predefinita in modalità di sviluppo e gli errori vengono visualizzati da Tracy, la modifica del valore `catchExceptions` a `true` aiuta a verificare che i presentatori di errori funzionino correttamente durante lo sviluppo.
+Dalla versione 3.2 di `nette/application` è possibile definire una coppia di presentatori di errori:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # per NetteApplicationBadRequestException
+		5xx: Error5xx   # per altre eccezioni
+```
 
 L'opzione `silentLinks` determina il comportamento di Nette in modalità sviluppatore quando la generazione dei collegamenti fallisce (ad esempio, perché non c'è un presentatore, ecc.). Il valore predefinito `false` significa che Nette attiva `E_USER_WARNING`. L'impostazione di `true` sopprime questo messaggio di errore. In un ambiente di produzione, `E_USER_WARNING` viene sempre invocato. Si può anche influenzare questo comportamento impostando la variabile del presentatore [$invalidLinkMode |creating-links#Invalid Links].
 
+Gli [pseudonimi semplificano il riferimento ai |creating-links#aliases] presentatori utilizzati di frequente.
+
 La [mappatura definisce le regole |modules#mapping] con cui il nome della classe viene derivato dal nome del presentatore.
 
 
@@ -80,7 +93,10 @@ latte:
 	strictParsing: ...   # (bool) l'impostazione predefinita è false
 
 	# abilita il [controllo del codice generato |latte:develop#Checking Generated Code]
-	phpLinter: ...       # (stringa) il valore predefinito è null
+	phpLinter: ...       # (string) il valore predefinito è null
+
+	# imposta il locale
+	locale: cs_CZ        # (string) il valore predefinito è null
 
 	# classe di $this->template
 	templateClass: App\MyTemplateClass # predefinita a Nette\Bridges\ApplicationLatte\DefaultTemplate
@@ -91,7 +107,7 @@ Se si utilizza la versione 3 di Latte, è possibile aggiungere nuove [estensioni
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/it/creating-links.texy b/application/it/creating-links.texy
index 7b8cafdf00..1c83fc0b31 100644
--- a/application/it/creating-links.texy
+++ b/application/it/creating-links.texy
@@ -38,7 +38,7 @@ Cliccare su un link è, in parole povere, come chiamare un metodo `ProductPresen
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Se il metodo `ProductPresenter::renderShow()` non ha `$lang` nella sua firma, può leggere il valore del parametro usando `$lang = $this->getParameter('lang')`.
+Se il metodo `ProductPresenter::renderShow()` non ha `$lang` nella sua firma, può recuperare il valore del parametro usando `$lang = $this->getParameter('lang')` o dalla [proprietà |presenters#Request Parameters].
 
 Se i parametri sono memorizzati in un array, possono essere espansi con l'operatore `...` (o `(expand)` in Latte 2.x):
 
@@ -140,7 +140,7 @@ Il target `this` creerà un collegamento alla pagina corrente:
 <a n:href="this">refresh</a>
 ```
 
-Allo stesso tempo, tutti i parametri specificati nella firma del metodo `render<View>()` o `action<Action>()` vengono trasferiti. Quindi, se ci troviamo nelle pagine `Product:show` e `id:123`, anche il collegamento a `this` passerà questo parametro.
+Allo stesso tempo, tutti i parametri specificati nella firma dell'elemento `action<Action>()` o `render<View>()` se il metodo `action<Action>()` non è definito, vengono trasferiti. Quindi, se ci troviamo nelle pagine `Product:show` e `id:123`, il collegamento a `this` passerà anche questo parametro.
 
 Naturalmente, è possibile specificare direttamente i parametri:
 
@@ -213,7 +213,7 @@ Poiché i [componenti |components] sono unità riutilizzabili separate che non d
 Se vogliamo collegarci ai presentatori nel modello del componente, usiamo il tag `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 o nel codice
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Alias .[#toc-aliases]{data-version:v3.2.2}
+==========================================
+
+A volte è utile assegnare un alias facilmente memorizzabile a una coppia Presentatore:azione. Per esempio, si può nominare la pagina iniziale `Front:Home:default` semplicemente come `home` o `Admin:Dashboard:default` come `admin`.
+
+Gli alias sono definiti nella [configurazione |configuration] sotto la chiave `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+Nei collegamenti, vengono scritti utilizzando il simbolo at, ad esempio:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Sono supportati in tutti i metodi che lavorano con i collegamenti, come `redirect()` e simili.
+
+
 Collegamenti non validi .[#toc-invalid-links]
 =============================================
 
diff --git a/application/it/how-it-works.texy b/application/it/how-it-works.texy
index bff0380317..3222b1f408 100644
--- a/application/it/how-it-works.texy
+++ b/application/it/how-it-works.texy
@@ -22,18 +22,18 @@ La struttura delle directory è simile a questa:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← classi di base necessarie
+│   │   └── <b>RouterFactory.php</b> ← configurazione degli indirizzi URL
+│   ├── <b>UI/</b>                   ← presenter, template & co.
+│   │   ├── <b>@layout.latte</b>     ← modello di layout condiviso
+│   │   └── <b>Home/</b>             ← cartella del presentatore Home
+│   │       ├── <b>HomePresenter.php</b> ← Classe del presentatore della casa
+│   │       └── <b>default.latte</b> ← template per l'azione default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ Le applicazioni scritte in Nette sono suddivise in molti cosiddetti presenter (i
 
 L'applicazione inizia chiedendo al cosiddetto router di decidere a quale dei presenter passare la richiesta corrente per l'elaborazione. Il router decide di chi è la responsabilità. Osserva l'URL di ingresso `https://example.com/product/123`, che vuole `show` un prodotto con `id: 123` come azione. È buona abitudine scrivere le coppie presentatore + azione separate da due punti come `Product:show`.
 
-Quindi il router ha trasformato l'URL in una coppia `Presenter:action` + parametri, nel nostro caso `Product:show` + `id: 123`. Si può vedere l'aspetto di un router nel file `app/Router/RouterFactory.php` e lo descriveremo in dettaglio nel capitolo [Routing |Routing].
+Quindi il router ha trasformato l'URL in una coppia `Presenter:action` + parametri, nel nostro caso `Product:show` + `id: 123`. Si può vedere l'aspetto di un router nel file `app/Core/RouterFactory.php` e lo descriveremo in dettaglio nel capitolo [Routing |Routing].
 
 Andiamo avanti. L'applicazione conosce già il nome del presentatore e può continuare. Creando un oggetto `ProductPresenter`, che è il codice del presentatore `Product`. Più precisamente, chiede al contenitore DI di creare il presentatore, perché produrre oggetti è il suo lavoro.
 
@@ -121,12 +121,9 @@ Quindi, è stato chiamato il metodo `renderShow(123)`, il cui codice è un esemp
 
 Successivamente, il presentatore restituisce la risposta. Questa può essere una pagina HTML, un'immagine, un documento XML, l'invio di un file dal disco, JSON o il reindirizzamento a un'altra pagina. È importante notare che, se non si dice esplicitamente come rispondere (come nel caso di `ProductPresenter`), la risposta sarà il rendering del modello con una pagina HTML. Perché? Perché nel 99% dei casi vogliamo disegnare un modello, quindi il presentatore prende questo comportamento come predefinito e vuole semplificarci il lavoro. Questo è il punto di Nette.
 
-Non dobbiamo nemmeno dichiarare quale modello disegnare, lui ricava il percorso per raggiungerlo secondo una semplice logica. Nel caso del presenter `Product` e dell'azione `show`, cerca di vedere se esiste uno di questi file di template relativi alla directory in cui si trova la classe `ProductPresenter`:
+Non è nemmeno necessario specificare quale template rendere; il framework dedurrà da solo il percorso. Nel caso dell'azione `show`, cerca semplicemente di caricare il template `show.latte` nella cartella con la classe `ProductPresenter`. Cerca anche di trovare il layout nel file `@layout.latte` (maggiori informazioni sulla [ricerca dei template |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Cercherà anche di trovare il layout nel file `@layout.latte` e quindi eseguirà il rendering del modello. Ora il compito del presentatore e dell'intera applicazione è completato. Se il modello non esiste, verrà restituita una pagina con errore 404. Per saperne di più sui presentatori, consultare la pagina [Presentatori |Presenters].
+Successivamente, i modelli vengono renderizzati. Questo completa il compito del presentatore e dell'intera applicazione e il lavoro è terminato. Se il modello non esistesse, verrebbe restituita una pagina di errore 404. Per saperne di più sui presentatori, consultare la pagina [Presentatori |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Per sicurezza, proviamo a riepilogare l'intero processo con un URL leggermente d
 3) il router decodifica l'URL come una coppia di oggetti `Home:default`
 4) viene creato un oggetto `HomePresenter`
 5) viene richiamato il metodo `renderDefault()` (se esiste)
-6) viene reso un modello `templates/Home/default.latte` con un layout `templates/@layout.latte`
+6) viene reso un modello `default.latte` con un layout `@layout.latte`
 
 
 Potreste esservi imbattuti in molti concetti nuovi, ma crediamo che abbiano un senso. Creare applicazioni in Nette è un gioco da ragazzi.
diff --git a/application/it/modules.texy b/application/it/modules.texy
index 55ee0c0696..4a4e9c1539 100644
--- a/application/it/modules.texy
+++ b/application/it/modules.texy
@@ -2,29 +2,31 @@ Moduli
 ******
 
 .[perex]
-In Nette, i moduli rappresentano le unità logiche che compongono un'applicazione. Comprendono presentatori, modelli, eventualmente anche componenti e classi di modelli.
+I moduli conferiscono chiarezza alle applicazioni Nette, facilitando la suddivisione in unità logiche.
 
-Una cartella per i presentatori e una per i modelli non sarebbe sufficiente per i progetti reali. Avere decine di file in una cartella è quantomeno disorganizzato. Come uscirne? Semplicemente dividendoli in sottodirectory su disco e in spazi dei nomi nel codice. E questo è esattamente ciò che fanno i moduli Nette.
-
-Dimentichiamo quindi un'unica cartella per i presentatori e i modelli e creiamo invece dei moduli, ad esempio `Admin` e `Front`.
+Analogamente all'organizzazione dei file in cartelle su un disco rigido, in Nette possiamo dividere presentatori, modelli e altre classi ausiliarie in moduli. Come funziona in pratica? Semplicemente incorporando nuove sottodirectory nella struttura. Ecco un esempio di struttura con due moduli, Front e Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Questa struttura di cartelle si rifletterà negli spazi dei nomi delle classi, quindi ad esempio `DashboardPresenter` sarà nello spazio dei nomi `App\Modules\Admin\Presenters`:
+Questa struttura di directory si riflette negli spazi dei nomi delle classi, per cui, ad esempio, `DashboardPresenter` si trova nello spazio dei nomi `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Il presentatore `Dashboard` all'interno del modulo `Admin` è referenziato all'interno dell'applicazione usando la notazione dei due punti come `Admin:Dashboard`, e la sua azione `default` come `Admin:Dashboard:default`.
-E come fa Nette a sapere che `Admin:Dashboard` rappresenta la classe `App\Modules\Admin\Presenters\DashboardPresenter`? Questo è determinato dalla [mappatura |#mapping] nella configurazione.
-Pertanto, la struttura data non è rigida e può essere modificata in base alle proprie esigenze.
+Nell'applicazione, ci si riferisce al presentatore `Dashboard` all'interno del modulo `Admin` usando la notazione dei due punti come `Admin:Dashboard`. Per l'azione `default`, ci si riferisce ad essa come `Admin:Dashboard:default`.
+
+La struttura presentata non è rigida; è possibile [personalizzarla completamente in base alle proprie esigenze |#mapping] nella configurazione. .[tip]
 
-I moduli possono naturalmente contenere tutti gli altri elementi oltre ai presentatori e ai modelli, come componenti, classi di modelli, ecc.
+I moduli possono includere tutti gli altri file, come i componenti e le classi ausiliarie, oltre ai presentatori e ai modelli. Se si sta valutando dove collocare questi ultimi, si può prendere in considerazione l'uso di una cartella `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Moduli annidati .[#toc-nested-modules]
 --------------------------------------
 
-I moduli non devono formare solo una struttura piatta, ma si possono anche creare sottomoduli, ad esempio:
+I moduli possono avere più livelli di annidamento, simili a una struttura di directory su disco:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Così, il modulo `Blog` è suddiviso nei sottomoduli `Admin` e `Front`. Anche in questo caso, ciò si rifletterà negli spazi dei nomi, che saranno `App\Modules\Blog\Admin\Presenters` e così via. Il presentatore `Dashboard` all'interno del sottomodulo viene chiamato `Blog:Admin:Dashboard`.
+Il modulo `Blog` è diviso nei sottomoduli `Admin` e `Front`. Questo si riflette anche negli spazi dei nomi, che appaiono come `App\UI\Blog\Admin` e simili. Per riferirsi al presentatore `Dashboard` all'interno del sottomodulo `Admin`, ci si riferisce ad esso come `Blog:Admin:Dashboard`.
+
+L'annidamento può essere profondo quanto necessario, consentendo la creazione di sottomoduli.
 
-L'annidamento può andare in profondità quanto si vuole, quindi si possono creare dei sottomoduli.
+Ad esempio, se nell'amministrazione sono presenti molti presentatori relativi alla gestione degli ordini, come `OrderDetail`, `OrderEdit`, `OrderDispatch`, ecc. si può creare un modulo `Order` in cui saranno organizzati presentatori come `Detail`, `Edit`, `Dispatch`, e altri.
 
 
 Creazione di collegamenti .[#toc-creating-links]
@@ -102,47 +118,66 @@ Vedere il [capitolo sull'instradamento |routing#Modules].
 Mappatura .[#toc-mapping]
 -------------------------
 
-Definisce le regole con cui il nome della classe viene derivato dal nome del presentatore. Vengono scritte nella [configurazione |configuration] sotto la chiave `application › mapping`.
+La mappatura definisce le regole per derivare il nome della classe dal nome del presentatore. Queste regole sono specificate nella [configurazione |configuration] sotto la chiave `application › mapping`.
 
-Cominciamo con un esempio che non usa moduli. Vogliamo solo che le classi del presentatore abbiano lo spazio dei nomi `App\Presenters`. Ciò significa che un presentatore come `Home` deve mappare alla classe `App\Presenters\HomePresenter`. Questo si può ottenere con la seguente configurazione:
+Le strutture di directory menzionate in precedenza in questa pagina si basano sulla seguente mappatura:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Il nome del presentatore viene sostituito con l'asterisco nella maschera della classe e il risultato è il nome della classe. Facile!
+Come funziona la mappatura? Per capire meglio, immaginiamo prima un'applicazione senza moduli. Vogliamo che le classi del presentatore rientrino nello spazio dei nomi `App\UI`, in modo che il presentatore `Home` sia mappato nella classe `App\UI\HomePresenter`. Ciò può essere ottenuto con questa configurazione:
 
-Se dividiamo i presentatori in moduli, possiamo avere la nostra mappatura per ogni modulo:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Questa mappatura funziona sostituendo l'asterisco nella maschera `App\UI\*Presenter` con il nome del presenter `Home`, ottenendo il nome finale della classe `App\UI\HomePresenter`. Semplice!
+
+Tuttavia, come si può vedere negli esempi di questo e di altri capitoli, le classi dei presentatori sono collocate in sottodirectory eponime, ad esempio il presentatore `Home` è mappato nella classe `App\UI\Home\HomePresenter`. Questo si ottiene raddoppiando l'asterisco (richiede Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Passiamo ora alla mappatura dei presentatori nei moduli. Possiamo definire mappature specifiche per ogni modulo:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Ora il presentatore `Front:Home` mappa alla classe `App\Modules\Front\Presenters\HomePresenter` e il presentatore `Admin:Dashboard` alla classe `App\Modules\Admin\Presenters\DashboardPresenter`.
+In base a questa configurazione, il presentatore `Front:Home` si riferisce alla classe `App\UI\Front\Home\HomePresenter`, mentre il presentatore `Api:OAuth` si riferisce alla classe `App\Api\OAuthPresenter`.
 
-È più pratico creare una regola generale (asterisco) per sostituire le prime due. L'asterisco in più sarà aggiunto alla maschera di classe solo per il modulo:
+Poiché i moduli `Front` e `Admin` hanno un approccio di mappatura simile e probabilmente ci saranno altri moduli di questo tipo, è possibile creare una regola generale che li sostituisca. Un nuovo asterisco per il modulo viene aggiunto alla maschera della classe:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Ma cosa succede se utilizziamo moduli annidati e abbiamo un presentatore `Admin:User:Edit`? In questo caso, il segmento con l'asterisco che rappresenta il modulo per ogni livello viene semplicemente ripetuto e il risultato è la classe `App\Modules\Admin\User\Presenters\EditPresenter`.
+Per i moduli annidati a più livelli, come il presentatore `Admin:User:Edit`, il segmento dell'asterisco si ripete per ogni livello, dando luogo alla classe `App\UI\Admin\User\Edit\EditPresenter`.
 
 Una notazione alternativa consiste nell'utilizzare un array composto da tre segmenti invece di una stringa. Questa notazione è equivalente alla precedente:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Il valore predefinito è `*: *Module\*Presenter`.
+Se abbiamo una sola regola nella configurazione, quella generale, possiamo scrivere brevemente:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/it/presenters.texy b/application/it/presenters.texy
index 687f5d900c..7f12f07c7f 100644
--- a/application/it/presenters.texy
+++ b/application/it/presenters.texy
@@ -60,7 +60,7 @@ Simile al metodo `render<View>()`. Mentre `render<View>()` è destinato a prepar
 
 È importante che `action<Action>()` sia chiamato prima di `render<View>()`quindi al suo interno si può eventualmente modificare il corso successivo del ciclo di vita, cioè cambiare il template che sarà reso e anche il metodo `render<View>()` che sarà chiamato, utilizzando `setView('otherView')`.
 
-I parametri della richiesta vengono passati al metodo. È possibile e consigliabile specificare i tipi di parametri, ad esempio `actionShow(int $id, string $slug = null)` - se il parametro `id` manca o non è un intero, il presentatore restituisce l'[errore 404 |#Error 404 etc.] e termina l'operazione.
+I parametri della richiesta vengono passati al metodo. È possibile e consigliabile specificare i tipi di parametri, ad esempio `actionShow(int $id, ?string $slug = null)` - se il parametro `id` manca o non è un intero, il presentatore restituisce l'[errore 404 |#Error 404 etc.] e termina l'operazione.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ Nel modello, questi messaggi sono disponibili nella variabile `$flashes` come og
 Errore 404 ecc. .[#toc-error-404-etc]
 =====================================
 
-Quando non possiamo soddisfare la richiesta, perché ad esempio l'articolo che vogliamo visualizzare non esiste nel database, lanceremo l'errore 404 usando il metodo `error(string $message = null, int $httpCode = 404)`, che rappresenta l'errore HTTP 404:
+Quando non possiamo soddisfare la richiesta, perché ad esempio l'articolo che vogliamo visualizzare non esiste nel database, lanceremo l'errore 404 usando il metodo `error(?string $message = null, int $httpCode = 404)`, che rappresenta l'errore HTTP 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parametri di richiesta .[#toc-request-parameters]
+=================================================
+
+Il presentatore, così come ogni componente, ottiene i suoi parametri dalla richiesta HTTP. I loro valori possono essere recuperati con il metodo `getParameter($name)` o `getParameters()`. I valori sono stringhe o array di stringhe, essenzialmente dati grezzi ottenuti direttamente dall'URL.
+
+Per maggiore comodità, si consiglia di rendere i parametri accessibili tramite proprietà. È sufficiente annotarli con l'attributo `#[Parameter]` attributo:
+
+```php
+use Nette\Application\Attributes\Parameter;  // questa linea è importante
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // deve essere pubblica
+}
+```
+
+Per le proprietà, si consiglia di specificare il tipo di dati (ad esempio, `string`). Nette calcolerà automaticamente il valore in base ad esso. Anche i valori dei parametri possono essere [convalidati |#Validation of Parameters].
+
+Quando si crea un collegamento, è possibile impostare direttamente il valore dei parametri:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Parametri persistenti .[#toc-persistent-parameters]
 ===================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Se `$this->lang` ha un valore come `'en'`, i link creati con `link()` o `n:href` conterranno anche il parametro `lang=en`. E quando il link viene cliccato, sarà di nuovo `$this->lang = 'en'`.
 
-Per le proprietà, si consiglia di includere il tipo di dati (ad esempio, `string`) e si può anche includere un valore predefinito. I valori dei parametri possono essere [convalidati |#Validation of Persistent Parameters].
+Per le proprietà, si consiglia di includere il tipo di dati (ad esempio, `string`) e si può anche includere un valore predefinito. I valori dei parametri possono essere [convalidati |#Validation of Parameters].
 
 I parametri persistenti vengono passati per impostazione predefinita tra tutte le azioni di un determinato presentatore. Per passarli tra più presentatori, è necessario definirli:
 
@@ -307,18 +333,12 @@ Approfondimento .[#toc-going-deeper]
 Quanto mostrato finora in questo capitolo sarà probabilmente sufficiente. Le righe che seguono sono destinate a chi è interessato ad approfondire i presentatori e vuole sapere tutto.
 
 
-Requisiti e parametri .[#toc-requirement-and-parameters]
+Convalida dei parametri .[#toc-validation-of-parameters]
 --------------------------------------------------------
 
-La richiesta gestita dal presentatore è l'oggetto [api:Nette\Application\Request] e viene restituita dal metodo del presentatore `getRequest()`. Include un array di parametri e ognuno di essi appartiene o a qualche componente o direttamente al presentatore (che in realtà è anch'esso un componente, anche se speciale). Quindi Nette ridistribuisce i parametri e passa tra i singoli componenti (e il presentatore) chiamando il metodo `loadState(array $params)`. I parametri possono essere ottenuti con il metodo `getParameters(): array`, singolarmente con `getParameter($name)`. I valori dei parametri sono stringhe o array di stringhe, in pratica dati grezzi ottenuti direttamente da un URL.
+I valori dei [parametri della richiesta |#request parameters] e dei [parametri persistenti |#persistent parameters] ricevuti dagli URL vengono scritti nelle proprietà dal metodo `loadState()`. Il metodo controlla anche se il tipo di dati specificato nella proprietà corrisponde, altrimenti risponde con un errore 404 e la pagina non viene visualizzata.
 
-
-Convalida dei parametri persistenti .[#toc-validation-of-persistent-parameters]
--------------------------------------------------------------------------------
-
-I valori dei [parametri persistenti |#persistent parameters] ricevuti dagli URL vengono scritti nelle proprietà dal metodo `loadState()`. Il metodo controlla anche se il tipo di dati specificato nella proprietà corrisponde, altrimenti risponde con un errore 404 e la pagina non viene visualizzata.
-
-Non fidarsi mai ciecamente dei parametri persistenti, perché possono essere facilmente sovrascritti dall'utente nell'URL. Ad esempio, è così che si controlla se `$this->lang` è tra le lingue supportate. Un buon modo per farlo è sovrascrivere il metodo `loadState()` citato in precedenza:
+Non fidarsi mai ciecamente dei parametri, perché possono essere facilmente sovrascritti dall'utente nell'URL. Ad esempio, è così che controlliamo se `$this->lang` è tra le lingue supportate. Un buon modo per farlo è sovrascrivere il metodo `loadState()` citato in precedenza:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Salvare e ripristinare la richiesta .[#toc-save-and-restore-the-request]
 ------------------------------------------------------------------------
 
-È possibile salvare la richiesta corrente in una sessione o ripristinarla dalla sessione e lasciare che il presentatore la esegua di nuovo. Ciò è utile, ad esempio, quando un utente compila un modulo e il suo login scade. Per non perdere i dati, prima di reindirizzare alla pagina di accesso, salviamo la richiesta corrente nella sessione usando `$reqId = $this->storeRequest()`, che restituisce un identificatore sotto forma di stringa breve e lo passa come parametro al presentatore dell'accesso.
+La richiesta che il presentatore gestisce è un oggetto [api:Nette\Application\Request] e viene restituita dal metodo del presentatore `getRequest()`.
+
+È possibile salvare la richiesta corrente in una sessione o ripristinarla dalla sessione e lasciare che il presentatore la esegua di nuovo. Ciò è utile, ad esempio, quando un utente compila un modulo e il suo login scade. Per non perdere i dati, prima di reindirizzare alla pagina di accesso, salviamo la richiesta corrente nella sessione con il metodo `$reqId = $this->storeRequest()`, che restituisce un identificatore sotto forma di stringa breve e lo passa come parametro al presentatore di accesso.
 
 Dopo l'accesso, chiamiamo il metodo `$this->restoreRequest($reqId)`, che preleva la richiesta dalla sessione e la inoltra ad essa. Il metodo verifica che la richiesta sia stata creata dallo stesso utente che ha effettuato l'accesso. Se un altro utente accede o la chiave non è valida, non fa nulla e il programma continua.
 
@@ -362,7 +384,7 @@ Il reindirizzamento non avviene con una richiesta AJAX o POST, perché comporter
 Si può anche invocare la canonizzazione manualmente con il metodo `canonicalize()`, che, come il metodo `link()`, riceve come argomenti il presentatore, le azioni e i parametri. Crea un link e lo confronta con l'URL corrente. Se è diverso, reindirizza al link generato.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// reindirizza se $slug è diverso da $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Limitazione dell'accesso tramite `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+------------------------------------------------------------------------------------------------------------
+
+L'attributo `#[Requires]` fornisce opzioni avanzate per limitare l'accesso ai presentatori e ai loro metodi. Può essere usato per specificare metodi HTTP, richiedere richieste AJAX, limitare l'accesso alla stessa origine e limitare l'accesso al solo inoltro. L'attributo può essere applicato alle classi di presentatori e ai singoli metodi, come ad esempio `action<Action>()`, `render<View>()`, `handle<Signal>()`, e `createComponent<Name>()`.
+
+È possibile specificare queste restrizioni:
+- sui metodi HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- che richiedono una richiesta AJAX: `#[Requires(ajax: true)]`
+- accesso solo dalla stessa origine: `#[Requires(sameOrigin: true)]`
+- accesso solo tramite inoltro: `#[Requires(forward: true)]`
+- restrizioni su azioni specifiche: `#[Requires(actions: 'default')]`
+
+Per i dettagli, vedere [Come usare l'attributo Requires |best-practices:attribute-requires].
+
+
+Controllo del metodo HTTP .[#toc-http-method-check]
+---------------------------------------------------
+
+In Nette, i presentatori verificano automaticamente il metodo HTTP di ogni richiesta in arrivo, principalmente per motivi di sicurezza. Per impostazione predefinita, sono ammessi i metodi `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Se si desidera abilitare altri metodi, come ad esempio `OPTIONS`, è possibile utilizzare l'attributo `#[Requires]` (dall'applicazione Nette v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Nella versione 3.1, la verifica viene eseguita in `checkHttpMethod()`, che controlla se il metodo specificato nella richiesta è incluso nell'array `$presenter->allowedMethods`. Aggiungere un metodo come questo:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+È fondamentale sottolineare che se si abilita il metodo `OPTIONS`, è necessario gestirlo correttamente anche nel presenter. Questo metodo è spesso usato come una cosiddetta richiesta di preflight, che i browser inviano automaticamente prima della richiesta vera e propria quando è necessario determinare se la richiesta è consentita dal punto di vista della politica CORS (Cross-Origin Resource Sharing). Se si consente questo metodo ma non si implementa una risposta appropriata, si possono creare incongruenze e potenziali problemi di sicurezza.
+
+
 Ulteriori letture .[#toc-further-reading]
 =========================================
 
diff --git a/application/it/routing.texy b/application/it/routing.texy
index c01d4ac823..f938a3e902 100644
--- a/application/it/routing.texy
+++ b/application/it/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Notazione avanzata .[#toc-advanced-notation]
 --------------------------------------------
 
-Il secondo parametro della rotta, che spesso scriviamo nel formato `Presenter:action`, è un'abbreviazione, che possiamo scrivere anche sotto forma di campo, dove indichiamo direttamente i valori (predefiniti) dei singoli parametri:
+L'obiettivo di una rotta, solitamente scritto nella forma `Presenter:action`, può anche essere espresso utilizzando un array che definisce i singoli parametri e i loro valori predefiniti:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Oppure possiamo usare questa forma, notando la riscrittura dell'espressione regolare di validazione:
+Per una specifica più dettagliata, si può usare una forma ancora più estesa, in cui oltre ai valori predefiniti si possono impostare altre proprietà dei parametri, come un'espressione regolare di validazione (vedere il parametro `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Questi formati più loquaci sono utili per aggiungere altri metadati.
+È importante notare che se i parametri definiti nell'array non sono inclusi nella maschera del percorso, i loro valori non possono essere modificati, nemmeno utilizzando i parametri di query specificati dopo un punto interrogativo nell'URL.
 
 
 Filtri e traduzioni .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integrazione .[#toc-integration]
 ================================
 
-Per collegare il nostro router all'applicazione, dobbiamo comunicarlo al contenitore DI. Il modo più semplice è preparare il factory che costruirà l'oggetto router e dire al contenitore di configurazione di usarlo. Diciamo quindi di scrivere un metodo a questo scopo `App\Router\RouterFactory::createRouter()`:
+Per collegare il nostro router all'applicazione, dobbiamo comunicarlo al contenitore DI. Il modo più semplice è preparare il factory che costruirà l'oggetto router e dire al contenitore di configurazione di usarlo. Diciamo quindi di scrivere un metodo a questo scopo `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Poi scriviamo nella [configurazione |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Tutte le dipendenze, come la connessione al database, ecc. vengono passate al metodo factory come parametri, utilizzando l'[autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Per uso separato si intende l'uso delle funzionalità del router in un'applicazi
 Quindi creeremo di nuovo un metodo che costruirà un router, ad esempio:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Oppure creeremo direttamente gli oggetti:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/it/templates.texy b/application/it/templates.texy
index bb704a88f2..55e31fa8b9 100644
--- a/application/it/templates.texy
+++ b/application/it/templates.texy
@@ -34,35 +34,81 @@ E questo potrebbe essere il modello di azione:
 Definisce il blocco `content`, che viene inserito al posto di `{include content}` nel layout, e ridefinisce anche il blocco `title`, che sovrascrive `{block title}` nel layout. Provate a immaginare il risultato.
 
 
-Ricerca dei modelli .[#toc-search-for-templates]
-------------------------------------------------
+Ricerca di modelli .[#toc-template-lookup]
+------------------------------------------
+
+Nei presentatori, non è necessario specificare quale template debba essere reso; il framework determinerà automaticamente il percorso, semplificando la codifica.
+
+Se si utilizza una struttura di cartelle in cui ogni presentatore ha una propria cartella, è sufficiente posizionare il template in questa cartella sotto il nome dell'azione (cioè della vista). Ad esempio, per l'azione `default`, utilizzare il modello `default.latte`:
 
-Il percorso dei modelli viene dedotto secondo una semplice logica. Si cerca di vedere se uno di questi file di template esiste relativamente alla directory in cui si trova la classe del presentatore, dove `<Presenter>` è il nome del presentatore corrente e `<view>` è il nome dell'azione corrente:
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Se si utilizza una struttura in cui i presentatori sono riuniti in una directory e i modelli in una cartella `templates`, salvare il tutto in un file `<Presenter>.<view>.latte` oppure `<Presenter>/<view>.latte`:
 
-Se il modello non viene trovato, si cercherà nella cartella `templates` a un livello superiore, cioè allo stesso livello della cartella con la classe del presentatore.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
 
-Se il modello non viene trovato nemmeno lì, la risposta è un [errore 404 |presenters#Error 404 etc.].
+La directory `templates` può anche essere collocata un livello più in alto, allo stesso livello della directory con le classi dei presentatori.
 
-Si può anche cambiare la vista usando `$this->setView('otherView')`. Oppure, invece di cercare, specificare direttamente il nome del file del template usando `$this->template->setFile('/path/to/template.latte')`.
+Se il modello non viene trovato, il presentatore risponde con un [errore 404 - pagina non trovata |presenters#Error 404 etc].
+
+È possibile modificare la vista utilizzando `$this->setView('anotherView')`. È anche possibile specificare direttamente il file del modello con `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-È possibile modificare i percorsi in cui vengono cercati i modelli sovrascrivendo il metodo [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], che restituisce un array di possibili percorsi di file.
+I file in cui vengono cercati i modelli possono essere modificati sovrascrivendo il metodo [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], che restituisce un array di possibili nomi di file.
+
+
+Ricerca dei modelli di layout .[#toc-layout-template-lookup]
+------------------------------------------------------------
+
+Nette cerca automaticamente anche il file di layout.
+
+Se si utilizza una struttura di directory in cui ogni presentatore ha una propria directory, collocare il layout nella cartella del presentatore, se è specifico solo per lui, oppure a un livello superiore se è comune a più presentatori:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Se si utilizza una struttura in cui i presentatori sono raggruppati in una directory e i modelli si trovano in una cartella `templates`, il layout sarà previsto nei seguenti punti:
 
-Il layout è previsto nei seguenti file:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` layout comune a più presentatori
+Se il presentatore si trova in un [modulo |modules], cercherà anche più in alto nell'albero della directory, in base alla nidificazione del modulo.
 
-`<Presenter>` è il nome del presentatore corrente e `<layout>` è il nome del layout, che per impostazione predefinita è `'layout'`. Il nome può essere modificato con `$this->setLayout('otherLayout')`, in modo da provare i file `@otherLayout.latte`.
+Il nome del layout può essere modificato con `$this->setLayout('layoutAdmin')` e sarà previsto nel file `@layoutAdmin.latte`. È anche possibile specificare direttamente il file del modello di layout usando `$this->setLayout('/path/to/template.latte')`.
 
-È anche possibile specificare direttamente il nome del file del modello di layout con `$this->setLayout('/path/to/template.latte')`. L'uso di `$this->setLayout(false)` disabilita la ricerca dei layout.
+L'uso di `$this->setLayout(false)` o del tag `{layout none}` all'interno del template disabilita la ricerca del layout.
 
 .[note]
-È possibile modificare i percorsi in cui vengono cercati i modelli sovrascrivendo il metodo [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], che restituisce un array di possibili percorsi di file.
+I file in cui vengono cercati i modelli di layout possono essere modificati sovrascrivendo il metodo [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], che restituisce un array di possibili nomi di file.
 
 
 Variabili nel modello .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ L'annotazione `@property-read` è per l'IDE e l'analisi statica, farà funzionar
 Ci si può concedere il lusso di sussurrare anche nei template, basta installare il plugin Latte in PhpStorm e specificare il nome della classe all'inizio del template, si veda l'articolo "Latte: come digitare il sistema":https://blog.nette.org/it/latte-come-usare-il-sistema-di-tipi:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 La versione 3 di Latte offre un metodo più avanzato, creando un'[estensione |latte:creating-extension] per ogni progetto web. Ecco un esempio approssimativo di una classe di questo tipo:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ La registriamo usando [configuration |configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ In alternativa, il traduttore può essere impostato utilizzando la [configurazio
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Il traduttore può essere utilizzato, ad esempio, come filtro `|translate`, con parametri aggiuntivi passati al metodo `translate()` (vedere `foo, bar`):
diff --git a/application/pl/@home.texy b/application/pl/@home.texy
index 138c335e70..8d3e67e939 100644
--- a/application/pl/@home.texy
+++ b/application/pl/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | wersja zgodna z PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 - 8.2
-| Nette Application 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/pl/ajax.texy b/application/pl/ajax.texy
index 4b42eac748..9a6f09bd03 100644
--- a/application/pl/ajax.texy
+++ b/application/pl/ajax.texy
@@ -1,12 +1,12 @@
-AJAX i snippety
-***************
+AJAX i fragmenty
+****************
 
 <div class=perex>
 
-Nowoczesne aplikacje internetowe działają dziś w połowie na serwerze, w połowie w przeglądarce. AJAX jest kluczowym elementem łączącym. Jakie wsparcie oferuje Nette Framework?
-- Wysyłanie fragmentów szablonów
-- przekazywanie zmiennych między PHP a JavaScriptem
-- debugowanie aplikacji AJAX
+W dobie nowoczesnych aplikacji internetowych, w których funkcjonalność często rozciąga się między serwerem a przeglądarką, AJAX jest niezbędnym elementem łączącym. Jakie możliwości w tym zakresie oferuje Nette Framework?
+- wysyłanie części szablonu, tzw. snippetów
+- przekazywanie zmiennych między PHP i JavaScript
+- narzędzia do debugowania żądań AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ Nowoczesne aplikacje internetowe działają dziś w połowie na serwerze, w poł
 Żądanie AJAX .[#toc-ajax-request]
 =================================
 
-Żądanie AJAX nie różni się od klasycznego żądania - prezenter jest wywoływany z określonym widokiem i parametrami. Również od prezentera zależy, jak na nie odpowie: może użyć własnej procedury, która zwraca fragment kodu HTML (HTML snippet), dokument XML, obiekt JSON lub kod JavaScript.
+Żądanie AJAX zasadniczo nie różni się od klasycznego żądania HTTP. Prezenter jest wywoływany z określonymi parametrami. To od prezentera zależy, jak odpowie na żądanie - może zwrócić dane w formacie JSON, wysłać fragment kodu HTML, dokument XML itp.
 
-Po stronie serwera żądanie AJAX może zostać wykryte za pomocą metody serwisowej [obudowującej żądanie HTTP |http:request] `$httpRequest->isAjax()` (wykrywa na podstawie nagłówka HTTP `X-Requested-With`). Wewnątrz prezentera dostępny jest skrót w postaci metody `$this->isAjax()`.
+Po stronie przeglądarki inicjujemy żądanie AJAX za pomocą funkcji `fetch()`:
 
-Aby wysłać dane do przeglądarki w formacie JSON, możesz użyć gotowego obiektu `payload`:
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// przetwarzanie odpowiedzi
+});
 ```
 
-Jeśli potrzebujesz pełnej kontroli nad wysłanym JSON, użyj metody `sendJson` w prezenterze. Spowoduje to natychmiastowe zakończenie prezentera i zrezygnowanie z szablonu:
+Po stronie serwera żądanie AJAX jest rozpoznawane przez metodę `$httpRequest->isAjax()` usługi [hermetyzującej żądanie HTTP |http:request]. Używa ona nagłówka HTTP `X-Requested-With`, więc jest niezbędna do jego wysłania. W prezenterze można użyć metody `$this->isAjax()`.
+
+Jeśli chcesz wysłać dane w formacie JSON, użyj metody [`sendJson()` |presenters#Sending a response] . Metoda ta kończy również aktywność prezentera.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Jeśli chcemy wysłać HTML, możemy wybrać specjalny szablon dla AJAX:
+Jeśli planujesz odpowiedzieć za pomocą specjalnego szablonu zaprojektowanego dla AJAX, możesz to zrobić w następujący sposób:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Fragmenty .[#toc-snippets]
+==========================
+
+Najpotężniejszym narzędziem oferowanym przez Nette do łączenia serwera z klientem są snippety. Dzięki nim można przekształcić zwykłą aplikację w aplikację AJAX przy minimalnym wysiłku i kilku linijkach kodu. Przykład Fifteen pokazuje, jak to wszystko działa, a jego kod można znaleźć na [GitHubie |https://github.com/nette-examples/fifteen].
+
+Snippety lub wycinki pozwalają aktualizować tylko części strony, zamiast przeładowywać całą stronę. Jest to szybsze i bardziej wydajne, a także zapewnia wygodniejsze wrażenia użytkownika. Snippety mogą przypominać Hotwire dla Ruby on Rails lub Symfony UX Turbo. Co ciekawe, Nette wprowadziło snippety 14 lat wcześniej.
+
+Jak działają snippety? Kiedy strona jest ładowana po raz pierwszy (żądanie inne niż AJAX), ładowana jest cała strona, w tym wszystkie snippety. Gdy użytkownik wchodzi w interakcję ze stroną (np. klika przycisk, przesyła formularz itp.), zamiast ładowania całej strony, wykonywane jest żądanie AJAX. Kod w prezenterze wykonuje akcję i decyduje, które fragmenty wymagają aktualizacji. Nette renderuje te fragmenty i wysyła je w postaci tablicy JSON. Kod obsługi w przeglądarce wstawia następnie otrzymane fragmenty z powrotem na stronę. W związku z tym przesyłany jest tylko kod zmienionych fragmentów, co oszczędza przepustowość i przyspiesza ładowanie w porównaniu do przesyłania całej zawartości strony.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-[Biblioteka Naja |https://naja.js.org] służy do obsługi żądań AJAX po stronie przeglądarki. [Zainstaluj |https://naja.js.org/#/guide/01-install-setup-naja] go jako pakiet node.js (do użytku z Webpack, Rollup, Vite, Parcel i innych):
+Do obsługi snippetów po stronie przeglądarki używana jest [biblioteka Na |https://naja.js.org] ja. Należy [ją zainstal |https://naja.js.org/#/guide/01-install-setup-naja] ować jako pakiet node.js (do użytku z aplikacjami takimi jak Webpack, Rollup, Vite, Parcel i innymi):
 
 ```shell
 npm install naja
 ```
 
-...lub osadzić bezpośrednio w szablonie strony:
+... lub wstawić ją bezpośrednio do szablonu strony:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Aby utworzyć żądanie AJAX ze zwykłego linku (sygnału) lub submitu formularza, wystarczy oznaczyć odpowiedni link, formularz lub przycisk klasą `ajax`:
+Najpierw należy [zainicjować |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] bibliotekę:
+
+```js
+naja.initialize();
+```
+
+Aby uczynić zwykły link (sygnał) lub przesłanie formularza żądaniem AJAX, wystarczy oznaczyć odpowiedni link, formularz lub przycisk klasą `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Aby utworzyć żądanie AJAX ze zwykłego linku (sygnału) lub submitu formularz
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippets
-========
-
-Znacznie potężniejszym narzędziem jest wbudowana obsługa snippetów AJAX. Dzięki niemu można zamienić zwykłą aplikację w AJAXową za pomocą zaledwie kilku linijek kodu. Przykład Fifteen, którego kod można znaleźć na [GitHubie |https://github.com/nette-examples/fifteen], demonstruje jak to działa.
-
-Działanie snippetów polega na tym, że na początkowym (czyli nie-AJAX-owym) żądaniu przenoszona jest cała strona, a następnie na każdym [podżądaniu |components#Signal] AJAX-owym (= żądanie do tego samego prezentera i widoku) przenoszony jest tylko kod zmienionych fragmentów we wspomnianym repozytorium `payload`. Istnieją dwa mechanizmy tego działania: unieważnianie i renderowanie snippetów.
-
-Snippets mogą przypominać Hotwire dla Ruby on Rails lub Symfony UX Turbo, ale Nette wymyślił je czternaście lat wcześniej.
-
+Przerysowywanie fragmentów .[#toc-redrawing-snippets]
+-----------------------------------------------------
 
-Unieważnianie fragmentów .[#toc-invalidation-of-snippets]
-=========================================================
-
-Każdy obiekt klasy [Control |components] (którą jest sam Presenter) potrafi zapamiętać, czy w sygnale zaszły zmiany wymagające jego przerysowania. Służy do tego para metod `redrawControl()` i `isControlInvalid()`. Przykład:
+Każdy obiekt klasy [Control |components] (w tym sam Presenter) przechowuje informacje o tym, czy wystąpiły zmiany, które wymagają jego przerysowania. W tym celu wykorzystywana jest metoda `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// po zalogowaniu się użytkownika obiekt musi zostać przerysowany
+	// po zalogowaniu konieczne jest przerysowanie odpowiedniego fragmentu
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette oferuje jednak jeszcze dokładniejszą rozdzielczość niż na poziomie komponentów. Metody te mogą przyjąć jako argument nazwę "snippet", czyli wycinka. Możliwe jest więc unieważnienie (czyli wymuszenie przerysowania) na poziomie tych wycinków (każdy obiekt może mieć dowolną liczbę wycinków). Jeśli cały komponent zostanie unieważniony, każdy wycinek zostanie przerysowany. Komponent jest "unieważniony" nawet jeśli podkomponent jest unieważniony.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // unieważnia snippet 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> prawda, przynajmniej jeden fragment jest nieprawidłowy
+Nette pozwala również na dokładniejszą kontrolę tego, co wymaga przerysowania. Wspomniana metoda może przyjąć nazwę fragmentu jako argument. W ten sposób możliwe jest unieważnienie (czyli wymuszenie przerysowania) na poziomie części szablonu. Jeśli cały komponent zostanie unieważniony, każdy jego fragment zostanie również przerysowany:
 
-$this->redrawControl(); // unieważnia cały komponent, każdy fragment
-$this->isControlInvalid('footer'); // -> true
+```php
+// unieważnia fragment "nagłówka
+$this->redrawControl('header');
 ```
 
-Komponent, który otrzymuje sygnał, jest automatycznie oznaczany jako wyłączony.
-
-Unieważniając snippety, wiemy dokładnie, które części których elementów będą musiały zostać przerysowane.
-
-
-Tagi `{snippet} … {/snippet}` .{toc: Tag snippet}
-=================================================
-
-Renderowanie strony jest bardzo podobne do normalnego żądania: ładowane są te same szablony itp. Ważne jest jednak pominięcie części, które nie powinny być wyprowadzane; pozostałe części są przypisywane do identyfikatora i wysyłane do użytkownika w formacie zrozumiałym dla JavaScript handler.
-
 
-Składnia .[#toc-syntax]
------------------------
+Snippety w Latte .[#toc-snippets-in-latte]
+------------------------------------------
 
-Jeśli wewnątrz szablonu znajduje się kontrolka lub snippet, musimy owinąć go znacznikiem `{snippet} ... {/snippet}` para - zapewniają one wycięcie wyrenderowanego snippetu i wysłanie go do przeglądarki. Zawija go również za pomocą tagu pomocniczego `<div>` z wygenerowanym `id`. W powyższym przykładzie snippet nosi nazwę `header` i może również reprezentować np. szablon kontrolny:
+Używanie snippetów w Latte jest niezwykle proste. Aby zdefiniować część szablonu jako snippet, wystarczy zawinąć go w znaczniki `{snippet}` i `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Jeśli wewnątrz szablonu znajduje się kontrolka lub snippet, musimy owinąć g
 {/snippet}
 ```
 
-Fragment o typie innym niż `<div>` lub snippet z dodatkowymi atrybutami HTML uzyskuje się poprzez zastosowanie wariantu atrybutów:
+Snippet tworzy element `<div>` na stronie HTML ze specjalnie wygenerowanym `id`. Podczas przerysowywania fragmentu zawartość tego elementu jest aktualizowana. Dlatego też, gdy strona jest początkowo renderowana, wszystkie snippety muszą być również renderowane, nawet jeśli początkowo mogą być puste.
+
+Można również utworzyć snippet z elementem innym niż `<div>` używając atrybutu n:attribute:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Fragment o typie innym niż `<div>` lub snippet z dodatkowymi atrybutami HTML uz
 ```
 
 
-Dynamiczne fragmenty .[#toc-dynamic-snippets]
-=============================================
+Obszary wycinków .[#toc-snippet-areas]
+--------------------------------------
 
-Nette pozwala również na stosowanie snippetów, których nazwa jest tworzona w czasie biegu - czyli dynamicznie. Jest to przydatne w przypadku różnych list, gdzie przy zmianie jednego wiersza nie chcemy AJAXować całej listy, a jedynie sam wiersz. Przykład:
+Nazwy fragmentów mogą być również wyrażeniami:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Mamy tu statyczny snippet `itemsContainer`, zawierający kilka dynamicznych snippetów `item-0`, `item-1` itd.
+W ten sposób otrzymamy kilka snippetów, takich jak `item-0`, `item-1`, itd. Gdybyśmy bezpośrednio unieważnili dynamiczny snippet (np. `item-1`), nic nie zostałoby przerysowane. Powodem jest to, że snippety działają jako prawdziwe fragmenty i tylko one są renderowane bezpośrednio. Jednak w szablonie nie ma technicznie snippetu o nazwie `item-1`. Pojawia się on dopiero podczas wykonywania otaczającego kodu snippetu, w tym przypadku pętli foreach. Dlatego część szablonu, która musi zostać wykonana, oznaczymy tagiem `{snippetArea}`:
 
-Nie można bezpośrednio unieważnić dynamicznych snippetów (unieważnienie `item-1` nic nie daje), trzeba unieważnić ich nadrzędny statyczny snippet (tutaj snippet `itemsContainer`). Wówczas cały kod kontenera zostanie wykonany, ale do przeglądarki zostaną wysłane tylko jego podkontenerowe snippety. Jeśli chcesz, aby przeglądarka otrzymała tylko jeden z nich, musisz zmodyfikować dane wejściowe tego kontenera, aby nie generował pozostałych.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-W powyższym przykładzie musisz po prostu upewnić się, że gdy wykonasz żądanie ajaxowe, w zmiennej `$list` znajduje się tylko jeden wpis, a zatem, że pętla `foreach` wypełnia tylko jeden dynamiczny snippet:
+I przerysujemy zarówno pojedynczy snippet, jak i cały obszar nadrzędny:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * Tato metoda vrací data pro seznam.
-	 * Obvykle se jedná pouze o vyžádání dat z modelu.
-	 * Pro účely tohoto příkladu jsou data zadána natvrdo.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'První',
-			'Druhý',
-			'Třetí',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Ważne jest również, aby upewnić się, że tablica `$items` zawiera tylko elementy, które powinny zostać przerysowane.
 
-Snippety w dołączonym szablonie .[#toc-snippets-in-an-included-template]
-========================================================================
-
-Może się zdarzyć, że w jakimś szablonie mamy snippet, który dopiero chcemy włączyć do innego szablonu. W tym przypadku musimy owinąć osadzenie tego szablonu znacznikami `snippetArea`, które następnie unieważniamy wraz z samym snippetem.
-
-Znaczniki `snippetArea` gwarantują, że kod osadzający szablon zostanie wykonany, ale do przeglądarki zostanie wysłany tylko wycinek z osadzanego szablonu.
+Podczas wstawiania innego szablonu do szablonu głównego za pomocą znacznika `{include}`, który zawiera snippety, konieczne jest ponowne zawinięcie dołączonego szablonu w `snippetArea` i unieważnienie zarówno snippetu, jak i obszaru razem:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Takie podejście może być również stosowane w połączeniu z dynamicznymi snippetami.
 
+Snippety w komponentach .[#toc-snippets-in-components]
+------------------------------------------------------
 
-Dodawanie i usuwanie .[#toc-adding-and-deleting]
-================================================
-
-Jeśli dodasz nowy element i unieważnisz `itemsContainer`, to żądanie AJAX zwróci również nowy snippet, ale handler javascript nie może go nigdzie przypisać. W rzeczywistości na stronie nie ma jeszcze elementu HTML o tym identyfikatorze.
-
-W takim przypadku najłatwiej jest owinąć całą listę jeszcze jednym snippetem i unieważnić całość:
+Możesz tworzyć fragmenty w [komponentach |components], a Nette automatycznie je przerysuje. Istnieje jednak pewne ograniczenie: aby przerysować snippety, Nette wywołuje metodę `render()` bez żadnych parametrów. Zatem przekazywanie parametrów w szablonie nie będzie działać:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Wysyłanie danych użytkownika .[#toc-sending-user-data]
+------------------------------------------------------
+
+Wraz ze snippetami można wysyłać do klienta dowolne dodatkowe dane. Wystarczy zapisać je w obiekcie `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-To samo tyczy się usuwania. Można by jakoś wysłać pusty snippet, ale w praktyce większość list jest paginowana i byłoby to zbyt skomplikowane, aby bardziej ekonomicznie usunąć jeden plus ewentualnie załadować inny (który nie pasował wcześniej).
-
 
-Wysyłanie parametrów do komponentu .[#toc-sending-parameters-to-component]
-==========================================================================
+Wysyłanie parametrów .[#toc-sending-parameters]
+===============================================
 
-Jeśli wysyłamy parametry do komponentu za pomocą żądania AJAX, zarówno parametry sygnałowe, jak i parametry trwałe, musimy określić ich globalną nazwę w żądaniu, które zawiera nazwę komponentu. Pełna nazwa parametru jest zwracana przez metodę `getParameterId()`.
+Gdy wysyłamy parametry do komponentu za pośrednictwem żądania AJAX, niezależnie od tego, czy są to parametry sygnału, czy parametry trwałe, musimy podać ich globalną nazwę, która zawiera również nazwę komponentu. Pełną nazwę parametru zwraca metoda `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Metoda handle z odpowiednimi parametrami w komponencie.
+Metoda uchwytu z odpowiednimi parametrami w komponencie:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/pl/bootstrap.texy b/application/pl/bootstrap.texy
index 3fb6475d75..084d93b416 100644
--- a/application/pl/bootstrap.texy
+++ b/application/pl/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Konfigurator jest odpowiedzialny za konfigurację środowiska aplikacji i usług.
+		$this->configurator = new Configurator;
+		// Ustawienie katalogu dla plików tymczasowych generowanych przez Nette (np. skompilowanych szablonów).
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette jest inteligentny i tryb deweloperski włącza się automatycznie,
+		// lub można go włączyć dla określonego adresu IP, odkomentowując następującą linię:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Włącza Tracy: najlepsze narzędzie do debugowania.
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: automatycznie ładuje wszystkie klasy w podanym katalogu
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Ładowanie plików konfiguracyjnych
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Podstawowym plikiem w przypadku aplikacji internetowych jest `index.php`, który znajduje się w katalogu publicznym `www/`. Spowoduje to, że klasa Bootstrap zainicjuje środowisko i zwróci `$configurator`, a następnie wyprodukuje kontener DI. Następnie pobiera z niego usługę `Application`, która uruchamia aplikację internetową:
+Początkowym plikiem dla aplikacji internetowych jest `index.php`, znajdujący się w publicznym katalogu `www/`. Używa on klasy `Bootstrap` do zainicjowania środowiska i utworzenia kontenera DI. Następnie uzyskuje usługę `Application` z kontenera, który uruchamia aplikację internetową:
 
 ```php
-// inicjalizacja środowiska + uzyskanie obiektu Configurator
-$configurator = App\Bootstrap::boot();
-// tworzenie kontenera DI
-$container = $configurator->createContainer();
-// Kontener DI tworzy obiekt "Nette
+$bootstrap = new App\Bootstrap;
+// Inicjalizacja środowiska + utworzenie kontenera DI
+$container = $bootstrap->bootWebApplication();
+// Kontener DI tworzy obiekt Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// uruchomienie aplikacji Nette
+// Uruchom aplikację Nette i obsłuż przychodzące żądanie
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Wybór trybu odbywa się poprzez autodetekcję, więc zazwyczaj nie ma potrzeby
 Jeśli chcemy włączyć tryb deweloperski w innych przypadkach, takich jak programiści uzyskujący dostęp z określonego adresu IP, używamy `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // można również określić pole adresu IP
+$this->configurator->setDebugMode('23.75.345.200'); // można również określić pole adresu IP
 ```
 
 Zdecydowanie zalecamy połączenie adresu IP z plikiem cookie. W pliku cookie `nette-debug` przechowujemy tajny token, np. `secret1234`, i w ten sposób umożliwiamy tryb deweloperski dla programistów uzyskujących dostęp z określonego adresu IP i posiadających token w pliku cookie:
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Możemy również całkowicie wyłączyć tryb deweloperski, nawet dla localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Uwaga, wartość `true` domyślnie włącza tryb deweloperski, co nigdy nie może mieć miejsca na serwerze produkcyjnym.
@@ -90,7 +115,7 @@ Narzędzie do debugowania Tracy .[#toc-debugging-tool-tracy]
 Aby ułatwić debugowanie, włączmy wspaniałe narzędzie [Tracy |tracy:]. Wizualizuje błędy w trybie deweloperskim i loguje błędy w trybie produkcyjnym do podanego katalogu:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Pliki tymczasowe .[#toc-temporary-files]
 Nette używa buforowania dla kontenera DI, RobotLoader, szablonów itp. Dlatego musisz ustawić ścieżkę do katalogu, w którym będzie przechowywany cache:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 W systemach Linux lub macOS ustaw katalogi `log/` i `temp/` na uprawnienia do [zapisu |nette:troubleshooting#Setting-Directory-Permissions].
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Zazwyczaj będziemy chcieli automatycznie załadować klasy za pomocą [RobotLoader |robot-loader:], więc musimy go uruchomić i kazać mu załadować klasy z katalogu, w którym znajduje się `Bootstrap.php` (czyli `__DIR__`), oraz z wszelkich podkatalogów:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Strefa czasowa .[#toc-timezone]
 Domyślną strefę czasową można ustawić za pośrednictwem konfiguratora.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ W trybie deweloperskim kontener jest automatycznie aktualizowany przy każdej zm
 Pliki konfiguracyjne są ładowane za pomocą `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Jeśli chcemy dodać więcej plików konfiguracyjnych, możemy wywołać funkcję `addConfig()` wielokrotnie.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Parametry statyczne .[#toc-static-parameters]
 Parametry wykorzystywane w plikach konfiguracyjnych można zdefiniować [w sekcji `parameters` |dependency-injection:configuration#parameters], a także przekazać (lub nadpisać) za pomocą metody `addStaticParameters()` (posiada ona alias `addParameters()`). Co ważne, różne wartości parametrów spowodują wygenerowanie dodatkowych kontenerów DI, czyli dodatkowych klas.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Parametry dynamiczne .[#toc-dynamic-parameters]
 Do kontenera możemy również dodać parametry dynamiczne, których różne wartości, w przeciwieństwie do parametrów statycznych, nie będą powodowały generowania nowych kontenerów DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Możemy po prostu dodać np. zmienne środowiskowe, do których następnie możemy się odwołać w konfiguracji pisząc `%env.variable%`.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ W plikach konfiguracyjnych można używać następujących parametrów statyczny
 - `%wwwDir%` jest bezwzględną ścieżką do katalogu zawierającego plik wejściowy `index.php`
 - `%tempDir%` jest bezwzględną ścieżką do katalogu plików tymczasowych
 - `%vendorDir%` to bezwzględna ścieżka do katalogu, w którym Composer instaluje biblioteki
+- `%rootDir%` to bezwzględna ścieżka do katalogu głównego projektu
 - `%debugMode%` wskazuje, czy aplikacja jest w trybie debugowania
 - `%consoleMode%` wskazuje, czy żądanie przyszło z linii poleceń
 
@@ -225,7 +252,7 @@ services:
 A w bootstrapie wstawiamy obiekt do kontenera:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Różne środowiska .[#toc-different-environments]
 ===============================================
 
-Zapraszamy do dostosowania klasy Bootstrap do swoich potrzeb. Możesz dodać parametry do metody `boot()`, aby odróżnić projekty internetowe, lub dodać inne metody, takie jak `bootForTests()`, która inicjalizuje środowisko dla testów jednostkowych, `bootForCli()` dla skryptów wywoływanych z linii poleceń itp.
+Nie wahaj się dostosować klasy `Bootstrap` do swoich potrzeb. Możesz dodać parametry do metody `bootWebApplication()`, aby rozróżnić projekty internetowe. Alternatywnie można dodać inne metody, takie jak `bootTestEnvironment()` do inicjalizacji środowiska dla testów jednostkowych, `bootConsoleApplication()` dla skryptów wywoływanych z wiersza poleceń itp.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Inicjalizacja testera sieci
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // inicializace Nette Testeru
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/pl/components.texy b/application/pl/components.texy
index 9a279ce4c5..21cbd673e9 100644
--- a/application/pl/components.texy
+++ b/application/pl/components.texy
@@ -230,6 +230,28 @@ Do szablonu wiadomości te są dostępne w zmiennej `$flashes` jako obiekty `std
 ```
 
 
+Przekierowanie po sygnale .[#toc-redirection-after-a-signal]
+============================================================
+
+Po przetworzeniu sygnału komponentu często następuje przekierowanie. Sytuacja ta jest podobna do formularzy - po przesłaniu formularza również przekierowujemy, aby zapobiec ponownemu przesłaniu danych po odświeżeniu strony w przeglądarce.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Ponieważ komponent jest elementem wielokrotnego użytku i zwykle nie powinien mieć bezpośredniej zależności od konkretnych prezenterów, metody `redirect()` i `link()` automatycznie interpretują parametr jako sygnał komponentu:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Jeśli konieczne jest przekierowanie do innego prezentera lub akcji, można to zrobić za pośrednictwem prezentera:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Trwałe parametry .[#toc-persistent-parameters]
 ==============================================
 
@@ -347,7 +369,7 @@ services:
 i w końcu użyć go w naszym prezenterze:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Komponenty w głębi .[#toc-advanced-use-of-components]
 Komponenty w aplikacji Nette to części aplikacji internetowej wielokrotnego użytku, które osadzamy w stronach, co jest tematem tego rozdziału. Jakie dokładnie są możliwości takiego komponentu?
 
 1) Jest renderowalny w szablonie
-2) wie, która część siebie ma być renderowana podczas [żądania AJAX |ajax#Invalidation] (snippety)
+2) wie [, którą część siebie |ajax#snippets] renderować podczas żądania AJAX (snippets)
 3) ma możliwość przechowywania swojego stanu w URL (trwałe parametry)
 4) posiada zdolność do reagowania na działania (sygnały) użytkownika
 5) tworzy strukturę hierarchiczną (gdzie korzeniem jest prezenter)
@@ -430,7 +452,7 @@ class PaginatingControl extends Control
 }
 ```
 
-Procesem przeciwnym, czyli pobieraniem wartości z persistent properites, zajmuje się metoda `saveState()`.
+Procesem przeciwnym, czyli pobieraniem wartości z persistent properties, zajmuje się metoda `saveState()`.
 
 
 Sygnały w głąb .[#toc-signaly-do-hloubky]
diff --git a/application/pl/configuration.texy b/application/pl/configuration.texy
index 243df5360c..d59b60bb8e 100644
--- a/application/pl/configuration.texy
+++ b/application/pl/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# pokazać panel "Nette Application" w Tracy BlueScreen?
 	debugger: ...           # (bool) domyślnie jest true
 
-	# czy error-presenter zostanie wywołany na błędzie?
-	catchExceptions: ...    # (bool) domyślnie przyjmuje wartość true w trybie produkcyjnym
+	# czy error-presenter będzie wywoływany przy błędzie?
+	# działa tylko w trybie deweloperskim
+	catchExceptions: ...    # (bool) domyślnie true
 
 	# error-presenter name
-	errorPresenter: Error   # (string) domyślnie 'Nette:Error'
+	errorPresenter: Error   # (string|array) domyślnie 'Nette:Error'
+
+	# definiuje aliasy dla prezenterów i wydarzeń
+	aliases: ...
 
 	# definiuje zasady rozwiązywania nazwy prezentera do klasy
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) domyślnie jest false
 ```
 
-Ponieważ prezentery błędów nie są domyślnie wywoływane w trybie deweloperskim, a błąd jest wyświetlany tylko przez Tracy, zmiana wartości `catchExceptions` na `true` pozwala nam zweryfikować ich poprawną funkcjonalność w trakcie rozwoju.
+Od wersji `nette/application` 3.2 możliwe jest zdefiniowanie pary prezenterów błędów:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # dla wyjątku Nette\Application\BadRequestException
+		5xx: Error5xx   # dla innych wyjątków
+```
 
 Opcja `silentLinks` określa, jak Nette zachowuje się w trybie rozwoju, gdy generowanie linków nie powiedzie się (np. z powodu braku prezentera itp.). Domyślna wartość `false` oznacza, że Nette rzuci błąd `E_USER_WARNING`. Ustawienie go na `true` spowoduje wyeliminowanie tego komunikatu o błędzie. W środowisku produkcyjnym, `E_USER_WARNING` jest zawsze podniesiony. Na to zachowanie można również wpłynąć poprzez ustawienie zmiennej prezentera [$invalidLinkMode |creating-links#Invalid-Links].
 
+[Aliasy ułatwiają odwoływanie się do |creating-links#aliases] często używanych prezenterów.
+
 [Odwzorowanie określa zasady |modules#Mapping], według których nazwa klasy jest wyprowadzana z nazwy prezentera.
 
 
@@ -82,6 +95,9 @@ latte:
 	# włącza [sprawdzanie wygenerowanego kodu |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) domyślnie null
 
+	# ustawia ustawienia regionalne
+	locale: cs_CZ        # (string) domyślnie null
+
 	# klasa obiektów $this->template
 	templateClass: AppMyTemplateClass # domyślnie jest Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Jeśli używasz Latte w wersji 3, możesz dodać nowe [rozszerzenia |latte:creat
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/pl/creating-links.texy b/application/pl/creating-links.texy
index 5c9126dba0..23d1be2671 100644
--- a/application/pl/creating-links.texy
+++ b/application/pl/creating-links.texy
@@ -38,7 +38,7 @@ Możliwe jest również przekazywanie nazwanych parametrów. Poniższy link prze
 <a n:href="Product:show $product->id, lang: cs">detail produktu</a>
 ```
 
-Jeśli metoda `ProductPresenter::renderShow()` nie ma `$lang` w swojej sygnaturze, może pobrać wartość parametru za pomocą `$lang = $this->getParameter('lang')`.
+Jeśli metoda `ProductPresenter::renderShow()` nie ma w swojej sygnaturze `$lang`, może pobrać wartość parametru za pomocą `$lang = $this->getParameter('lang')` lub z [właściwości |presenters#Request Parameters].
 
 Jeśli parametry są przechowywane w tablicy, można je rozwinąć za pomocą operatora `...` (w Latte 2.x operator `(expand)`):
 
@@ -140,7 +140,7 @@ Cel `this` tworzy link do bieżącej strony:
 <a n:href="this">refresh</a>
 ```
 
-Wszystkie parametry określone w podpisie są również przekazywane `render<View>()` lub `action<Action>()` metody. Jeśli więc jesteśmy na `Product:show` i `id: 123`, to link do `this` również przekaże ten parametr.
+W tym samym czasie, wszystkie parametry określone w sygnaturze parametru `action<Action>()` lub `render<View>()` jeśli metoda `action<Action>()` nie są zdefiniowane, są przekazywane. Jeśli więc jesteśmy na stronach `Product:show` i `id:123`, link do `this` również przekaże ten parametr.
 
 Oczywiście istnieje możliwość bezpośredniego podania parametrów:
 
@@ -213,7 +213,7 @@ Ponieważ [komponenty |components] są samodzielnymi, wielokrotnego użytku jedn
 Gdybyśmy chcieli odwołać się do prezenterów w szablonie komponentu, użylibyśmy do tego celu tagu `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">úvod</a>
+<a href={plink Home:default}>home</a>
 ```
 
 lub w kodzie
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Pseudonimy .[#toc-aliases]{data-version:v3.2.2}
+===============================================
+
+Czasami przydatne jest przypisanie łatwego do zapamiętania aliasu do pary Presenter:action. Na przykład, można nazwać stronę główną `Front:Home:default` po prostu jako `home` lub `Admin:Dashboard:default` jako `admin`.
+
+Aliasy są definiowane w [konfiguracji |configuration] pod kluczem `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+W linkach są one zapisywane przy użyciu symbolu at, na przykład:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Są one obsługiwane we wszystkich metodach, które działają z linkami, takimi jak `redirect()` i podobne.
+
+
 Nieprawidłowe linki .[#toc-invalid-links]
 =========================================
 
diff --git a/application/pl/how-it-works.texy b/application/pl/how-it-works.texy
index fa65218c64..a2b0c8b57c 100644
--- a/application/pl/how-it-works.texy
+++ b/application/pl/how-it-works.texy
@@ -22,18 +22,18 @@ Struktura katalogów wygląda mniej więcej tak:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← adresář s aplikací
-│   ├── <b>Presenters/</b>           ← presentery a šablony
-│   │   ├── <b>HomePresenter.php</b> ← třída presenteru Home
-│   │   └── <b>templates/</b>        ← adresář se šablonami
-│   │       ├── <b>@layout.latte</b> ← šablona layoutu
-│   │       └── <b>Home/</b>         ← šablony presenteru Home
-│   │           └── <b>default.latte</b>  ← šablona akce 'default'
-│   ├── <b>Router/</b>               ← konfigurace URL adres
+│   ├── <b>Core/</b>                 ← podstawowe niezbędne klasy
+│   │   └── <b>RouterFactory.php</b> ← konfiguracja adresów URL
+│   ├── <b>UI/</b>                   ← prezentery, szablony & co.
+│   │   ├── <b>@layout.latte</b>     ← szablon udostępnionego layoutu
+│   │   └── <b>Home/</b>             ← Katalog główny prezentera
+│   │       ├── <b>HomePresenter.php</b> ← Klasa prezentera strony głównej
+│   │       └── <b>default.latte</b> ← szablon dla akcji default
 │   └── <b>Bootstrap.php</b>         ← zaváděcí třída Bootstrap
 ├── <b>bin/</b>                      ← skripty spouštěné z příkazové řádky
 ├── <b>config/</b>                   ← konfigurační soubory
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← logované chyby
 ├── <b>temp/</b>                     ← dočasné soubory, cache, …
 ├── <b>vendor/</b>                   ← knihovny instalované Composerem
@@ -91,7 +91,7 @@ Aplikacje napisane w Nette są podzielone na wiele prezenterów (w innych framew
 
 Aplikacja rozpoczyna się od zapytania tzw. routera o decyzję, do którego prezentera przekazać bieżące żądanie do przetworzenia. Router decyduje o tym, czyja to odpowiedzialność. Patrzy na wejściowy URL `https://example.com/product/123`, którego poprosi o wyświetlenie (`show`) produktu z `id: 123` jako **akcji** . Dobrą praktyką jest zapisanie pary prezenter + akcja oddzielonej dwukropkiem jako `Product:show`.
 
-W ten sposób router przekształca adres URL w parę `Presenter:action` + parametry, w naszym przypadku `Product:show` + `id: 123`. Jak wygląda taki router, można zobaczyć w pliku `app/Router/RouterFactory.php`, a szczegółowo opisujemy go w rozdziale [Routing |Routing].
+W ten sposób router przekształca adres URL w parę `Presenter:action` + parametry, w naszym przypadku `Product:show` + `id: 123`. Jak wygląda taki router, można zobaczyć w pliku `app/Core/RouterFactory.php`, a szczegółowo opisujemy go w rozdziale [Routing |Routing].
 
 Ruszajmy dalej. Aplikacja zna teraz nazwę prezentera i może przejść dalej. Produkując obiekt klasy `ProductPresenter`, który jest kodem prezentera `Product`. Dokładniej, prosi kontener DI o wyprodukowanie prezentera, ponieważ jest tam, aby go wyprodukować.
 
@@ -121,12 +121,9 @@ Wywołana jest więc metoda `renderShow(123)`, której kod jest fikcyjnym przyk
 
 Następnie prezenter zwraca odpowiedź. Może to być strona HTML, obraz, dokument XML, wysłanie pliku z dysku, JSON, a nawet przekierowanie na inną stronę. Co ważne, o ile nie powiemy wprost prezenterowi, jak ma odpowiedzieć (co ma miejsce w przypadku `ProductPresenter`), odpowiedzią będzie renderowanie szablonu ze stroną HTML. Dlaczego? Ponieważ w 99% przypadków chcemy renderować szablon, więc prezenter przyjmuje to zachowanie jako domyślne i chce ułatwić nam pracę. O to właśnie chodzi w Nette.
 
-Nie musimy nawet określać, jaki szablon ma być renderowany, sam wywnioskuje ścieżkę do niego za pomocą prostej logiki. W przypadku prezentera `Product` i akcji `show`, spróbuje sprawdzić, czy istnieje jeden z tych plików szablonów przechowywanych względnie z katalogu klasy `ProductPresenter`:
+Nie musimy nawet określać, który szablon ma być renderowany; framework sam wydedukuje ścieżkę. W przypadku akcji `show`, po prostu próbuje załadować szablon `show.latte` w katalogu z klasą `ProductPresenter`. Próbuje również znaleźć układ w pliku `@layout.latte` (więcej o [wyszukiwaniu szablonów |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Spróbuje również prześledzić układ w pliku `@layout.latte`, a następnie wyrenderować szablon. W ten sposób kończy się zadanie prezentera i aplikacji, a praca zostaje zakończona. Jeśli szablon nie istnieje, zwrócona zostanie strona błędu 404. Więcej o prezenterach można przeczytać na stronie [Prezenterzy |presenters].
+Następnie szablony są renderowane. To kończy zadanie prezentera i całej aplikacji, a praca jest wykonywana. Jeśli szablon nie istnieje, zostanie zwrócona strona błędu 404. Więcej informacji na temat prezenterów można znaleźć na stronie [Prezenterzy |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Aby być bezpiecznym, spróbujmy podsumować cały proces z nieco innym adresem
 3) router dekoduje adres URL jako parę `Home:default`
 4) tworzony jest obiekt klasy `HomePresenter`
 5) wywoływana jest metoda `renderDefault()` (jeśli istnieje)
-6) wyrenderować szablon np. `templates/Home/default.latte` z układem np. `templates/@layout.latte`
+6) wyrenderować szablon np. `default.latte` z układem np. `@layout.latte`
 
 
 Teraz być może spotkałeś się z wieloma nowymi pojęciami, ale wierzymy, że mają one sens. Tworzenie aplikacji w Nette to ogromna bułka z masłem.
diff --git a/application/pl/modules.texy b/application/pl/modules.texy
index a2a4480132..ecca26c3dc 100644
--- a/application/pl/modules.texy
+++ b/application/pl/modules.texy
@@ -2,29 +2,31 @@ Moduły
 ******
 
 .[perex]
-W Nette moduły reprezentują logiczne jednostki, które tworzą aplikację. Należą do nich prezentery, szablony, ewentualnie komponenty i klasy modeli.
+Moduły zapewniają przejrzystość aplikacji Nette, ułatwiając podział na logiczne jednostki.
 
-Jeden komponent dla prezenterów i jeden dla szablonów nie wystarczyłby dla prawdziwych projektów. Posiadanie kilkudziesięciu plików w jednym folderze jest co najmniej niezorganizowane. Jak się z niego wydostać? Po prostu dzielimy je na podkatalogi na dysku i na przestrzenie nazw w kodzie. I właśnie to robią moduły Nette.
-
-Zapomnijmy więc o jednym folderze dla prezenterów i szablonów, a zamiast tego stwórzmy moduły, na przykład `Admin` i `Front`.
+Podobnie jak w przypadku organizowania plików w foldery na dysku twardym, w Nette możemy podzielić prezenterów, szablony i inne klasy pomocnicze na moduły. Jak to działa w praktyce? Po prostu poprzez włączenie nowych podkatalogów do struktury. Oto przykład struktury z dwoma modułami, Front i Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← adresář s moduly
-│   ├── <b>Admin/</b>            ← modul Admin
-│   │   ├── <b>Presenters/</b>   ← jeho presentery
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← modul Front
-│       └── <b>Presenters/</b>   ← jeho presentery
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Ta struktura katalogów będzie odzwierciedlona w przestrzeni nazw klas, więc na przykład `DashboardPresenter` będzie w przestrzeni `App\Modules\Admin\Presenters`:
+Ta struktura katalogów jest odzwierciedlona w przestrzeniach nazw klas, więc na przykład `DashboardPresenter` znajduje się w przestrzeni nazw `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Prezenter `Dashboard` wewnątrz modułu `Admin` jest określany w aplikacji za pomocą notacji z podwójną kropką jako `Admin:Dashboard`, a jego działanie `default` jest określane jako `Admin:Dashboard:default`.
-A skąd Nette own wie, że `Admin:Dashboard` reprezentuje klasę `App\Modules\Admin\Presenters\DashboardPresenter`? Mówimy to za pomocą [mapowania |#Mappings] w konfiguracji.
-Tak więc podana struktura nie jest stała i można ją modyfikować według potrzeb.
+W aplikacji odnosimy się do prezentera `Dashboard` w module `Admin` używając notacji dwukropka jako `Admin:Dashboard`. W przypadku akcji `default` odnosimy się do niej jako `Admin:Dashboard:default`.
+
+Przedstawiona struktura nie jest sztywna; można [ją w pełni dostosować do własnych potrzeb |#mapping] w konfiguracji. .[tip]
 
-Moduły mogą oczywiście zawierać wszystkie inne części oprócz prezenterów i szablonów, jak komponenty, klasy modeli itp.
+Moduły mogą zawierać wszystkie inne pliki, takie jak komponenty i klasy pomocnicze, oprócz prezenterów i szablonów. Jeśli zastanawiasz się, gdzie je umieścić, rozważ użycie folderu `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Moduły zagnieżdżone .[#toc-nested-modules]
 ------------------------------------------
 
-Moduły nie muszą tworzyć tylko płaskiej struktury, można też tworzyć np. submoduły:
+Moduły mogą mieć wiele poziomów zagnieżdżenia, podobnie jak struktura katalogów na dysku:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← adresář s moduly
-│   ├── <b>Blog/</b>             ← modul Blog
-│   │   ├── <b>Admin/</b>        ← submodul Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodul Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← modul Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Tak więc moduł `Blog` jest podzielony na podmoduły `Admin` i `Front`. I znowu będzie to odzwierciedlone w przestrzeni nazw, która będzie `App\Modules\Blog\Admin\Presenters` itd. Prezenter `Dashboard` wewnątrz submodułu jest określany jako `Blog:Admin:Dashboard`.
+Moduł `Blog` jest podzielony na podmoduły `Admin` i `Front`. Jest to również odzwierciedlone w przestrzeniach nazw, które następnie pojawiają się jako `App\UI\Blog\Admin` i podobnie. Aby odnieść się do prezentera `Dashboard` w podmodule `Admin`, odnosimy się do niego jako `Blog:Admin:Dashboard`.
+
+Zagnieżdżanie może być tak głębokie, jak potrzeba, umożliwiając tworzenie podmodułów.
 
-Rozgałęzienie może iść tak głęboko, jak chcesz, więc możesz tworzyć podmoduły.
+Na przykład, jeśli w administracji masz wiele prezenterów związanych z zarządzaniem zamówieniami, takich jak `OrderDetail`, `OrderEdit`, `OrderDispatch`, itp., możesz utworzyć moduł `Order`, w którym będą zorganizowane prezentery takie jak `Detail`, `Edit`, `Dispatch`, i inne.
 
 
 Tworzenie linków .[#toc-creating-links]
@@ -102,47 +118,66 @@ Patrz [rozdział dotyczący routingu |routing#Modules].
 Mapowanie .[#toc-mapping]
 -------------------------
 
-Określa zasady, według których nazwa klasy jest wyprowadzana z nazwy prezentera. Zapisujemy je w [konfiguracji |configuration] pod kluczem `application › mapping`.
+Mapowanie definiuje zasady wyprowadzania nazwy klasy z nazwy prezentera. Reguły te są określone w [konfiguracji |configuration] pod kluczem `application › mapping`.
 
-Zacznijmy od próbki, która nie korzysta z modułów. Będziemy chcieli, aby klasy prezentera miały przestrzeń nazw `App\Presenters`. To znaczy, będziemy chcieli, aby prezenter, na przykład, `Home` mapował do klasy `App\Presenters\HomePresenter`. Można to osiągnąć dzięki następującej konfiguracji:
+Struktury katalogów wspomniane wcześniej na tej stronie są oparte na następującym mapowaniu:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Zastąp nazwę prezentera gwiazdką w masce klasy, a wynikiem będzie nazwa klasy. Spokojnie!
+Jak działa mapowanie? Dla lepszego zrozumienia, wyobraźmy sobie najpierw aplikację bez modułów. Chcemy, aby klasy prezenterów należały do przestrzeni nazw `App\UI`, tak aby prezenter `Home` był mapowany na klasę `App\UI\HomePresenter`. Można to osiągnąć za pomocą tej konfiguracji:
 
-Jeśli złamiemy prezenterów na moduły, możemy mieć niestandardowe mapowanie dla każdego modułu:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Mapowanie to polega na zastąpieniu gwiazdki w masce `App\UI\*Presenter` nazwą prezentera `Home`, co daje końcową nazwę klasy `App\UI\HomePresenter`. Proste!
+
+Jednakże, jak widać w przykładach w tym i innych rozdziałach, umieszczamy klasy prezenterów w podkatalogach o tej samej nazwie, np. prezenter `Home` jest mapowany na klasę `App\UI\Home\HomePresenter`. Osiąga się to poprzez podwojenie gwiazdki (wymaga Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Przejdźmy teraz do mapowania prezenterów na moduły. Możemy zdefiniować konkretne mapowania dla każdego modułu:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Teraz prezenter `Front:Home` mapuje do klasy `App\Modules\Front\Presenters\HomePresenter`, a prezenter `Admin:Dashboard` mapuje do klasy `App\Modules\Admin\Presenters\DashboardPresenter`.
+Zgodnie z tą konfiguracją, prezenter `Front:Home` mapuje się do klasy `App\UI\Front\Home\HomePresenter`, podczas gdy prezenter `Api:OAuth` mapuje się do klasy `App\Api\OAuthPresenter`.
 
-Bardziej praktyczne będzie stworzenie ogólnej (gwiazdkowej) reguły, która zastąpi pierwsze dwie. W masce klasy zostanie dodana dodatkowa gwiazdka tylko dla tego modułu:
+Ponieważ moduły `Front` i `Admin` mają podobne podejście do mapowania i prawdopodobnie będzie więcej takich modułów, możliwe jest utworzenie ogólnej reguły, która je zastąpi. Nowa gwiazdka dla modułu jest dodawana do maski klasy:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Ale co w przypadku, gdy korzystamy z wielu zagnieżdżonych modułów i mamy np. prezentera `Admin:User:Edit`? W takim przypadku segment z gwiazdką reprezentujący moduł dla każdego poziomu zostanie po prostu powtórzony, a wynikiem będzie klasa `App\Modules\Admin\User\Presenters\EditPresenter`.
+W przypadku wielopoziomowych zagnieżdżonych modułów, takich jak prezenter `Admin:User:Edit`, segment gwiazdki powtarza się dla każdego poziomu, dając w rezultacie klasę `App\UI\Admin\User\Edit\EditPresenter`.
 
-Alternatywną notacją jest użycie tablicy składającej się z trzech segmentów zamiast ciągu. Ta notacja jest równoważna z poprzednią:
+Alternatywnym zapisem jest użycie tablicy złożonej z trzech segmentów zamiast łańcucha. Ta notacja jest równoważna poprzedniej:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Wartość domyślna to `*: *Module\*Presenter`.
+Jeśli mamy tylko jedną regułę w konfiguracji, tę ogólną, możemy napisać krótko:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/pl/presenters.texy b/application/pl/presenters.texy
index b6a00e6d74..f35bddf004 100644
--- a/application/pl/presenters.texy
+++ b/application/pl/presenters.texy
@@ -60,7 +60,7 @@ Podobna metoda `render<View>()`. Podczas gdy `render<View>()` Metoda ma na celu
 
 Ważne jest to, że `action<Action>()` jest wywoływany przed `render<View>()`więc możemy w nim potencjalnie zmienić dalszy bieg historii, czyli zmienić szablon do wylosowania, a także metodę `render<View>()`który zostanie wywołany. Odbywa się to za pomocą strony `setView('jineView')`.
 
-Do metody przekazywane są parametry z żądania. Możliwe i zalecane jest podawanie typów do parametrów, np. `actionShow(int $id, string $slug = null)` - jeśli w parametrze `id` zabraknie lub nie będzie on liczbą całkowitą, prezenter zwróci [błąd 404 |#Error-404-etc] i wyjdzie.
+Do metody przekazywane są parametry z żądania. Możliwe i zalecane jest podawanie typów do parametrów, np. `actionShow(int $id, ?string $slug = null)` - jeśli w parametrze `id` zabraknie lub nie będzie on liczbą całkowitą, prezenter zwróci [błąd 404 |#Error-404-etc] i wyjdzie.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ Wiadomości te są dostępne dla szablonu w zmiennej `$flashes` jako obiekty `st
 Error 404 i co. .[#toc-error-404-etc]
 =====================================
 
-Jeśli żądanie nie może zostać spełnione, na przykład dlatego, że artykuł, który chcemy wyświetlić, nie istnieje w bazie danych, rzucamy błąd 404 za pomocą metody `error(string $message = null, int $httpCode = 404)`.
+Jeśli żądanie nie może zostać spełnione, na przykład dlatego, że artykuł, który chcemy wyświetlić, nie istnieje w bazie danych, rzucamy błąd 404 za pomocą metody `error(?string $message = null, int $httpCode = 404)`.
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parametry żądania .[#toc-request-parameters]
+============================================
+
+Prezenter, jak również każdy komponent, uzyskuje swoje parametry z żądania HTTP. Ich wartości można pobrać za pomocą metody `getParameter($name)` lub `getParameters()`. Wartości są ciągami lub tablicami ciągów, zasadniczo surowymi danymi uzyskanymi bezpośrednio z adresu URL.
+
+Dla większej wygody zalecamy udostępnianie parametrów za pośrednictwem właściwości. Wystarczy opatrzyć je adnotacją `#[Parameter]` atrybut:
+
+```php
+use Nette\Application\Attributes\Parameter;  // Ta linia jest ważna
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // musi być publiczny
+}
+```
+
+W przypadku właściwości sugerujemy określenie typu danych (np. `string`). Nette automatycznie rzuci wartość na jej podstawie. Wartości parametrów mogą być również [walidowane |#Validation of Parameters].
+
+Podczas tworzenia linku można bezpośrednio ustawić wartość parametrów:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Trwałe parametry .[#toc-persistent-parameters]
 ==============================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Jeśli `$this->lang` ma wartość taką jak `'en'`, to linki utworzone przy użyciu `link()` lub `n:href` będą zawierały również parametr `lang=en`. A gdy link zostanie kliknięty, ponownie będzie to `$this->lang = 'en'`.
 
-Dla właściwości zalecamy dołączenie typu danych (np. `string`) i można również dołączyć wartość domyślną. Wartości parametrów mogą być [walidowane |#Validation of Persistent Parameters].
+W przypadku właściwości zalecamy podanie typu danych (np. `string`), a także wartości domyślnej. Wartości parametrów mogą być [walidowane |#Validation of Parameters].
 
 Trwałe parametry są domyślnie przekazywane pomiędzy wszystkimi akcjami danego prezentera. Aby przekazać je pomiędzy wieloma prezenterami, musisz je zdefiniować:
 
@@ -307,18 +333,12 @@ Sięgając głębiej .[#toc-going-deeper]
 Z tym, co do tej pory omówiliśmy w tym rozdziale, jesteś prawdopodobnie całkowicie zadowolony. Kolejne wiersze są dla tych, którzy interesują się prezenterami dogłębnie i chcą wiedzieć wszystko.
 
 
-Wymagania i parametry .[#toc-requirement-and-parameters]
---------------------------------------------------------
+Walidacja parametrów .[#toc-validation-of-parameters]
+-----------------------------------------------------
 
-Żądanie obsługiwane przez prezentera ma postać obiektu [api:Nette\Application\Request] i jest zwracane przez metodę prezentera `getRequest()`. Zawiera ona tablicę parametrów, a każdy z nich należy albo do któregoś z komponentów, albo bezpośrednio do prezentera (który w rzeczywistości też jest komponentem, choć specjalnym). Nette dokonuje więc redystrybucji parametrów i przechodzi między poszczególnymi komponentami (i prezenterem), wywołując metodę `loadState(array $params)`. Parametry można uzyskać za pomocą metody `getParameters(): array`, indywidualnie za pomocą `getParameter($name)`. Wartości parametrów są ciągami lub tablicami ciągów, są to w zasadzie surowe dane uzyskane bezpośrednio z adresu URL.
+Wartości [parametrów żądania |#request parameters] i [parametrów stałych |#persistent parameters] otrzymanych z adresów URL są zapisywane we właściwościach przez metodę `loadState()`. Sprawdza również, czy typ danych określony we właściwości jest zgodny, w przeciwnym razie odpowie błędem 404, a strona nie zostanie wyświetlona.
 
-
-Walidacja trwałych parametrów .[#toc-validation-of-persistent-parameters]
--------------------------------------------------------------------------
-
-Wartości [trwałych parametrów |#persistent parameters] otrzymanych z adresów URL są zapisywane do właściwości przez metodę `loadState()`. Sprawdza ona również, czy typ danych określony we właściwości pasuje, w przeciwnym razie odpowie błędem 404 i strona nie zostanie wyświetlona.
-
-Nigdy ślepo nie ufaj trwałym parametrom, ponieważ mogą one zostać łatwo nadpisane przez użytkownika w adresie URL. Na przykład w ten sposób sprawdzamy, czy `$this->lang` jest wśród obsługiwanych języków. Dobrym sposobem na to jest nadpisanie metody `loadState()` wspomnianej powyżej:
+Nigdy nie należy ślepo ufać parametrom, ponieważ mogą one zostać łatwo nadpisane przez użytkownika w adresie URL. Na przykład w ten sposób sprawdzamy, czy `$this->lang` należy do obsługiwanych języków. Dobrym sposobem na to jest nadpisanie metody `loadState()` wspomnianej powyżej:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Zapisywanie i przywracanie wniosku .[#toc-save-and-restore-the-request]
 -----------------------------------------------------------------------
 
-Bieżące żądanie można zapisać do sesji lub przywrócić z niej i pozwolić prezenterowi wykonać je ponownie. Jest to przydatne, na przykład, gdy użytkownik wypełnia formularz i jego login wygasa. Aby uniknąć utraty danych, przed przekierowaniem na stronę logowania zapisujemy bieżące żądanie do sesji za pomocą `$reqId = $this->storeRequest()`, która zwraca jej identyfikator jako krótki łańcuch i przekazuje go jako parametr do prezentera logowania.
+Żądanie obsługiwane przez prezentera jest obiektem [api:Nette\Application\Request] i jest zwracane przez metodę prezentera `getRequest()`.
+
+Możesz zapisać bieżące żądanie w sesji lub przywrócić je z sesji i pozwolić prezenterowi wykonać je ponownie. Jest to przydatne na przykład, gdy użytkownik wypełnia formularz, a jego login wygasa. Aby nie utracić danych, przed przekierowaniem na stronę logowania zapisujemy bieżące żądanie do sesji za pomocą `$reqId = $this->storeRequest()`, która zwraca identyfikator w postaci krótkiego ciągu znaków i przekazuje go jako parametr do prezentera logowania.
 
 Po zalogowaniu się wywołujemy metodę `$this->restoreRequest($reqId)`, która pobiera żądanie z sesji i przekazuje je dalej. Ta metoda sprawdza, czy żądanie zostało utworzone przez tego samego użytkownika, który jest teraz zalogowany. Jeśli zalogował się inny użytkownik lub klucz był nieważny, nie robi nic i program kontynuuje.
 
@@ -362,7 +384,7 @@ Przekierowanie nie nastąpi w przypadku żądań AJAX lub POST, ponieważ spowod
 Możesz również wywołać kanonizację ręcznie za pomocą metody `canonicalize()`, która przekaże prezentera, akcję i parametry podobnie jak w przypadku metody `link()`. Tworzy link i porównuje go z bieżącym adresem URL. Jeśli się różni, przekierowuje na wygenerowany link.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// přesměruje, pokud $slug se liší od $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Ograniczenie dostępu przy użyciu `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+------------------------------------------------------------------------------------------------------------
+
+Atrybut `#[Requires]` zapewnia zaawansowane opcje ograniczania dostępu do prezenterów i ich metod. Można go użyć do określenia metod HTTP, wymagania żądań AJAX, ograniczenia dostępu do tego samego źródła i ograniczenia dostępu tylko do przekazywania. Atrybut może być stosowany do klas prezenterów, jak również poszczególnych metod, takich jak `action<Action>()`, `render<View>()`, `handle<Signal>()`, i `createComponent<Name>()`.
+
+Można określić te ograniczenia:
+- na metodach HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- wymagające żądania AJAX: `#[Requires(ajax: true)]`
+- dostęp tylko z tego samego źródła: `#[Requires(sameOrigin: true)]`
+- dostęp tylko przez przekierowanie: `#[Requires(forward: true)]`
+- ograniczenia dotyczące określonych działań: `#[Requires(actions: 'default')]`
+
+Aby uzyskać szczegółowe informacje, zobacz [Jak używać atrybutu Requires atrybut |best-practices:attribute-requires].
+
+
+Sprawdzanie metod HTTP .[#toc-http-method-check]
+------------------------------------------------
+
+W Nette prezenterzy automatycznie weryfikują metodę HTTP każdego przychodzącego żądania głównie ze względów bezpieczeństwa. Domyślnie dozwolone są metody `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Jeśli chcesz włączyć dodatkowe metody, takie jak `OPTIONS`, możesz użyć atrybutu `#[Requires]` (od wersji Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+W wersji 3.1 weryfikacja jest wykonywana w `checkHttpMethod()`, która sprawdza, czy metoda określona w żądaniu znajduje się w tablicy `$presenter->allowedMethods`. Należy dodać taką metodę:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Ważne jest, aby podkreślić, że jeśli włączysz metodę `OPTIONS`, musisz również poprawnie obsługiwać ją w swoim prezenterze. Metoda ta jest często używana jako tak zwane żądanie wstępne, które przeglądarki automatycznie wysyłają przed faktycznym żądaniem, gdy konieczne jest ustalenie, czy żądanie jest dozwolone z punktu widzenia polityki CORS (Cross-Origin Resource Sharing). Jeśli zezwolisz na tę metodę, ale nie zaimplementujesz odpowiedniej odpowiedzi, może to prowadzić do niespójności i potencjalnych problemów z bezpieczeństwem.
+
+
 Dalsza lektura .[#toc-further-reading]
 ======================================
 
diff --git a/application/pl/routing.texy b/application/pl/routing.texy
index 4ce1af8644..ede7479898 100644
--- a/application/pl/routing.texy
+++ b/application/pl/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Wpis rozszerzony .[#toc-advanced-notation]
 ------------------------------------------
 
-Drugi parametr routy, który często zapisywany jest w formacie `Presenter:action`, jest skrótem, który można również zapisać jako tablicę, gdzie bezpośrednio wypisujemy (domyślne) wartości poszczególnych parametrów:
+Cel trasy, zwykle zapisany w postaci `Presenter:action`, może być również wyrażony za pomocą tablicy, która definiuje poszczególne parametry i ich wartości domyślne:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Możemy też użyć tego formularza, zauważając nadpisanie wyrażenia regularnego walidacji:
+Aby uzyskać bardziej szczegółową specyfikację, można użyć jeszcze bardziej rozszerzonej formy, w której oprócz wartości domyślnych można ustawić inne właściwości parametru, takie jak wyrażenie regularne walidacji (patrz parametr `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Te bardziej verbose formaty są przydatne do dodawania dodatkowych metadanych.
+Ważne jest, aby pamiętać, że jeśli parametry zdefiniowane w tablicy nie są zawarte w masce ścieżki, ich wartości nie mogą zostać zmienione, nawet przy użyciu parametrów zapytania określonych po znaku zapytania w adresie URL.
 
 
 Filtry i tłumaczenia .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integracja aplikacji .[#toc-integration]
 ========================================
 
-Aby zintegrować stworzony router z aplikacją, musimy powiedzieć o nim kontenerowi DI. Najprostszym sposobem na to jest przygotowanie fabryki tworzącej obiekt routera i powiedzenie konfiguracji kontenera, aby go użyć. Załóżmy, że w tym celu napiszemy metodę `App\Router\RouterFactory::createRouter()`:
+Aby zintegrować stworzony router z aplikacją, musimy powiedzieć o nim kontenerowi DI. Najprostszym sposobem na to jest przygotowanie fabryki tworzącej obiekt routera i powiedzenie konfiguracji kontenera, aby go użyć. Załóżmy, że w tym celu napiszemy metodę `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Następnie wpisujemy do [konfiguracji |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Wszelkie zależności, na przykład od bazy danych itp, są przekazywane do metody fabrycznej jako jej parametry przez [autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Przez użycie samodzielne rozumiemy wykorzystanie możliwości routera w aplikac
 Czyli znowu tworzymy metodę, która buduje dla nas np. router:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Możemy też wykonać obiekty bezpośrednio:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/pl/templates.texy b/application/pl/templates.texy
index a7dd044914..51705f00d3 100644
--- a/application/pl/templates.texy
+++ b/application/pl/templates.texy
@@ -34,35 +34,81 @@ I to będzie szablon akcji:
 Definiuje blok `content`, który zostanie wstawiony w miejsce `{include content}` w układzie, a także redefiniuje blok `title`, który zastąpi `{block title}` w układzie. Spróbujcie sobie wyobrazić ten rezultat.
 
 
-Wyszukiwanie szablonów .[#toc-search-for-templates]
----------------------------------------------------
+Wyszukiwanie szablonów .[#toc-template-lookup]
+----------------------------------------------
 
-Ścieżka do szablonów jest wyprowadzana przez prezentera za pomocą prostej logiki. Spróbuje sprawdzić, czy jeden z tych plików znajduje się relatywnie od katalogu klasy prezentera, gdzie `<Presenter>` to nazwa aktualnego prezentera, a `<view>` jest nazwą bieżącego zdarzenia:
+W prezenterach nie trzeba określać, który szablon ma być renderowany; framework automatycznie określi ścieżkę, ułatwiając kodowanie.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Jeśli używasz struktury katalogów, w której każdy prezenter ma swój własny katalog, po prostu umieść szablon w tym katalogu pod nazwą akcji (tj. widoku). Na przykład dla akcji `default` należy użyć szablonu `default.latte`:
 
-Jeśli szablon nie zostanie znaleziony, spróbuje poszukać w katalogu `templates` o jeden poziom wyżej, czyli na tym samym poziomie co katalog z klasą prezentera.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Jeśli tam również nie zostanie znaleziony szablon, odpowiedzią będzie [błąd 404 |presenters#Error 404 etc.].
+Jeśli używasz struktury, w której prezenterzy znajdują się w jednym katalogu, a szablony w folderze `templates`, zapisz je w pliku `<Presenter>.<view>.latte` lub `<Presenter>/<view>.latte`:
 
-Widok można również zmienić za pomocą strony `$this->setView('jineView')`. Lub, zamiast szukać bezpośrednio, określ nazwę pliku szablonu za pomocą `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+Katalog `templates` może być również umieszczony o jeden poziom wyżej, na tym samym poziomie co katalog z klasami prezenterów.
+
+Jeśli szablon nie zostanie znaleziony, prezenter odpowie [błędem 404 - nie znaleziono strony |presenters#Error 404 etc].
+
+Widok można zmienić za pomocą `$this->setView('anotherView')`. Możliwe jest również bezpośrednie określenie pliku szablonu za pomocą `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Pliki, w których wyszukiwane są szablony można zmienić nakładając na metodę [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], która zwraca tablicę możliwych nazw plików.
+Pliki, w których wyszukiwane są szablony, można zmienić, nadpisując metodę [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], która zwraca tablicę możliwych nazw plików.
+
+
+Wyszukiwanie szablonu układu .[#toc-layout-template-lookup]
+-----------------------------------------------------------
+
+Nette automatycznie wyszukuje również plik układu.
+
+Jeśli używasz struktury katalogów, w której każdy prezenter ma swój własny katalog, umieść układ w folderze z prezenterem, jeśli jest on specyficzny tylko dla niego, lub poziom wyżej, jeśli jest wspólny dla wielu prezenterów:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Jeśli używasz struktury, w której prezenterzy są zgrupowani w jednym katalogu, a szablony znajdują się w folderze `templates`, layout będzie oczekiwany w następujących miejscach:
 
-W tych plikach spodziewany jest układ:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` układ wspólny dla wielu prezenterów
+Jeśli prezenter znajduje się w [module |modules], będzie on również wyszukiwany dalej w drzewie katalogów zgodnie z zagnieżdżeniem modułu.
 
-Gdzie `<Presenter>` to nazwa aktualnego prezentera, a `<layout>` jest nazwą układu, którą domyślnie jest `'layout'`. Nazwę można zmienić za pomocą `$this->setLayout('jinyLayout')`, więc wypróbowane zostaną pliki `@jinyLayout.latte`.
+Nazwę layoutu można zmienić za pomocą `$this->setLayout('layoutAdmin')`, a następnie będzie ona oczekiwana w pliku `@layoutAdmin.latte`. Można również bezpośrednio określić plik szablonu układu za pomocą `$this->setLayout('/path/to/template.latte')`.
 
-Możesz również bezpośrednio określić nazwę pliku szablonu układu, używając `$this->setLayout('/path/to/template.latte')`. Użycie `$this->setLayout(false)` wyłączy śledzenie układu.
+Użycie `$this->setLayout(false)` lub znacznika `{layout none}` wewnątrz szablonu wyłącza wyszukiwanie układu.
 
 .[note]
-Pliki, w których wyszukiwane są szablony układów można zmienić nakładając na metodę [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], która zwraca tablicę możliwych nazw plików.
+Pliki, w których przeszukiwane są szablony układu, można zmienić, nadpisując metodę [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], która zwraca tablicę możliwych nazw plików.
 
 
 Zmienne w szablonie .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ Adnotacja `@property-read` jest dla IDE i analizy statycznej, sprawi, że szepta
 Możesz również mieć luksus szeptania w szablonach, wystarczy zainstalować wtyczkę Latte w PhpStorm i umieścić nazwę klasy na początku szablonu, zobacz artykuł "Latte: jak wpisać system":https://blog.nette.org/pl/latte-jak-korzystac-z-systemu-typow, aby uzyskać więcej informacji:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte w wersji 3 oferuje bardziej zaawansowany sposób tworzenia [rozszerzenia |latte:creating-extension] dla każdego projektu internetowego. Oto krótki przykład takiej klasy:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ Rejestrujemy go za pomocą [konfiguracji |configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternatywnie, tłumacz może być ustawiony za pomocą [konfiguracji |configura
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Translator może być wtedy użyty np. jako filtr `|translate`, z dodatkowymi parametrami przekazywanymi do metody `translate()` (patrz `foo, bar`):
diff --git a/application/pt/@home.texy b/application/pt/@home.texy
index 68976dc90d..de531925ab 100644
--- a/application/pt/@home.texy
+++ b/application/pt/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | versão | compatível com PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 - 8.2
-| Aplicação Nette 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Aplicativo Nette 3.0 | PHP 7.1 - 8.0
 | Aplicação Nette 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/pt/ajax.texy b/application/pt/ajax.texy
index 2ef450e4d6..c2159c60f4 100644
--- a/application/pt/ajax.texy
+++ b/application/pt/ajax.texy
@@ -3,40 +3,43 @@ AJAX & Snippets
 
 <div class=perex>
 
-As aplicações web modernas atualmente rodam metade em um servidor e metade em um navegador. O AJAX é um fator de união vital. Que suporte o Nette Framework oferece?
-- envio de fragmentos de modelos (os chamados *snippets*)
-- passando variáveis entre PHP e JavaScript
-- Depuração de aplicações AJAX
+Na era dos aplicativos modernos da Web, em que a funcionalidade geralmente se estende entre o servidor e o navegador, o AJAX é um elemento de conexão essencial. Que opções o Nette Framework oferece nessa área?
+- envio de partes do modelo, os chamados snippets
+- passagem de variáveis entre PHP e JavaScript
+- ferramentas para depuração de solicitações AJAX
 
 </div>
 
 
-Solicitação AJAX .[#toc-ajax-request]
-=====================================
+Solicitação de AJAX .[#toc-ajax-request]
+========================================
 
-Uma solicitação AJAX não difere de uma solicitação clássica - o apresentador é chamado com uma visão e parâmetros específicos. Cabe também ao apresentador como responder a ela: ele pode usar sua própria rotina, que retorna um fragmento de código HTML (HTML snippet), um documento XML, um objeto JSON ou código JavaScript.
+Basicamente, uma solicitação AJAX não difere de uma solicitação HTTP clássica. Um apresentador é chamado com parâmetros específicos. Cabe ao apresentador decidir como responder à solicitação: ele pode retornar dados no formato JSON, enviar uma parte do código HTML, um documento XML etc.
 
-No lado do servidor, uma solicitação AJAX pode ser detectada usando o método de serviço [que encapsula a solicitação HTTP |http:request] `$httpRequest->isAjax()` (detecta com base no cabeçalho HTTP `X-Requested-With`). Dentro do apresentador, um atalho está disponível na forma do método `$this->isAjax()`.
+No lado do navegador, iniciamos uma solicitação AJAX usando a função `fetch()`:
 
-Há um objeto pré-processado chamado `payload` dedicado ao envio de dados para o navegador no JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// processamento da resposta
+});
 ```
 
-Para um controle total sobre sua saída JSON, utilize o método `sendJson` em seu apresentador. Ele encerra o apresentador imediatamente e você não precisará de um modelo:
+No lado do servidor, uma solicitação AJAX é reconhecida pelo método `$httpRequest->isAjax()` do serviço [que encapsula a solicitação HTTP |http:request]. Ele usa o cabeçalho HTTP `X-Requested-With`, portanto, é essencial enviá-lo. No apresentador, você pode usar o método `$this->isAjax()`.
+
+Se você quiser enviar dados no formato JSON, use o método [`sendJson()` |presenters#Sending a response] método. O método também encerra a atividade do apresentador.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Se quisermos enviar HTML, podemos definir um modelo especial para pedidos AJAX:
+Se você planeja responder com um modelo especial projetado para AJAX, pode fazer isso da seguinte forma:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Trechos .[#toc-snippets]
+========================
+
+A ferramenta mais poderosa oferecida pela Nette para conectar o servidor com o cliente são os snippets. Com eles, você pode transformar um aplicativo comum em um aplicativo AJAX com o mínimo de esforço e algumas linhas de código. O exemplo Fifteen demonstra como tudo isso funciona, e seu código pode ser encontrado no [GitHub |https://github.com/nette-examples/fifteen].
+
+Os snippets, ou recortes, permitem que você atualize apenas partes da página, em vez de recarregar a página inteira. Isso é mais rápido e mais eficiente, além de proporcionar uma experiência de usuário mais confortável. Os snippets podem lembrá-lo do Hotwire para Ruby on Rails ou do Symfony UX Turbo. É interessante notar que a Nette introduziu os snippets 14 anos antes.
+
+Como os snippets funcionam? Quando a página é carregada pela primeira vez (uma solicitação não AJAX), a página inteira, incluindo todos os snippets, é carregada. Quando o usuário interage com a página (por exemplo, clica em um botão, envia um formulário etc.), em vez de carregar a página inteira, é feita uma solicitação AJAX. O código no apresentador executa a ação e decide quais trechos precisam ser atualizados. A Nette renderiza esses trechos e os envia na forma de uma matriz JSON. O código de manipulação no navegador insere os trechos recebidos de volta na página. Portanto, somente o código dos trechos alterados é transferido, economizando largura de banda e acelerando o carregamento em comparação com a transferência de todo o conteúdo da página.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-A [biblioteca Naja |https://naja.js.org] é utilizada para lidar com pedidos AJAX no lado do navegador. [Instale-a |https://naja.js.org/#/guide/01-install-setup-naja] como um pacote node.js (para usar com Webpack, Rollup, Vite, Parcel e mais):
+Para lidar com snippets no navegador, é usada a [biblioteca Naja |https://naja.js.org]. [Instale-a |https://naja.js.org/#/guide/01-install-setup-naja] como um pacote node.js (para uso com aplicativos como Webpack, Rollup, Vite, Parcel e outros):
 
 ```shell
 npm install naja
 ```
 
-...ou inseri-lo diretamente no modelo da página:
+... ou insira-a diretamente no modelo da página:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Para criar uma solicitação AJAX a partir de um link regular (sinal) ou envio de formulário, basta marcar o link, formulário ou botão relevante com a classe `ajax`:
+Primeiro, você precisa [inicializar |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] a biblioteca:
+
+```js
+naja.initialize();
+```
+
+Para transformar um link comum (sinal) ou o envio de um formulário em uma solicitação AJAX, basta marcar o respectivo link, formulário ou botão com a classe `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Para criar uma solicitação AJAX a partir de um link regular (sinal) ou envio d
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippets .[#toc-snippets]
-=========================
-
-Há uma ferramenta muito mais poderosa de suporte AJAX incorporado - trechos. O uso deles torna possível transformar uma aplicação regular em AJAX, utilizando apenas algumas linhas de código. Como tudo funciona é demonstrado no exemplo dos Quinze, cujo código também é acessível no build ou no [GitHub |https://github.com/nette-examples/fifteen].
-
-A forma como os trechos funcionam é que a página inteira é transferida durante a solicitação inicial (isto é, não-AJAX) e depois com cada [sub solicitação |components#signal] AJAX (solicitação da mesma visão do mesmo apresentador) apenas o código das partes alteradas é transferido no repositório `payload` mencionado anteriormente.
-
-Snippets podem lembrá-lo da Hotwire para Ruby on Rails ou Symfony UX Turbo, mas a Nette surgiu com eles catorze anos antes.
-
+Redesenho de snippets .[#toc-redrawing-snippets]
+------------------------------------------------
 
-Invalidação de Snippets .[#toc-invalidation-of-snippets]
-========================================================
-
-Cada descendente do [Controle de |components] Classe (que um Apresentador também é) é capaz de lembrar se houve alguma mudança durante um pedido que requeira sua reapresentação. Há um par de métodos para lidar com isso: `redrawControl()` e `isControlInvalid()`. Um exemplo:
+Todos os objetos da classe [Control |components] (inclusive o próprio Presenter) mantêm um registro da ocorrência de alterações que exijam o redesenho. O método `redrawControl()` é usado para essa finalidade.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// O objeto tem de ser restituído após o usuário ter feito o login
+	// depois de fazer login, é necessário redesenhar a parte relevante
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-A Nette, entretanto, oferece uma resolução ainda mais fina do que os componentes inteiros. Os métodos listados aceitam o nome do chamado "snippet" como um parâmetro opcional. Um "snippet" é basicamente um elemento em seu modelo marcado para esse fim por uma tag Latte, mais sobre isso depois. Assim, é possível pedir a um componente para redesenhar apenas *partes* de seu gabarito. Se o componente inteiro for invalidado, então todos os seus trechos serão restituídos. Um componente é "inválido" também se qualquer um de seus subcomponentes for inválido.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // invalida o snippet chamado 'header'.
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, at least one snippet is invalid
+O Nette também permite um controle mais preciso do que precisa ser redesenhado. O método mencionado acima pode usar o nome do snippet como argumento. Assim, é possível invalidar (ou seja, forçar um redesenho) no nível da parte do modelo. Se o componente inteiro for invalidado, todos os trechos dele também serão redesenhados:
 
-$this->redrawControl(); // invalida todo o componente, todos os snippet
-$this->isControlInvalid('footer'); // -> true
+```php
+// invalida o trecho de "cabeçalho
+$this->redrawControl('header');
 ```
 
-Um componente que recebe um sinal é automaticamente marcado para ser redesenhado.
-
-Graças ao desenho de snippet, sabemos exatamente quais partes de quais elementos devem ser novamente entregues.
-
-
-Tag `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
-
-A renderização da página procede de forma muito semelhante a um pedido regular: os mesmos modelos são carregados, etc. A parte vital é, no entanto, deixar de fora as partes que não devem chegar à saída; as outras partes devem ser associadas a um identificador e enviadas ao usuário em um formato compreensível para um manipulador de JavaScript.
-
 
-Sintaxe .[#toc-syntax]
-----------------------
+Snippets em Latte .[#toc-snippets-in-latte]
+-------------------------------------------
 
-Se houver um controle ou um snippet no modelo, temos que embrulhá-lo usando a tag do par `{snippet} ... {/snippet}` - ele assegurará que o snippet renderizado será "cortado" e enviado para o navegador. Ele também o anexará em um helper `<div>` (é possível utilizar uma etiqueta diferente). No exemplo a seguir, um trecho chamado `header` está definido. Ele pode também representar o modelo de um componente:
+Usar snippets no Latte é extremamente fácil. Para definir uma parte do modelo como um snippet, basta envolvê-la nas tags `{snippet}` e `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Se houver um controle ou um snippet no modelo, temos que embrulhá-lo usando a t
 {/snippet}
 ```
 
-Um fragmento de um tipo diferente de `<div>` ou um snippet com atributos HTML adicionais é obtido usando a variante de atributo:
+O snippet cria um elemento `<div>` na página HTML com um `id` especialmente gerado. Ao redesenhar um snippet, o conteúdo desse elemento é atualizado. Portanto, quando a página é renderizada inicialmente, todos os snippets também devem ser renderizados, mesmo que inicialmente estejam vazios.
+
+Você também pode criar um snippet com um elemento diferente de `<div>` usando um atributo n::
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Um fragmento de um tipo diferente de `<div>` ou um snippet com atributos HTML ad
 ```
 
 
-Snippets dinâmicos .[#toc-dynamic-snippets]
-===========================================
+Áreas de snippet .[#toc-snippet-areas]
+--------------------------------------
 
-Em Nette você também pode definir trechos com um nome dinâmico baseado em um parâmetro de tempo de execução. Isto é mais adequado para várias listas onde precisamos mudar apenas uma linha, mas não queremos transferir a lista inteira junto com ela. Um exemplo disto seria:
+Os nomes dos snippets também podem ser expressões:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Há um trecho estático chamado `itemsContainer`, contendo vários trechos dinâmicos: `item-0`, `item-1` e assim por diante.
+Dessa forma, obteremos vários snippets como `item-0`, `item-1`, etc. Se invalidássemos diretamente um snippet dinâmico (por exemplo, `item-1`), nada seria redesenhado. O motivo é que os snippets funcionam como verdadeiros trechos e somente eles são renderizados diretamente. Entretanto, no modelo, não há tecnicamente um trecho chamado `item-1`. Ele só aparece quando se executa o código ao redor do snippet, nesse caso, o loop foreach. Por isso, marcaremos a parte do modelo que precisa ser executada com a tag `{snippetArea}`:
 
-Você não pode redesenhar um trecho dinâmico diretamente (o redesenho de `item-1` não tem efeito), você tem que redesenhar seu trecho pai (neste exemplo `itemsContainer`). Isto faz com que o código do snippet pai seja executado, mas então apenas seus sub-snippets são enviados para o navegador. Se você quiser enviar apenas um dos sub-snippets, você tem que modificar a entrada para que o trecho pai não gere os outros sub-snippets.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-No exemplo acima você tem que ter certeza de que para um pedido AJAX apenas um item será adicionado à matriz `$list`, portanto o laço `foreach` imprimirá apenas um trecho dinâmico.
+E redesenharemos tanto o snippet individual quanto toda a área abrangente:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Também é essencial garantir que a matriz `$items` contenha apenas os itens que devem ser redesenhados.
 
-Snippets em um Modelo Incluído .[#toc-snippets-in-an-included-template]
-=======================================================================
-
-Pode acontecer que o trecho esteja em um modelo que está sendo incluído a partir de um modelo diferente. Nesse caso, precisamos embrulhar o código de inclusão no segundo modelo com a tag `snippetArea`, então redesenhamos tanto o snippetArea quanto o snippet real.
-
-A tag `snippetArea` assegura que o código interno seja executado, mas apenas o trecho real no modelo incluído é enviado para o navegador.
+Ao inserir outro modelo no modelo principal usando a tag `{include}`, que tem snippets, é necessário envolver novamente o modelo incluído em um `snippetArea` e invalidar o snippet e a área juntos:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* incluído.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Você também pode combiná-lo com trechos dinâmicos.
 
+Snippets em componentes .[#toc-snippets-in-components]
+------------------------------------------------------
 
-Adicionando e excluindo .[#toc-adding-and-deleting]
-===================================================
-
-Se você acrescentar um novo item à lista e invalidar `itemsContainer`, o pedido AJAX devolve trechos incluindo o novo, mas o manipulador de javascript não será capaz de renderizá-lo. Isto porque não há nenhum elemento HTML com o ID recém-criado.
-
-Neste caso, a maneira mais simples é envolver toda a lista em mais um trecho e invalidar tudo isso:
+Você pode criar snippets em [componentes |components], e o Nette os redesenha automaticamente. Entretanto, há uma limitação específica: para redesenhar os snippets, ele chama o método `render()` sem nenhum parâmetro. Portanto, a passagem de parâmetros no modelo não funcionará:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Envio de dados do usuário .[#toc-sending-user-data]
+---------------------------------------------------
+
+Juntamente com os snippets, você pode enviar quaisquer dados adicionais ao cliente. Basta gravá-los no objeto `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-O mesmo vale para a eliminação de um item. Seria possível enviar um trecho vazio, mas geralmente as listas podem ser paginadas e seria complicado implementar a exclusão de um item e o carregamento de outro (que costumava estar em uma página diferente da lista paginada).
-
 
-Parâmetros de envio para o componente .[#toc-sending-parameters-to-component]
-=============================================================================
+Parâmetros de envio .[#toc-sending-parameters]
+==============================================
 
-Quando enviamos parâmetros para o componente via solicitação AJAX, sejam parâmetros de sinal ou parâmetros persistentes, devemos fornecer seu nome global, que também contém o nome do componente. O nome completo do parâmetro retorna o método `getParameterId()`.
+Quando enviamos parâmetros ao componente por meio de solicitação AJAX, sejam eles parâmetros de sinal ou parâmetros persistentes, devemos fornecer seu nome global, que também contém o nome do componente. O nome completo do parâmetro retorna o método `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-E método de manuseio com s parâmetros correspondentes em componente.
+Um método handle com os parâmetros correspondentes no componente:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/pt/bootstrap.texy b/application/pt/bootstrap.texy
index 1ebef20eff..1428498866 100644
--- a/application/pt/bootstrap.texy
+++ b/application/pt/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// O configurador é responsável pela configuração do ambiente e dos serviços do aplicativo.
+		$this->configurator = new Configurator;
+		// Defina o diretório para os arquivos temporários gerados pelo Nette (por exemplo, modelos compilados)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// O Nette é inteligente e o modo de desenvolvimento é ativado automaticamente,
+		// ou você pode ativá-lo para um endereço IP específico, descomentando a seguinte linha:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Habilita o Tracy: a melhor ferramenta de depuração do tipo "canivete suíço".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: carrega automaticamente todas as classes no diretório fornecido
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Carregar arquivos de configuração
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-No caso de aplicações web, o arquivo inicial é `index.php`, que está localizado no diretório público `www/`. Ele permite que a classe `Bootstrap` inicialize o ambiente e devolva o `$configurator` que cria o contêiner DI. Em seguida, obtém o serviço `Application`, que executa a aplicação web:
+O arquivo inicial para aplicativos Web é `index.php`, localizado no diretório público `www/`. Ele usa a classe `Bootstrap` para inicializar o ambiente e criar um contêiner DI. Em seguida, ele obtém o serviço `Application` do contêiner, que inicia o aplicativo Web:
 
 ```php
-// inicializar o ambiente + obter objeto Configurador
-$configurator = App\Bootstrap::boot();
-// criar um recipiente DI
-$container = $configurator->createContainer();
-// Recipiente DI cria um objeto de aplicação Nette
+$bootstrap = new App\Bootstrap;
+// Inicializar o ambiente + criar um contêiner DI
+$container = $bootstrap->bootWebApplication();
+// O contêiner DI cria um objeto Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// iniciar a aplicação Nette
+// Iniciar o aplicativo Nette e tratar a solicitação de entrada
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ A seleção do modo é feita por autodetecção, de modo que normalmente não h
 Se você quiser ativar o modo de desenvolvimento em outros casos, por exemplo, para programadores que acessam de um endereço IP específico, você pode usar `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // um ou mais endereços IP
+$this->configurator->setDebugMode('23.75.345.200'); // um ou mais endereços IP
 ```
 
 Definitivamente, recomendamos combinar um endereço IP com um cookie. Armazenaremos um token secreto no cookie `nette-debug`, por exemplo `secret1234`, e o modo de desenvolvimento será ativado para programadores com esta combinação de IP e cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Também podemos desligar completamente o modo desenvolvedor, mesmo para o localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Note que o valor `true` liga o modo desenvolvedor por hard, o que nunca deveria acontecer em um servidor de produção.
@@ -90,7 +115,7 @@ Ferramenta de depuração Tracy .[#toc-debugging-tool-tracy]
 Para facilitar a depuração, vamos acionar a grande ferramenta [Tracy |tracy:]. No modo desenvolvedor ela visualiza os erros e no modo de produção registra os erros no diretório especificado:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Arquivos temporários .[#toc-temporary-files]
 Nette utiliza o cache para contêiner DI, RobotLoader, modelos, etc. Portanto, é necessário definir o caminho para o diretório onde o cache será armazenado:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 No Linux ou macOS, defina as [permissões de escrita |nette:troubleshooting#Setting directory permissions] para os diretórios `log/` e `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Normalmente, queremos carregar automaticamente as classes usando [o RobotLoader |robot-loader:], então temos que iniciá-lo e deixá-lo carregar classes do diretório onde se encontra `Bootstrap.php` (ou seja, `__DIR__`) e todos os seus subdiretórios:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Fuso horário .[#toc-timezone]
 O Configurador permite que você especifique um fuso horário para sua aplicação.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ No modo de desenvolvimento, o recipiente é atualizado automaticamente cada vez
 Os arquivos de configuração são carregados usando `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 O método `addConfig()` pode ser chamado várias vezes para adicionar vários arquivos.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Parâmetros estáticos .[#toc-static-parameters]
 Os parâmetros usados nos arquivos de configuração podem ser definidos [na seção `parameters` |dependency-injection:configuration#parameters] e também passados (ou sobrescritos) pelo método `addStaticParameters()` (tem o pseudônimo `addParameters()`). É importante que diferentes valores de parâmetros causem a geração de recipientes DI adicionais, ou seja, classes adicionais.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Parâmetros dinâmicos .[#toc-dynamic-parameters]
 Também podemos adicionar parâmetros dinâmicos ao recipiente, seus diferentes valores, ao contrário dos parâmetros estáticos, não causarão a geração de novos recipientes DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 As variáveis ambientais poderiam ser facilmente disponibilizadas usando parâmetros dinâmicos. Podemos acessá-las via `%env.variable%` em arquivos de configuração.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Você pode usar os seguintes parâmetros estáticos nos arquivos de configuraç
 - `%wwwDir%` é o caminho absoluto para o diretório que contém o arquivo de entrada `index.php`
 - `%tempDir%` é o caminho absoluto para o diretório de arquivos temporários
 - `%vendorDir%` é o caminho absoluto para o diretório onde o Composer instala as bibliotecas
+- `%rootDir%` é o caminho absoluto para o diretório raiz do projeto
 - `%debugMode%` indica se a aplicação está em modo de depuração
 - `%consoleMode%` indica se o pedido veio através da linha de comando
 
@@ -225,7 +252,7 @@ services:
 Criar uma nova instância e inseri-la no bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Diferentes Ambientes .[#toc-different-environments]
 ===================================================
 
-Sinta-se à vontade para personalizar a classe `Bootstrap` de acordo com suas necessidades. Você pode adicionar parâmetros ao método `boot()` para diferenciar projetos web, ou adicionar outros métodos, tais como `bootForTests()`, que inicializa o ambiente para testes unitários, `bootForCli()` para scripts chamados a partir da linha de comando, e assim por diante.
+Não hesite em personalizar a classe `Bootstrap` de acordo com suas necessidades. Você pode adicionar parâmetros ao método `bootWebApplication()` para diferenciar os projetos da Web. Como alternativa, você pode adicionar outros métodos, como `bootTestEnvironment()` para inicializar o ambiente para testes de unidade, `bootConsoleApplication()` para scripts chamados pela linha de comando e assim por diante.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Inicialização do Nette Tester
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Nette Tester initialization
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/pt/components.texy b/application/pt/components.texy
index e8df613355..502dc15cdc 100644
--- a/application/pt/components.texy
+++ b/application/pt/components.texy
@@ -230,6 +230,28 @@ No modelo, estas mensagens estão disponíveis na variável `$flashes` como obje
 ```
 
 
+Redirecionamento após um sinal .[#toc-redirection-after-a-signal]
+=================================================================
+
+Depois de processar um sinal de componente, o redirecionamento geralmente é feito. Essa situação é semelhante à dos formulários: após o envio de um formulário, também redirecionamos para evitar o reenvio de dados quando a página é atualizada no navegador.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Como um componente é um elemento reutilizável e normalmente não deve ter uma dependência direta de apresentadores específicos, os métodos `redirect()` e `link()` interpretam automaticamente o parâmetro como um sinal de componente:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Se precisar redirecionar para um apresentador ou ação diferente, você poderá fazer isso por meio do apresentador:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Parâmetros Persistentes .[#toc-persistent-parameters]
 =====================================================
 
@@ -347,7 +369,7 @@ services:
 Finalmente, utilizaremos esta fábrica em nosso apresentador:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Componentes em profundidade .[#toc-components-in-depth]
 Os componentes de uma aplicação Nette são as partes reutilizáveis de uma aplicação web que incorporamos nas páginas, que é o tema deste capítulo. Quais são exatamente as capacidades de um componente desse tipo?
 
 1) é renderizável em um modelo
-2) ela sabe qual parte de si mesma deve prestar durante um [pedido AJAX |ajax#invalidation] (trechos)
+2) ele sabe [qual parte de si mesmo |ajax#snippets] deve ser renderizada durante uma solicitação AJAX (snippets)
 3) tem a capacidade de armazenar seu estado em uma URL (parâmetros persistentes)
 4) tem a capacidade de responder às ações (sinais) do usuário
 5) cria uma estrutura hierárquica (onde a raiz é o apresentador)
@@ -430,7 +452,7 @@ class PaginatingControl extends Control
 }
 ```
 
-O processo oposto, ou seja, a coleta de valores de properites persistentes, é tratado pelo método `saveState()`.
+O processo oposto, ou seja, a coleta de valores de properties persistentes, é tratado pelo método `saveState()`.
 
 
 Sinais em profundidade .[#toc-signals-in-depth]
diff --git a/application/pt/configuration.texy b/application/pt/configuration.texy
index b4561d709c..55e3c0cb5d 100644
--- a/application/pt/configuration.texy
+++ b/application/pt/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# mostra painel "Aplicação Nette" em Tracy BlueScreen?
 	debugger: ...           # (bool) por omissão
 
-	# será que o apresentador de erro será chamado por erro?
-	catchExceptions: ...    # (bool) é o padrão verdadeiro no modo de produção
+	# O apresentador de erros será chamado no erro?
+	# tem efeito somente no modo de desenvolvedor
+	catchExceptions: ...    # (bool) tem como padrão true
 
 	# nome do apresentador de erro
-	errorPresenter: Error   # (string) padrão para 'Nette:Erro'.
+	errorPresenter: Error   # (string|array) padrão para 'Nette:Erro'.
+
+	# define aliases para apresentadores e eventos
+	aliases: ...
 
 	# define as regras para resolver o nome do apresentador para uma classe
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) falha em falso
 ```
 
-Como os apresentadores de erros não são chamados por padrão no modo de desenvolvimento e os erros são exibidos por Tracy, alterar o valor `catchExceptions` para `true` ajuda a verificar se os apresentadores de erros funcionam corretamente durante o desenvolvimento.
+A partir da versão 3.2 do site `nette/application`, é possível definir um par de apresentadores de erros:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # para Nette\Application\BadRequestException
+		5xx: Error5xx   # para outras exceções
+```
 
 A opção `silentLinks` determina como Nette se comporta em modo desenvolvedor quando a geração de links falha (por exemplo, porque não há apresentador, etc.). O valor padrão `false` significa que a Nette aciona `E_USER_WARNING`. A configuração para `true` suprime esta mensagem de erro. Em um ambiente de produção, `E_USER_WARNING` é sempre invocado. Também podemos influenciar este comportamento definindo a variável apresentadora [$invalidLinkMode |creating-links#Invalid Links].
 
+[Os apelidos simplificam a referência a |creating-links#aliases] apresentadores usados com frequência.
+
 O [mapeamento define as regras |modules#mapping] pelas quais o nome da classe é derivado do nome do apresentador.
 
 
@@ -82,6 +95,9 @@ latte:
 	# Permite [verificar o código gerado |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) o padrão é null
 
+	# Define a localidade
+	locale: cs_CZ        # (string) o padrão é nulo
+
 	# classe de $this->template
 	templateClass: App\MyTemplateClass # defaults to Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Se você estiver usando Latte versão 3, você pode adicionar uma nova [extensã
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/pt/creating-links.texy b/application/pt/creating-links.texy
index b58d739ab1..fa9feeb9a8 100644
--- a/application/pt/creating-links.texy
+++ b/application/pt/creating-links.texy
@@ -38,7 +38,7 @@ Também é possível passar parâmetros nomeados. O seguinte link passa o parâm
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Se o método `ProductPresenter::renderShow()` não tiver `$lang` em sua assinatura, ele pode ler o valor do parâmetro usando `$lang = $this->getParameter('lang')`.
+Se o método `ProductPresenter::renderShow()` não tiver `$lang` em sua assinatura, ele poderá recuperar o valor do parâmetro usando `$lang = $this->getParameter('lang')` ou a partir da [propriedade |presenters#Request Parameters].
 
 Se os parâmetros estiverem armazenados em uma matriz, eles podem ser expandidos com o operador `...` (ou `(expand)` operador em Latte 2.x):
 
@@ -140,7 +140,7 @@ A meta `this` irá criar um link para a página atual:
 <a n:href="this">refresh</a>
 ```
 
-Ao mesmo tempo, todos os parâmetros especificados na assinatura do `render<View>()` ou `action<Action>()` método são transferidos. Portanto, se estivermos nas páginas `Product:show` e `id:123`, o link para `this` também passará este parâmetro.
+Ao mesmo tempo, todos os parâmetros especificados na assinatura do parâmetro `action<Action>()` ou `render<View>()` se o método `action<Action>()` não estiver definido, serão transferidos. Portanto, se estivermos nas páginas `Product:show` e `id:123`, o link para `this` também passará esse parâmetro.
 
 Naturalmente, é possível especificar os parâmetros diretamente:
 
@@ -213,7 +213,7 @@ Como [os componentes |components] são unidades reutilizáveis separadas que nã
 Se quisermos fazer um link para apresentadores no modelo de componente, usamos a tag `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 ou no código
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Pseudônimos .[#toc-aliases]{data-version:v3.2.2}
+================================================
+
+Às vezes, é útil atribuir um alias facilmente memorável a um par Presenter:action. Por exemplo, você poderia nomear a página inicial `Front:Home:default` simplesmente como `home` ou `Admin:Dashboard:default` como `admin`.
+
+Os aliases são definidos na [configuração |configuration] sob a chave `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+Nos links, eles são escritos usando o símbolo at, por exemplo:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Eles são compatíveis com todos os métodos que funcionam com links, como `redirect()` e similares.
+
+
 Links inválidos .[#toc-invalid-links]
 =====================================
 
diff --git a/application/pt/how-it-works.texy b/application/pt/how-it-works.texy
index 68f955b2b5..c55012ce62 100644
--- a/application/pt/how-it-works.texy
+++ b/application/pt/how-it-works.texy
@@ -22,18 +22,18 @@ A estrutura do diretório é algo parecido com isto:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← classes básicas necessárias
+│   │   └── <b>RouterFactory.php</b> ← configuração de endereços URL
+│   ├── <b>UI/</b>                   ← apresentadores, modelos e outros
+│   │   ├── <b>@layout.latte</b>     ← modelo de layout compartilhado
+│   │   └── <b>Home/</b>             ← Diretório do apresentador Home
+│   │       ├── <b>HomePresenter.php</b> ← Classe do apresentador da página inicial
+│   │       └── <b>default.latte</b> ← template for action default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ As aplicações escritas em Nette são divididas em muitos dos chamados apresent
 
 A aplicação começa pedindo ao chamado roteador que decida qual dos apresentadores deve passar o atual pedido de processamento. O roteador decide de quem é a responsabilidade. Ele analisa a URL de entrada `https://example.com/product/123`, que quer `show` um produto com `id: 123` como uma ação. É um bom hábito escrever um par de apresentador + ação separado por dois pontos como `Product:show`.
 
-Assim, o roteador transformou a URL em um par `Presenter:action` + parâmetros, em nosso caso `Product:show` + `id: 123`. Você pode ver como é um roteador no arquivo `app/Router/RouterFactory.php` e nós o descreveremos em detalhes no capítulo [Roteamento |Routing].
+Assim, o roteador transformou a URL em um par `Presenter:action` + parâmetros, em nosso caso `Product:show` + `id: 123`. Você pode ver como é um roteador no arquivo `app/Core/RouterFactory.php` e nós o descreveremos em detalhes no capítulo [Roteamento |Routing].
 
 Vamos em frente. O pedido já conhece o nome do apresentador e pode continuar. Ao criar um objeto `ProductPresenter`, que é o código do apresentador `Product`. Mais precisamente, pede ao contêiner DI para criar o apresentador, pois a produção de objetos é sua função.
 
@@ -121,12 +121,9 @@ Então, o método `renderShow(123)` foi chamado, cujo código é um exemplo fict
 
 Posteriormente, o apresentador retorna a resposta. Pode ser uma página HTML, uma imagem, um documento XML, o envio de um arquivo do disco, JSON ou o redirecionamento para outra página. É importante ressaltar que se não dissermos explicitamente como responder (que é o caso de `ProductPresenter`), a resposta será renderizar o template com uma página HTML. Por quê? Bem, porque em 99% dos casos queremos desenhar um template, então o apresentador toma este comportamento como padrão e quer tornar nosso trabalho mais fácil. Esse é o ponto de vista da Nette.
 
-Não temos nem mesmo que declarar qual modelo desenhar, ele deriva o caminho para ele de acordo com uma lógica simples. No caso do apresentador `Product` e da ação `show`, ele tenta ver se um destes arquivos de modelo existe em relação ao diretório onde se encontra a classe `ProductPresenter`:
+Não precisamos nem mesmo especificar o modelo a ser renderizado; a estrutura deduzirá o caminho por si só. No caso da ação `show`, ele simplesmente tenta carregar o modelo `show.latte` no diretório com a classe `ProductPresenter`. Ele também tenta encontrar o layout no arquivo `@layout.latte` (mais informações sobre a [pesquisa de modelos |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Ele também tentará encontrar o layout no arquivo `@layout.latte` e depois renderiza o modelo. Agora a tarefa do apresentador e de todo o pedido está concluída. Se o modelo não existir, uma página com erro 404 será devolvida. Você pode ler mais sobre os apresentadores na página [Apresentadores |Presenters].
+Em seguida, os modelos são renderizados. Isso conclui a tarefa do apresentador e de todo o aplicativo, e o trabalho está concluído. Se o modelo não existir, será retornada uma página de erro 404. Você pode ler mais sobre apresentadores na página [Apresentadores |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Só para ter certeza, vamos tentar recapitular todo o processo com uma URL ligei
 3) o roteador decodifica a URL como um par `Home:default`
 4) um objeto `HomePresenter` é criado
 5) método `renderDefault()` é chamado (se existir)
-6) um modelo `templates/Home/default.latte` com um layout `templates/@layout.latte` é apresentado
+6) um modelo `default.latte` com um layout `@layout.latte` é apresentado
 
 
 Você pode ter se deparado com muitos conceitos novos agora, mas acreditamos que eles fazem sentido. Criar aplicações em Nette é uma brisa.
diff --git a/application/pt/modules.texy b/application/pt/modules.texy
index 35ee3786d3..a2e02d0257 100644
--- a/application/pt/modules.texy
+++ b/application/pt/modules.texy
@@ -2,29 +2,31 @@ Módulos
 *******
 
 .[perex]
-Em Nette, os módulos representam as unidades lógicas que compõem uma aplicação. Eles incluem apresentadores, gabaritos, possivelmente também componentes e classes de modelos.
+Os módulos dão clareza aos aplicativos Nette, facilitando a divisão em unidades lógicas.
 
-Um diretório para apresentadores e um para modelos não seria suficiente para projetos reais. Ter dezenas de arquivos em uma pasta é pelo menos desorganizado. Como sair dela? Nós simplesmente os dividimos em subdiretórios em disco e em namespaces no código. E é exatamente isso que os módulos Nette fazem.
-
-Portanto, vamos esquecer uma única pasta para apresentadores e modelos e, em vez disso, criar módulos, por exemplo `Admin` e `Front`.
+Da mesma forma que organizamos os arquivos em pastas em um disco rígido, na Nette podemos dividir apresentadores, modelos e outras classes auxiliares em módulos. Como isso funciona na prática? Simplesmente incorporando novos subdiretórios à estrutura. Aqui está um exemplo de uma estrutura com dois módulos, Front e Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Esta estrutura de diretório será refletida pelos namespaces de classe, portanto, por exemplo `DashboardPresenter` estará no namespace `App\Modules\Admin\Presenters`:
+Essa estrutura de diretórios é refletida nos namespaces das classes, portanto, por exemplo, `DashboardPresenter` está localizado no namespace `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-O `Dashboard` apresentador dentro do módulo `Admin` é referenciado dentro da aplicação usando a notação de cólon como `Admin:Dashboard`, e sua ação `default` como `Admin:Dashboard:default`.
-E como a Nette propriamente dita sabe que `Admin:Dashboard` representa a classe `App\Modules\Admin\Presenters\DashboardPresenter`? Isto é determinado pelo [mapeamento |#mapping] na configuração.
-Assim, a estrutura dada não é difícil de definir e você pode modificá-la de acordo com suas necessidades.
+No aplicativo, nos referimos ao apresentador `Dashboard` dentro do módulo `Admin` usando a notação de dois pontos como `Admin:Dashboard`. Para sua ação `default`, nos referimos a ela como `Admin:Dashboard:default`.
+
+A estrutura apresentada não é rígida; você pode [personalizá-la totalmente de acordo com suas necessidades |#mapping] na configuração. .[tip]
 
-Os módulos podem naturalmente conter todos os outros itens além de apresentadores e modelos, tais como componentes, classes de modelos, etc.
+Os módulos podem incluir todos os outros arquivos, como componentes e classes auxiliares, além de apresentadores e modelos. Se estiver pensando em onde colocá-los, considere o uso de uma pasta `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Módulos aninhados .[#toc-nested-modules]
 ----------------------------------------
 
-Os módulos não precisam formar apenas uma estrutura plana, você também pode criar submódulos, por exemplo:
+Os módulos podem ter vários níveis de aninhamento, semelhante a uma estrutura de diretórios em um disco:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Assim, o módulo `Blog` está dividido em `Admin` e `Front` submódulos. Mais uma vez, isto se refletirá nos namespaces, que serão `App\Modules\Blog\Admin\Presenters` etc. O apresentador `Dashboard` dentro do submódulo é referido como `Blog:Admin:Dashboard`.
+O módulo `Blog` é dividido em submódulos `Admin` e `Front`. Isso também se reflete nos namespaces, que aparecem como `App\UI\Blog\Admin` e similares. Para nos referirmos ao apresentador `Dashboard` dentro do submódulo `Admin`, nos referimos a ele como `Blog:Admin:Dashboard`.
+
+O aninhamento pode ser tão profundo quanto necessário, permitindo a criação de sub-submódulos.
 
-O ninho pode ir tão fundo quanto você desejar, de modo que sub-submódulos podem ser criados.
+Por exemplo, se na administração você tem muitos apresentadores relacionados ao gerenciamento de pedidos, como `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., você pode criar um módulo `Order` no qual apresentadores como `Detail`, `Edit`, `Dispatch` e outros serão organizados.
 
 
 Criação de links .[#toc-creating-links]
@@ -102,47 +118,66 @@ Ver [capítulo sobre roteamento |routing#Modules].
 Mapeamento .[#toc-mapping]
 --------------------------
 
-Define as regras pelas quais o nome da classe é derivado do nome do apresentador. Nós as escrevemos na [configuração |configuration] sob a chave `application › mapping`.
+O mapeamento define as regras para derivar o nome da classe do nome do apresentador. Essas regras são especificadas na [configuração |configuration] sob a chave `application › mapping`.
 
-Vamos começar com uma amostra que não utiliza módulos. Queremos apenas que as classes de apresentadores tenham o namespace `App\Presenters`. Isso significa que um apresentador como o `Home` deve mapear para a classe `App\Presenters\HomePresenter`. Isto pode ser conseguido através da seguinte configuração:
+As estruturas de diretório mencionadas anteriormente nesta página são baseadas no seguinte mapeamento:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-O nome do apresentador é substituído pelo asterisco na máscara da classe e o resultado é o nome da classe. Fácil!
+Como funciona o mapeamento? Para entender melhor, vamos primeiro imaginar um aplicativo sem módulos. Queremos que as classes do apresentador se enquadrem no namespace `App\UI`, de modo que o apresentador `Home` mapeie para a classe `App\UI\HomePresenter`. Isso pode ser obtido com esta configuração:
 
-Se dividirmos os apresentadores em módulos, podemos ter nosso próprio mapeamento para cada módulo:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Esse mapeamento funciona substituindo o asterisco na máscara `App\UI\*Presenter` pelo nome do apresentador `Home`, resultando no nome final da classe `App\UI\HomePresenter`. Simples!
+
+Entretanto, como você pode ver nos exemplos deste e de outros capítulos, colocamos as classes de apresentador em subdiretórios homônimos, por exemplo, o apresentador `Home` é mapeado para a classe `App\UI\Home\HomePresenter`. Isso é feito duplicando-se o asterisco (requer o Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Agora, vamos passar a mapear os apresentadores em módulos. Podemos definir mapeamentos específicos para cada módulo:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Agora o apresentador `Front:Home` mapeia para a classe `App\Modules\Front\Presenters\HomePresenter` e o apresentador `Admin:Dashboard` para a classe `App\Modules\Admin\Presenters\DashboardPresenter`.
+De acordo com essa configuração, o apresentador `Front:Home` mapeia para a classe `App\UI\Front\Home\HomePresenter`, enquanto o apresentador `Api:OAuth` mapeia para a classe `App\Api\OAuthPresenter`.
 
-É mais prático criar uma regra geral (estrela) para substituir as duas primeiras. O asterisco extra será adicionado à máscara de classe apenas para o módulo:
+Como os módulos `Front` e `Admin` têm uma abordagem de mapeamento semelhante e é provável que haja mais módulos desse tipo, é possível criar uma regra geral que os substitua. Um novo asterisco para o módulo é adicionado à máscara de classe:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Mas e se usarmos módulos aninhados e tivermos um apresentador `Admin:User:Edit`? Neste caso, o segmento com um asterisco representando o módulo para cada nível é simplesmente repetido e o resultado é a classe `App\Modules\Admin\User\Presenters\EditPresenter`.
+Para módulos aninhados em vários níveis, como o apresentador `Admin:User:Edit`, o segmento de asterisco se repete para cada nível, resultando na classe `App\UI\Admin\User\Edit\EditPresenter`.
 
-Uma notação alternativa é utilizar um conjunto composto de três segmentos em vez de um fio. Esta notação é equivalente à anterior:
+Uma notação alternativa é usar uma matriz composta de três segmentos em vez de uma cadeia de caracteres. Essa notação é equivalente à anterior:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-O valor padrão é `*: *Module\*Presenter`.
+Se tivermos apenas uma regra na configuração, a geral, podemos escrever de forma resumida:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/pt/presenters.texy b/application/pt/presenters.texy
index 58522bfda0..b6537f16c6 100644
--- a/application/pt/presenters.texy
+++ b/application/pt/presenters.texy
@@ -60,7 +60,7 @@ Semelhante ao método `render<View>()`. Enquanto `render<View>()` é destinado a
 
 É importante que `action<Action>()` é chamado antes `render<View>()`Assim, dentro dele podemos possivelmente mudar o próximo ciclo de vida, ou seja, mudar o modelo que será apresentado e também o método `render<View>()` que será chamado, usando `setView('otherView')`.
 
-Os parâmetros do pedido são passados para o método. É possível e recomendado especificar tipos para os parâmetros, por exemplo `actionShow(int $id, string $slug = null)` - se o parâmetro `id` estiver faltando ou se não for um número inteiro, o apresentador retorna o [erro 404 |#Error 404 etc.] e encerra a operação.
+Os parâmetros do pedido são passados para o método. É possível e recomendado especificar tipos para os parâmetros, por exemplo `actionShow(int $id, ?string $slug = null)` - se o parâmetro `id` estiver faltando ou se não for um número inteiro, o apresentador retorna o [erro 404 |#Error 404 etc.] e encerra a operação.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ No modelo, estas mensagens estão disponíveis na variável `$flashes` como obje
 Erro 404 etc. .[#toc-error-404-etc]
 ===================================
 
-Quando não pudermos atender ao pedido porque, por exemplo, o artigo que queremos exibir não existe no banco de dados, vamos jogar fora o erro 404 usando o método `error(string $message = null, int $httpCode = 404)`, que representa o erro HTTP 404:
+Quando não pudermos atender ao pedido porque, por exemplo, o artigo que queremos exibir não existe no banco de dados, vamos jogar fora o erro 404 usando o método `error(?string $message = null, int $httpCode = 404)`, que representa o erro HTTP 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parâmetros de solicitação .[#toc-request-parameters]
+====================================================
+
+O apresentador, assim como todos os componentes, obtém seus parâmetros da solicitação HTTP. Seus valores podem ser recuperados usando o método `getParameter($name)` ou `getParameters()`. Os valores são cadeias de caracteres ou matrizes de cadeias de caracteres, essencialmente dados brutos obtidos diretamente do URL.
+
+Para maior comodidade, recomendamos tornar os parâmetros acessíveis por meio de propriedades. Basta anotá-los com o atributo `#[Parameter]` atributo:
+
+```php
+use Nette\Application\Attributes\Parameter;  // essa linha é importante
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // deve ser pública
+}
+```
+
+Para propriedades, sugerimos especificar o tipo de dados (por exemplo, `string`). O Nette converterá automaticamente o valor com base nele. Os valores dos parâmetros também podem ser [validados |#Validation of Parameters].
+
+Ao criar um link, você pode definir diretamente o valor dos parâmetros:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Parâmetros Persistentes .[#toc-persistent-parameters]
 =====================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Se `$this->lang` tem um valor como `'en'`, então os links criados usando `link()` ou `n:href` também conterão o parâmetro `lang=en`. E quando o link for clicado, ele será novamente `$this->lang = 'en'`.
 
-Para propriedades, recomendamos que você inclua o tipo de dados (por exemplo, `string`) e você também pode incluir um valor padrão. Os valores dos parâmetros podem ser [validados |#Validation of Persistent Parameters].
+Para propriedades, recomendamos que você inclua o tipo de dados (por exemplo, `string`) e também pode incluir um valor padrão. Os valores dos parâmetros podem ser [validados |#Validation of Parameters].
 
 Parâmetros persistentes são passados por padrão entre todas as ações de um determinado apresentador. Para passá-los entre vários apresentadores, você precisa defini-los também:
 
@@ -307,18 +333,12 @@ Indo mais fundo .[#toc-going-deeper]
 O que mostramos até agora neste capítulo provavelmente será suficiente. As seguintes linhas destinam-se àqueles que estão interessados em apresentadores em profundidade e querem saber tudo.
 
 
-Requisitos e parâmetros .[#toc-requirement-and-parameters]
-----------------------------------------------------------
+Validação de parâmetros .[#toc-validation-of-parameters]
+--------------------------------------------------------
 
-O pedido tratado pelo apresentador é o objeto [api:Nette\Application\Request] e é devolvido pelo método do apresentador `getRequest()`. Ele inclui um conjunto de parâmetros e cada um deles pertence a alguns dos componentes ou diretamente ao apresentador (que na verdade é também um componente, embora especial). Assim, Nette redistribui os parâmetros e passa entre os componentes individuais (e o apresentador), chamando o método `loadState(array $params)`. Os parâmetros podem ser obtidos pelo método `getParameters(): array`, individualmente usando `getParameter($name)`. Os valores dos parâmetros são strings ou matrizes de strings, são basicamente dados brutos obtidos diretamente de uma URL.
+Os valores dos [parâmetros de solicitação |#request parameters] e dos [parâmetros persistentes |#persistent parameters] recebidos dos URLs são gravados nas propriedades pelo método `loadState()`. Ele também verifica se o tipo de dados especificado na propriedade corresponde; caso contrário, ele responderá com um erro 404 e a página não será exibida.
 
-
-Validação de Parâmetros Persistentes .[#toc-validation-of-persistent-parameters]
---------------------------------------------------------------------------------
-
-Os valores de [parâmetros persistentes |#persistent parameters] recebidos de URLs são escritos nas propriedades pelo método `loadState()`. Ele também verifica se o tipo de dados especificado na propriedade corresponde, caso contrário, responderá com um erro 404 e a página não será exibida.
-
-Nunca confie cegamente em parâmetros persistentes, pois eles podem ser facilmente sobrescritos pelo usuário no URL. Por exemplo, é assim que verificamos se `$this->lang` está entre os idiomas suportados. Uma boa maneira de fazer isso é sobrescrever o método `loadState()` mencionado acima:
+Nunca confie cegamente nos parâmetros, pois eles podem ser facilmente substituídos pelo usuário no URL. Por exemplo, é assim que verificamos se `$this->lang` está entre os idiomas suportados. Uma boa maneira de fazer isso é substituir o método `loadState()` mencionado acima:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Salvar e Restaurar o Pedido .[#toc-save-and-restore-the-request]
 ----------------------------------------------------------------
 
-Você pode salvar o pedido atual para uma sessão ou restaurá-lo da sessão e deixar o apresentador executá-lo novamente. Isto é útil, por exemplo, quando um usuário preenche um formulário e seu login expira. Para não perder dados, antes de redirecionar para a página de login, salvamos a solicitação atual para a sessão usando `$reqId = $this->storeRequest()`, que retorna um identificador na forma de uma seqüência curta e o passa como parâmetro para o apresentador de login.
+A solicitação que o apresentador trata é um objeto [api:Nette\Application\Request] e é retornada pelo método do apresentador `getRequest()`.
+
+Você pode salvar a solicitação atual em uma sessão ou restaurá-la da sessão e permitir que o apresentador a execute novamente. Isso é útil, por exemplo, quando um usuário preenche um formulário e seu login expira. Para não perder dados, antes de redirecionar para a página de login, salvamos a solicitação atual na sessão usando `$reqId = $this->storeRequest()`, que retorna um identificador na forma de uma cadeia de caracteres curta e o passa como parâmetro para o apresentador de login.
 
 Após o login, chamamos o método `$this->restoreRequest($reqId)`, que capta o pedido da sessão e o encaminha para ele. O método verifica que a solicitação foi criada pelo mesmo usuário que está agora logado. Se outro usuário faz o login ou a chave é inválida, ele não faz nada e o programa continua.
 
@@ -362,7 +384,7 @@ O redirecionamento não ocorre com um pedido AJAX ou POST porque resultaria em p
 Você também pode invocar a canonização manualmente usando o método `canonicalize()`, que, como o método `link()`, recebe o apresentador, ações e parâmetros como argumentos. Ele cria um link e o compara com a URL atual. Se for diferente, ele se redireciona para o link gerado.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// redireciona se $slug for diferente de $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Restrição de acesso usando `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+------------------------------------------------------------------------------------------------------
+
+O atributo `#[Requires]` fornece opções avançadas para restringir o acesso aos apresentadores e seus métodos. Ele pode ser usado para especificar métodos HTTP, exigir solicitações AJAX, limitar o acesso à mesma origem e restringir o acesso somente ao encaminhamento. O atributo pode ser aplicado a classes de apresentadores, bem como a métodos individuais, como `action<Action>()`, `render<View>()`, `handle<Signal>()`, e `createComponent<Name>()`.
+
+Você pode especificar essas restrições:
+- em métodos HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- que exigem uma solicitação AJAX: `#[Requires(ajax: true)]`
+- acesso somente a partir da mesma origem: `#[Requires(sameOrigin: true)]`
+- acesso somente por meio de encaminhamento: `#[Requires(forward: true)]`
+- restrições a ações específicas: `#[Requires(actions: 'default')]`
+
+Para obter detalhes, consulte [Como usar o atributo Requires |best-practices:attribute-requires].
+
+
+Verificação do método HTTP .[#toc-http-method-check]
+----------------------------------------------------
+
+No Nette, os apresentadores verificam automaticamente o método HTTP de cada solicitação recebida, principalmente por motivos de segurança. Por padrão, os métodos `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` são permitidos.
+
+Se quiser habilitar métodos adicionais, como `OPTIONS`, você pode usar o atributo `#[Requires]` (do Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Na versão 3.1, a verificação é realizada em `checkHttpMethod()`, que verifica se o método especificado na solicitação está incluído na matriz `$presenter->allowedMethods`. Adicione um método como este:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+É fundamental enfatizar que, se você habilitar o método `OPTIONS`, também deverá tratá-lo adequadamente em seu apresentador. Esse método é frequentemente usado como a chamada solicitação de preflight, que os navegadores enviam automaticamente antes da solicitação real quando é necessário determinar se a solicitação é permitida do ponto de vista da política de CORS (Cross-Origin Resource Sharing). Se você permitir esse método, mas não implementar uma resposta adequada, isso poderá gerar inconsistências e possíveis problemas de segurança.
+
+
 Leitura adicional .[#toc-further-reading]
 =========================================
 
diff --git a/application/pt/routing.texy b/application/pt/routing.texy
index 6caf887e2d..6a81076903 100644
--- a/application/pt/routing.texy
+++ b/application/pt/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Notação avançada .[#toc-advanced-notation]
 ------------------------------------------
 
-O segundo parâmetro da rota, que freqüentemente escrevemos no formato `Presenter:action`, é uma abreviação, que também podemos escrever na forma de um campo, onde indicamos diretamente os valores (padrão) dos parâmetros individuais:
+O destino de uma rota, geralmente escrito no formato `Presenter:action`, também pode ser expresso usando uma matriz que define parâmetros individuais e seus valores padrão:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Ou podemos usar este formulário, observando a reescrita da expressão regular de validação:
+Para uma especificação mais detalhada, é possível usar um formulário ainda mais extenso, no qual, além dos valores padrão, outras propriedades de parâmetro podem ser definidas, como uma expressão regular de validação (consulte o parâmetro `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Estes formatos mais faladores são úteis para adicionar outros metadados.
+É importante observar que, se os parâmetros definidos na matriz não estiverem incluídos na máscara de caminho, seus valores não poderão ser alterados, nem mesmo usando parâmetros de consulta especificados após um ponto de interrogação no URL.
 
 
 Filtros e Traduções .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integração .[#toc-integration]
 ==============================
 
-A fim de conectar nosso roteador à aplicação, devemos informar o recipiente DI sobre isso. A maneira mais fácil é preparar a fábrica que irá construir o objeto roteador e dizer à configuração do contêiner para usá-lo. Portanto, digamos que escrevemos um método para este fim `App\Router\RouterFactory::createRouter()`:
+A fim de conectar nosso roteador à aplicação, devemos informar o recipiente DI sobre isso. A maneira mais fácil é preparar a fábrica que irá construir o objeto roteador e dizer à configuração do contêiner para usá-lo. Portanto, digamos que escrevemos um método para este fim `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Em seguida, escrevemos em [configuração |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Quaisquer dependências, tais como uma conexão de banco de dados, etc., são passadas para o método de fábrica como seus parâmetros usando [a fiação automática |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Por uso separado, entendemos o uso das capacidades do roteador em uma aplicaçã
 Assim, mais uma vez, criaremos um método que construirá um roteador, por exemplo:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Ou criaremos objetos diretamente:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/pt/templates.texy b/application/pt/templates.texy
index 059e35178e..2886c6740e 100644
--- a/application/pt/templates.texy
+++ b/application/pt/templates.texy
@@ -34,35 +34,81 @@ E este poderia ser o modelo de ação:
 Ele define o bloco `content`, que é inserido no lugar de `{include content}` no layout, e também redefine o bloco `title`, que sobrescreve `{block title}` no layout. Tente imaginar o resultado.
 
 
-Busca de modelos .[#toc-search-for-templates]
----------------------------------------------
+Pesquisa de modelos .[#toc-template-lookup]
+-------------------------------------------
 
-O caminho para os modelos é deduzido de acordo com uma lógica simples. Ele tenta ver se um destes arquivos de gabaritos existe em relação ao diretório onde se encontra a classe apresentadora, onde `<Presenter>` é o nome do atual apresentador e `<view>` é o nome da ação atual:
+Nos apresentadores, você não precisa especificar qual modelo deve ser renderizado; a estrutura determinará automaticamente o caminho, facilitando a codificação para você.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Se você usar uma estrutura de diretórios em que cada apresentador tenha seu próprio diretório, basta colocar o modelo nesse diretório com o nome da ação (ou seja, visualização). Por exemplo, para a ação `default`, use o modelo `default.latte`:
 
-Se o modelo não for encontrado, ele tentará procurar no diretório `templates` um nível acima, ou seja, no mesmo nível que o diretório com a classe apresentadora.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Se o modelo também não for encontrado lá, a resposta é um [erro 404 |presenters#Error 404 etc.].
+Se você usar uma estrutura em que os apresentadores estejam juntos em um diretório e os modelos em uma pasta `templates`, salve-os em um arquivo `<Presenter>.<view>.latte` ou `<Presenter>/<view>.latte`:
 
-Você também pode mudar a visão usando `$this->setView('otherView')`. Ou, em vez de procurar, especifique diretamente o nome do arquivo modelo usando `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+O diretório `templates` também pode ser colocado um nível acima, no mesmo nível do diretório com as classes de apresentador.
+
+Se o modelo não for encontrado, o apresentador responderá com o [erro 404 - página não encontrada |presenters#Error 404 etc].
+
+Você pode alterar a visualização usando `$this->setView('anotherView')`. Também é possível especificar diretamente o arquivo de modelo com `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Você pode alterar os caminhos onde os modelos são pesquisados substituindo o método de [formataçãoTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que retorna um conjunto de possíveis caminhos de arquivos.
+Os arquivos onde os modelos são pesquisados podem ser alterados substituindo o método [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que retorna uma matriz de possíveis nomes de arquivos.
+
+
+Pesquisa de modelos de layout .[#toc-layout-template-lookup]
+------------------------------------------------------------
+
+O Nette também procura automaticamente o arquivo de layout.
+
+Se você usar uma estrutura de diretórios em que cada apresentador tenha seu próprio diretório, coloque o layout na pasta com o apresentador, se for específico apenas para ele, ou em um nível superior, se for comum a vários apresentadores:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Se você usar uma estrutura em que os apresentadores estejam agrupados em um diretório e os modelos estejam em uma pasta `templates`, o layout será esperado nos seguintes locais:
 
-O layout é esperado nos seguintes arquivos:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` layout comum a vários apresentadores
+Se o apresentador estiver em um [módulo |modules], ele também pesquisará mais acima na árvore de diretórios, de acordo com o aninhamento do módulo.
 
-`<Presenter>` é o nome do atual apresentador e `<layout>` é o nome do layout, que é, por padrão, `'layout'`. O nome pode ser alterado com `$this->setLayout('otherLayout')`, para que os arquivos `@otherLayout.latte` sejam experimentados.
+O nome do layout pode ser alterado usando `$this->setLayout('layoutAdmin')` e, em seguida, ele será esperado no arquivo `@layoutAdmin.latte`. Você também pode especificar diretamente o arquivo de modelo de layout usando `$this->setLayout('/path/to/template.latte')`.
 
-Você também pode especificar diretamente o nome do arquivo do modelo de layout usando `$this->setLayout('/path/to/template.latte')`. O uso do `$this->setLayout(false)` desabilitará a busca do layout.
+O uso de `$this->setLayout(false)` ou da tag `{layout none}` dentro do modelo desativa a pesquisa de layout.
 
 .[note]
-Você pode alterar os caminhos onde os modelos são pesquisados, substituindo o método [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que retorna uma série de possíveis caminhos de arquivos.
+Os arquivos em que os modelos de layout são pesquisados podem ser alterados substituindo o método [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que retorna uma matriz de possíveis nomes de arquivos.
 
 
 Variáveis no modelo .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ A anotação `@property-read` é para IDE e análise estática, fará com que o
 Você também pode se dar ao luxo de sussurrar nos modelos, basta instalar o plugin Latte no PhpStorm e especificar o nome da classe no início do modelo, veja o artigo "Latte: como digitar sistema":https://blog.nette.org/pt/latte-como-usar-o-sistema-de-tipo:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 A versão 3 do Latte oferece uma maneira mais avançada, criando uma [extensão |latte:creating-extension] para cada projeto web. Aqui está um exemplo rudimentar de tal classe:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ Registramos usando [a configuração#Latte |configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternativamente, o tradutor pode ser definido usando a [configuração |configu
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 O tradutor pode então ser usado, por exemplo, como um filtro `|translate`, com parâmetros adicionais passados para o método `translate()` (ver `foo, bar`):
diff --git a/application/ro/@home.texy b/application/ro/@home.texy
index 8a8c11fbf4..5dfe0522dc 100644
--- a/application/ro/@home.texy
+++ b/application/ro/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | versiune | compatibil cu PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 - 8.2
-| Nette Application 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/ro/ajax.texy b/application/ro/ajax.texy
index 145ab87fdd..03eec3fac5 100644
--- a/application/ro/ajax.texy
+++ b/application/ro/ajax.texy
@@ -3,10 +3,10 @@ AJAX & Snippets
 
 <div class=perex>
 
-În prezent, aplicațiile web moderne rulează pe jumătate pe un server și pe jumătate în browser. AJAX este un factor vital de unificare. Ce suport oferă Nette Framework?
-- trimiterea de fragmente de șabloane (așa-numitele *snippets*)
+În era aplicațiilor web moderne, în care funcționalitatea se întinde adesea între server și browser, AJAX este un element de legătură esențial. Ce opțiuni oferă Nette Framework în acest domeniu?
+- trimiterea unor părți din șablon, așa-numitele snippet-uri
 - transmiterea de variabile între PHP și JavaScript
-- depanarea aplicațiilor AJAX
+- instrumente de depanare a cererilor AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ AJAX & Snippets
 Cerere AJAX .[#toc-ajax-request]
 ================================
 
-O cerere AJAX nu diferă de o cerere clasică - prezentatorul este apelat cu o vizualizare și parametri specifici. De asemenea, este la latitudinea prezentatorului cum să răspundă la aceasta: poate utiliza propria rutină, care returnează un fragment de cod HTML (fragment HTML), un document XML, un obiect JSON sau cod JavaScript.
+O cerere AJAX nu diferă în mod fundamental de o cerere HTTP clasică. Un prezentator este apelat cu parametri specifici. Depinde de prezentator cum să răspundă la cerere - acesta poate returna date în format JSON, poate trimite o parte din codul HTML, un document XML etc.
 
-Pe partea serverului, o cerere AJAX poate fi detectată cu ajutorul metodei de serviciu care [încapsulează cererea HTTP |http:request] `$httpRequest->isAjax()` (detectează pe baza antetului HTTP `X-Requested-With`). În interiorul prezentatorului, este disponibilă o scurtătură sub forma metodei `$this->isAjax()`.
+Pe partea de browser, inițiem o cerere AJAX utilizând funcția `fetch()`:
 
-Există un obiect preprocesat numit `payload` dedicat trimiterii de date către browser în JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// prelucrarea răspunsului
+});
 ```
 
-Pentru un control complet asupra ieșirii JSON, utilizați metoda `sendJson` în prezentator. Aceasta termină imediat presenterul și vă veți descurca fără șablon:
+Pe partea serverului, o cerere AJAX este recunoscută de metoda `$httpRequest->isAjax()` a serviciului [care încapsulează cererea HTTP |http:request]. Aceasta utilizează antetul HTTP `X-Requested-With`, deci este esențial să o trimitem. În cadrul prezentatorului, puteți utiliza metoda `$this->isAjax()`.
+
+Dacă doriți să trimiteți date în format JSON, utilizați metoda [`sendJson()` |presenters#Sending a response] metoda . Metoda încheie, de asemenea, activitatea prezentatorului.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Dacă dorim să trimitem HTML, putem fie să setăm un șablon special pentru cererile AJAX:
+Dacă intenționați să răspundeți cu un șablon special conceput pentru AJAX, puteți face acest lucru după cum urmează:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Fragmente .[#toc-snippets]
+==========================
+
+Cel mai puternic instrument oferit de Nette pentru conectarea serverului cu clientul sunt snippets. Cu ajutorul acestora, puteți transforma o aplicație obișnuită într-una AJAX cu un efort minim și câteva linii de cod. Exemplul Fifteen demonstrează cum funcționează totul, iar codul său poate fi găsit pe [GitHub |https://github.com/nette-examples/fifteen].
+
+Snippets, sau clippings, vă permit să actualizați doar părți ale paginii, în loc să reîncărcați întreaga pagină. Acest lucru este mai rapid și mai eficient și oferă, de asemenea, o experiență mai confortabilă pentru utilizator. Snippets s-ar putea să vă amintească de Hotwire pentru Ruby on Rails sau Symfony UX Turbo. Interesant este că Nette a introdus snippets cu 14 ani mai devreme.
+
+Cum funcționează snippets? Atunci când pagina este încărcată pentru prima dată (o cerere non-AJAX), se încarcă întreaga pagină, inclusiv toate snippet-urile. Atunci când utilizatorul interacționează cu pagina (de exemplu, face clic pe un buton, trimite un formular etc.), în loc să se încarce întreaga pagină, se face o cerere AJAX. Codul din prezentator execută acțiunea și decide ce fragmente trebuie actualizate. Nette redă aceste fragmente și le trimite sub forma unei matrice JSON. Codul de manipulare din browser inserează apoi fragmentele primite înapoi în pagină. Prin urmare, este transferat doar codul fragmentelor modificate, ceea ce permite economisirea lățimii de bandă și accelerarea încărcării în comparație cu transferul întregului conținut al paginii.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
- [Librăria Naja |https://naja.js.org] este utilizată pentru a gestiona cererile AJAX din partea browserului. [Instalați-o |https://naja.js.org/#/guide/01-install-setup-naja] ca un pachet node.js (pentru a o utiliza cu Webpack, Rollup, Vite, Parcel și altele):
+Pentru a gestiona fragmente de text în browser, se utilizează [biblioteca Naja |https://naja.js.org]. [Instalați-o |https://naja.js.org/#/guide/01-install-setup-naja] ca un pachet node.js (pentru a fi utilizată cu aplicații precum Webpack, Rollup, Vite, Parcel și altele):
 
 ```shell
 npm install naja
 ```
 
-...sau inserați-o direct în șablonul de pagină:
+... sau inserați-o direct în șablonul de pagină:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Pentru a crea o solicitare AJAX dintr-un link obișnuit (semnal) sau un formular de trimitere, trebuie doar să marcați link-ul, formularul sau butonul respectiv cu clasa `ajax`:
+Mai întâi trebuie să [inițializați |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] biblioteca:
+
+```js
+naja.initialize();
+```
+
+Pentru a transforma un link obișnuit (semnal) sau un formular de trimitere într-o cerere AJAX, este suficient să marcați link-ul, formularul sau butonul respectiv cu clasa `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Pentru a crea o solicitare AJAX dintr-un link obișnuit (semnal) sau un formular
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Snippets .[#toc-snippets]
-=========================
-
-Există un instrument mult mai puternic de suport AJAX încorporat - snippets. Utilizarea acestora face posibilă transformarea unei aplicații obișnuite într-una AJAX folosind doar câteva linii de cod. Modul în care funcționează totul este demonstrat în exemplul Fifteen, al cărui cod este, de asemenea, accesibil în build sau pe [GitHub |https://github.com/nette-examples/fifteen].
-
-Modul în care funcționează snippet-urile este că întreaga pagină este transferată în timpul cererii inițiale (adică non-AJAX) și apoi, la fiecare [subcerere |components#signal] AJAX (cerere a aceleiași vizualizări a aceluiași prezentator), doar codul părților modificate este transferat în depozitul `payload` menționat anterior.
-
-Snippets vă poate aminti de Hotwire pentru Ruby on Rails sau de Symfony UX Turbo, dar Nette a venit cu ele cu paisprezece ani mai devreme.
-
-
-Invalidarea Snippets .[#toc-invalidation-of-snippets]
-=====================================================
+Redesenarea fragmentelor .[#toc-redrawing-snippets]
+---------------------------------------------------
 
-Fiecare descendent al clasei [Control |components] (care este, de asemenea, un prezentator) este capabil să își amintească dacă au existat modificări în timpul unei solicitări care să necesite o nouă redare. Există o pereche de metode pentru a gestiona acest lucru: `redrawControl()` și `isControlInvalid()`. Un exemplu:
+Fiecare obiect al clasei [Control |components] (inclusiv prezentatorul însuși) păstrează o evidență a modificărilor care au avut loc și care necesită redesenarea sa. Metoda `redrawControl()` este utilizată în acest scop.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Obiectul trebuie să se redea după ce utilizatorul s-a logat
+	// după logare, este necesar să se redeseneze partea relevantă
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette oferă însă o rezoluție și mai fină decât componentele întregi. Metodele enumerate acceptă ca parametru opțional numele unui așa-numit "snippet". Un "snippet" este practic un element din șablonul dvs. marcat în acest scop de o etichetă Latte, mai multe detalii în continuare. Astfel, este posibil să cereți unei componente să redeseneze doar *părți* din șablonul său. Dacă întreaga componentă este invalidată, atunci toate "snippet-urile" sale sunt reredimensionate. O componentă este "invalidată" și dacă oricare dintre subcomponentele sale este invalidată.
 
-```php
-$this->isControlInvalid(); // -> fals
-
-$this->redrawControl('header'); // invalidează fragmentul numit "header
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, cel puțin un fragment este invalidat
+Nette permite, de asemenea, un control mai fin al elementelor care trebuie redesenate. Metoda menționată mai sus poate primi ca argument numele fragmentului. Astfel, este posibil să se invalideze (adică să se forțeze o redesenare) la nivelul părții de șablon. În cazul în care întreaga componentă este invalidată, fiecare fragment din aceasta este, de asemenea, redesenat:
 
-$this->redrawControl(); // invalidează întreaga componentă, fiecare fragment
-$this->isControlInvalid('footer'); // -> true
+```php
+// invalidează fragmentul de "antet
+$this->redrawControl('header');
 ```
 
-O componentă care primește un semnal este marcată automat pentru redesenare.
-
-Mulțumită redimensionării fragmentelor, știm exact ce părți din ce elemente trebuie redimensionate.
-
 
-Etichetă `{snippet} … {/snippet}` .{toc: Tag snippet}
-=====================================================
+Fragmente în Latte .[#toc-snippets-in-latte]
+--------------------------------------------
 
-Redarea paginii se desfășoară în mod similar cu o cerere obișnuită: sunt încărcate aceleași șabloane etc. Partea vitală este, totuși, să se lase deoparte părțile care nu trebuie să ajungă la ieșire; celelalte părți trebuie asociate cu un identificator și trimise utilizatorului într-un format inteligibil pentru un manipulator JavaScript.
-
-
-Sintaxa .[#toc-syntax]
-----------------------
-
-Dacă există un control sau un fragment în șablon, trebuie să îl înfășurăm cu ajutorul etichetei `{snippet} ... {/snippet}` - aceasta se va asigura că fragmentul redat va fi "tăiat" și trimis către browser. De asemenea, acesta va fi inclus într-un helper `<div>` (este posibil să se folosească o altă etichetă). În exemplul următor este definit un fragment numit `header`. Acesta poate reprezenta la fel de bine șablonul unei componente:
+Utilizarea snippet-urilor în Latte este extrem de ușoară. Pentru a defini o parte a șablonului ca fiind un snippet, este suficient să o înfășurați în etichetele `{snippet}` și `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Dacă există un control sau un fragment în șablon, trebuie să îl înfășur
 {/snippet}
 ```
 
-Un fragment de alt tip decât `<div>` sau un fragment cu atribute HTML suplimentare se obține prin utilizarea variantei de atribut:
+Snippet-ul creează un element `<div>` în pagina HTML cu o etichetă special generată `id`. Atunci când se redesenează un fragment, conținutul acestui element este actualizat. Prin urmare, atunci când pagina este redată inițial, toate fragmentele trebuie, de asemenea, redate, chiar dacă acestea pot fi inițial goale.
+
+De asemenea, puteți crea un fragment cu un alt element decât `<div>` utilizând un atribut n::
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Un fragment de alt tip decât `<div>` sau un fragment cu atribute HTML supliment
 ```
 
 
-Snippets dinamice .[#toc-dynamic-snippets]
-==========================================
+Zone de fragmente .[#toc-snippet-areas]
+---------------------------------------
 
-În Nette puteți defini, de asemenea, fragmente cu un nume dinamic bazat pe un parametru de execuție. Acest lucru este cel mai potrivit pentru diverse liste în cazul în care trebuie să modificăm doar un singur rând, dar nu dorim să transferăm întreaga listă odată cu el. Un exemplu în acest sens ar fi:
+Numele snippet-urilor pot fi, de asemenea, expresii:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Există un fragment static numit `itemsContainer`, care conține mai multe fragmente dinamice: `item-0`, `item-1` și așa mai departe.
+În acest fel, vom obține mai multe fragmente precum `item-0`, `item-1`, etc. Dacă ar fi să invalidăm direct un fragment dinamic (de exemplu, `item-1`), nimic nu ar fi redesenat. Motivul este că snippet-urile funcționează ca adevărate extrase și doar ele însele sunt redate direct. Cu toate acestea, în șablon, nu există, din punct de vedere tehnic, un fragment numit `item-1`. Acesta apare doar atunci când se execută codul care înconjoară fragmentul, în acest caz, bucla foreach. Prin urmare, vom marca partea din șablon care trebuie executată cu eticheta `{snippetArea}`:
 
-Nu puteți redesena direct un fragment dinamic (redesenarea lui `item-1` nu are niciun efect), ci trebuie să redesenați fragmentul său părinte (în acest exemplu `itemsContainer`). Acest lucru determină executarea codului snippet-ului părinte, dar apoi doar sub-snippet-urile sale sunt trimise către browser. Dacă doriți să trimiteți doar unul dintre sub-snippet-uri, trebuie să modificați intrarea pentru snippet-ul părinte pentru a nu genera celelalte sub-snippet-uri.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-În exemplul de mai sus, trebuie să vă asigurați că, pentru o cerere AJAX, doar un singur element va fi adăugat la matricea `$list`, prin urmare, bucla `foreach` va imprima doar un singur fragment dinamic.
+Și vom redesena atât fragmentul individual, cât și întreaga zonă de ansamblu:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+De asemenea, este esențial să ne asigurăm că matricea `$items` conține doar elementele care trebuie redesenate.
 
-Fragmente într-un șablon inclus .[#toc-snippets-in-an-included-template]
-========================================================================
-
-Se poate întâmpla ca fragmentul să se afle într-un șablon care este inclus dintr-un alt șablon. În acest caz, trebuie să înfășurăm codul de includere în cel de-al doilea șablon cu eticheta `snippetArea`, apoi redesenăm atât snippetArea, cât și fragmentul propriu-zis.
-
-Eticheta `snippetArea` asigură că codul din interior este executat, dar numai fragmentul real din șablonul inclus este trimis către browser.
+Atunci când se inserează un alt șablon în șablonul principal folosind eticheta `{include}`, care are fragmente, este necesar să se înfășoare din nou șablonul inclus într-un `snippetArea` și să se invalideze atât fragmentul, cât și zona împreună:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* copil.latte *}
+{* inclus.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-De asemenea, îl puteți combina cu snippet-uri dinamice.
 
+Snippets în componente .[#toc-snippets-in-components]
+-----------------------------------------------------
 
-Adăugarea și ștergerea .[#toc-adding-and-deleting]
-==================================================
-
-Dacă adăugați un nou element în listă și invalidați `itemsContainer`, cererea AJAX returnează fragmente, inclusiv pe cel nou, dar gestionarul javascript nu va putea să îl redea. Acest lucru se datorează faptului că nu există un element HTML cu ID-ul nou creat.
-
-În acest caz, cea mai simplă metodă este de a îngloba întreaga listă într-un alt fragment și de a-l invalida pe tot:
+Puteți crea fragmente în cadrul [componentelor |components], iar Nette le va redesena automat. Cu toate acestea, există o limitare specifică: pentru a redesena snippets, se apelează metoda `render()` fără niciun parametru. Astfel, trecerea parametrilor în șablon nu va funcționa:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Trimiterea datelor de utilizator .[#toc-sending-user-data]
+----------------------------------------------------------
+
+Împreună cu fragmente, puteți trimite orice date suplimentare către client. Pur și simplu scrieți-le în obiectul `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Același lucru este valabil și pentru ștergerea unui element. Ar fi posibil să se trimită un fragment gol, dar, de obicei, listele pot fi paginate și ar fi complicat să se implementeze ștergerea unui element și încărcarea altuia (care se afla pe o pagină diferită a listei paginate).
 
+Parametrii de trimitere .[#toc-sending-parameters]
+==================================================
 
-Trimiterea parametrilor către componentă .[#toc-sending-parameters-to-component]
-================================================================================
-
-Atunci când trimitem parametrii către componentă prin intermediul unei cereri AJAX, fie că este vorba de parametri de semnal sau de parametri persistenți, trebuie să furnizăm numele global al acestora, care conține și numele componentei. Numele complet al parametrului returnează metoda `getParameterId()`.
+Atunci când trimitem parametrii către componentă prin intermediul unei cereri AJAX, fie că este vorba de parametri de semnal sau de parametri persistenți, trebuie să furnizăm numele lor global, care conține și numele componentei. Numele complet al parametrului returnează metoda `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Și gestionează metoda cu s parametrii corespunzători în componentă.
+O metodă handle cu parametrii corespunzători din componentă:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/ro/bootstrap.texy b/application/ro/bootstrap.texy
index def23eed0e..97b1a1fe30 100644
--- a/application/ro/bootstrap.texy
+++ b/application/ro/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Configuratorul este responsabil de configurarea mediului și a serviciilor aplicației.
+		$this->configurator = new Configurator;
+		// Setați directorul pentru fișierele temporare generate de Nette (de exemplu, șabloane compilate)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette este inteligent, iar modul de dezvoltare se activează automat,
+		// sau îl puteți activa pentru o anumită adresă IP prin decomentarea următoarei linii:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Activează Tracy: instrumentul suprem de depanare "swiss army knife".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: Încarcă automat toate clasele din directorul dat
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Încarcă fișierele de configurare
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-În cazul aplicațiilor web, fișierul inițial este `index.php`, care se află în directorul public `www/`. Acesta permite clasei `Bootstrap` să inițializeze mediul și să returneze `$configurator` care creează containerul DI. Apoi se obține serviciul `Application`, care execută aplicația web:
+Fișierul inițial pentru aplicațiile web este `index.php`, situat în directorul public `www/`. Acesta utilizează clasa `Bootstrap` pentru a inițializa mediul și a crea un container DI. Apoi, obține serviciul `Application` din container, care lansează aplicația web:
 
 ```php
-// inițializarea mediului + obținerea obiectului Configurator
-$configurator = App\Bootstrap::boot();
-// creați un container DI
-$container = $configurator->createContainer();
-// containerul DI creează un obiect Nette\Application\Application
+$bootstrap = new App\Bootstrap;
+// Inițializarea mediului + crearea unui container DI
+$container = $bootstrap->bootWebApplication();
+// Containerul DI creează un obiect Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// pornește aplicația Nette
+// Porniți aplicația Nette și tratați cererea de intrare
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Selectarea modului se face prin autodetecție, astfel încât, de obicei, nu est
 Dacă doriți să activați modul de dezvoltare în alte cazuri, de exemplu, pentru programatorii care accesează de la o anumită adresă IP, puteți utiliza `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // una sau mai multe adrese IP
+$this->configurator->setDebugMode('23.75.345.200'); // una sau mai multe adrese IP
 ```
 
 Vă recomandăm cu siguranță să combinați o adresă IP cu un cookie. Vom stoca un token secret în cookie-ul `nette-debug`, de exemplu `secret1234`, iar modul de dezvoltare va fi activat pentru programatorii cu această combinație de IP și cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 De asemenea, putem dezactiva complet modul de dezvoltare, chiar și pentru localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Rețineți că valoarea `true` activează modul dezvoltator din greu, ceea ce nu ar trebui să se întâmple niciodată pe un server de producție.
@@ -90,7 +115,7 @@ Instrumentul de depanare Tracy .[#toc-debugging-tool-tracy]
 Pentru o depanare mai ușoară, vom porni minunata unealtă [Tracy |tracy:]. În modul dezvoltator, acesta vizualizează erorile, iar în modul de producție înregistrează erorile în directorul specificat:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Temporary Files .[#toc-temporary-files]
 Nette utilizează memoria cache pentru DI container, RobotLoader, șabloane etc. Prin urmare, este necesar să setați calea către directorul în care va fi stocată memoria cache:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Pe Linux sau macOS, setați [permisiunile de scriere |nette:troubleshooting#Setting directory permissions] pentru directoarele `log/` și `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 De obicei, vom dori să încărcăm automat clasele folosind [RobotLoader |robot-loader:], așa că trebuie să îl pornim și să îl lăsăm să încarce clasele din directorul în care se află `Bootstrap.php` (adică `__DIR__`) și din toate subdirectoarele sale:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Fusul orar .[#toc-timezone]
 Configurator vă permite să specificați un fus orar pentru aplicația dumneavoastră.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ Fișierele de configurare sunt de obicei scrise în [formatul NEON |neon:format]
 Fișierele de configurare sunt încărcate utilizând `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Metoda `addConfig()` poate fi apelată de mai multe ori pentru a adăuga mai multe fișiere.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Parametrii statici .[#toc-static-parameters]
 Parametrii utilizați în fișierele de configurare pot fi definiți [în secțiunea `parameters` |dependency-injection:configuration#parameters] și, de asemenea, pot fi trecuți (sau suprascriși) prin metoda `addStaticParameters()` (are pseudonimul `addParameters()`). Este important ca valorile diferite ale parametrilor să determine generarea de containere DI suplimentare, adică de clase suplimentare.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Parametrii dinamici .[#toc-dynamic-parameters]
 De asemenea, putem adăuga parametri dinamici la container, valorile lor diferite, spre deosebire de parametrii statici, nu vor determina generarea de noi containere DI.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Variabilele de mediu ar putea fi puse cu ușurință la dispoziție prin intermediul parametrilor dinamici. Le putem accesa prin intermediul `%env.variable%` în fișierele de configurare.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Puteți utiliza următorii parametri statici în fișierele de configurare:
 - `%wwwDir%` este calea absolută către directorul care conține fișierul de intrare `index.php`
 - `%tempDir%` este calea absolută către directorul pentru fișierele temporare
 - `%vendorDir%` este calea absolută către directorul în care Composer instalează bibliotecile
+- `%rootDir%` este calea absolută către directorul rădăcină al proiectului
 - `%debugMode%` indică dacă aplicația se află în modul de depanare
 - `%consoleMode%` indică dacă cererea a venit prin linia de comandă
 
@@ -225,7 +252,7 @@ services:
 Creați o nouă instanță și inserați-o în bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Diferite medii .[#toc-different-environments]
 =============================================
 
-Nu ezitați să personalizați clasa `Bootstrap` pentru a se potrivi nevoilor dumneavoastră. Puteți adăuga parametri la metoda `boot()` pentru a diferenția proiectele web sau puteți adăuga alte metode, cum ar fi `bootForTests()`, care inițializează mediul pentru testele unitare, `bootForCli()` pentru scripturile apelate din linia de comandă și așa mai departe.
+Nu ezitați să personalizați clasa `Bootstrap` în funcție de nevoile dumneavoastră. Puteți adăuga parametri la metoda `bootWebApplication()` pentru a face diferența între proiectele web. Alternativ, puteți adăuga alte metode, cum ar fi `bootTestEnvironment()` pentru a inițializa mediul pentru testele unitare, `bootConsoleApplication()` pentru scripturile apelate din linia de comandă și așa mai departe.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
 {
-	$configurator = self::boot();
 	Tester\Environment::setup(); // Inițializarea Nette Tester
-	return $configurator;
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
+{
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/ro/components.texy b/application/ro/components.texy
index 13ee93eb88..1d48351bbd 100644
--- a/application/ro/components.texy
+++ b/application/ro/components.texy
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // și redirecționarea
 ```
 
 
+Redirecționarea după un semnal .[#toc-redirection-after-a-signal]
+=================================================================
+
+După procesarea unui semnal de componentă, urmează adesea redirecționarea. Această situație este similară formularelor - după trimiterea unui formular, redirecționăm, de asemenea, pentru a preveni retrimiterea datelor atunci când pagina este reîmprospătată în browser.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Deoarece o componentă este un element reutilizabil și de obicei nu ar trebui să aibă o dependență directă de anumiți prezentatori, metodele `redirect()` și `link()` interpretează automat parametrul ca fiind un semnal de componentă:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Dacă trebuie să redirecționați către un alt prezentator sau acțiune, puteți face acest lucru prin intermediul prezentatorului:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Parametrii persistenți .[#toc-persistent-parameters]
 ====================================================
 
@@ -347,7 +369,7 @@ services:
 În cele din urmă, vom utiliza această fabrică în prezentatorul nostru:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Componente în profunzime .[#toc-components-in-depth]
 Componentele într-o aplicație Nette sunt părțile reutilizabile ale unei aplicații web pe care le încorporăm în pagini, care reprezintă subiectul acestui capitol. Care sunt mai exact capacitățile unei astfel de componente?
 
 1) este redabilă într-un șablon
-2) știe ce parte din ea însăși trebuie să redea în timpul unei [cereri AJAX |ajax#invalidation] (fragmente)
+2) știe [ce parte din el însuși |ajax#snippets] să redea în timpul unei cereri AJAX (fragmente)
 3) are capacitatea de a stoca starea sa într-un URL (parametri persistenți)
 4) are capacitatea de a răspunde la acțiunile utilizatorului (semnale)
 5) creează o structură ierarhică (în care rădăcina este prezentatorul)
diff --git a/application/ro/configuration.texy b/application/ro/configuration.texy
index e1ce662525..d5965b0e36 100644
--- a/application/ro/configuration.texy
+++ b/application/ro/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# afișează panoul "Nette Application" în Tracy BlueScreen?
 	debugger: ...           # (bool) valoarea implicită este true
 
-	# error-presenter va fi apelat în caz de eroare?
-	catchExceptions: ...    # (bool) implicit la true în modul de producție
+	# va fi apelat error-presenter la eroare?
+	# are efect numai în modul dezvoltator
+	catchExceptions: ...    # (bool) implicit la true
 
 	# numele prezentatorului de erori
-	errorPresenter: Error   # (string) valoarea implicită este "Nette:Error" (Nette:Error)
+	errorPresenter: Error   # (string|array) valoarea implicită este "Nette:Error" (Nette:Error)
+
+	# definește pseudonimele pentru prezentatori și evenimente
+	aliases: ...
 
 	# definește regulile de rezolvare a numelui prezentatorului la o clasă
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) valoarea implicită este false
 ```
 
-Deoarece error-presenters nu este apelat în mod implicit în modul de dezvoltare, iar erorile sunt afișate de Tracy, schimbarea valorii `catchExceptions` în `true` ajută la verificarea funcționării corecte a error-presenters în timpul dezvoltării.
+Începând cu `nette/application` versiunea 3.2, este posibilă definirea unei perechi de prezentatori de erori:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # pentru Nette\Application\BadRequestException
+		5xx: Error5xx   # pentru alte excepții
+```
 
 Opțiunea `silentLinks` determină modul în care se comportă Nette în modul de dezvoltare atunci când generarea legăturilor eșuează (de exemplu, pentru că nu există un prezentator etc.). Valoarea implicită `false` înseamnă că Nette declanșează `E_USER_WARNING`. Setarea la `true` suprimă acest mesaj de eroare. Într-un mediu de producție, `E_USER_WARNING` este întotdeauna invocat. De asemenea, putem influența acest comportament prin setarea variabilei presenter [$invalidLinkMode |creating-links#Invalid Links].
 
+[Pseudonimele simplifică trimiterea |creating-links#aliases] la prezentatorii utilizați frecvent.
+
  [Cartografierea definește regulile |modules#mapping] prin care numele clasei este derivat din numele prezentatorului.
 
 
@@ -82,6 +95,9 @@ latte:
 	# activează [verificarea codului generat |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) implicit este null
 
+	# stabilește localul
+	locale: cs_CZ        # (string) implicit este nul
+
 	# clasa lui $this->template
 	templateClass: App\MyTemplateClass # valoarea implicită este Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Dacă utilizați Latte versiunea 3, puteți adăuga o nouă [extensie |latte:cre
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/ro/creating-links.texy b/application/ro/creating-links.texy
index 659cc88a08..187cb01adf 100644
--- a/application/ro/creating-links.texy
+++ b/application/ro/creating-links.texy
@@ -38,7 +38,7 @@ De asemenea, este posibil să se treacă parametri numiți. Următoarea legătur
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-În cazul în care metoda `ProductPresenter::renderShow()` nu are `$lang` în semnătura sa, aceasta poate citi valoarea parametrului folosind `$lang = $this->getParameter('lang')`.
+În cazul în care metoda `ProductPresenter::renderShow()` nu are `$lang` în semnătura sa, aceasta poate prelua valoarea parametrului folosind `$lang = $this->getParameter('lang')` sau din [proprietate |presenters#Request Parameters].
 
 În cazul în care parametrii sunt stocați într-o matrice, aceștia pot fi dezvoltați cu operatorul `...` (sau cu operatorul `(expand)` în Latte 2.x):
 
@@ -140,7 +140,7 @@ Obiectivul `this` va crea un link către pagina curentă:
 <a n:href="this">refresh</a>
 ```
 
-În același timp, toți parametrii specificați în semnătura de la `render<View>()` sau `action<Action>()` sunt transferați. Astfel, dacă ne aflăm pe paginile `Product:show` și `id:123`, legătura către `this` va transfera și acest parametru.
+În același timp, toți parametrii specificați în semnătura `action<Action>()` sau `render<View>()` în cazul în care metoda `action<Action>()` nu este definită, sunt transferați. Astfel, dacă ne aflăm pe paginile `Product:show` și `id:123`, legătura către `this` va transfera și acest parametru.
 
 Desigur, este posibil să se specifice parametrii direct:
 
@@ -213,7 +213,7 @@ Deoarece [componentele |components] sunt unități separate reutilizabile care n
 Dacă dorim să facem legătura cu prezentatorii din șablonul componentei, folosim eticheta `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 sau în cod
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Aliasuri .[#toc-aliases]{data-version:v3.2.2}
+=============================================
+
+Uneori este util să atribuiți un pseudonim ușor de memorat unei perechi prezentator:acțiune. De exemplu, ați putea numi pagina de pornire `Front:Home:default` simplu `home` sau `Admin:Dashboard:default` `admin` .
+
+Aliasurile sunt definite în [configurație |configuration] sub cheia `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+În legături, acestea se scriu folosind simbolul at, de exemplu:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Acestea sunt acceptate în toate metodele care lucrează cu legături, cum ar fi `redirect()` și altele similare.
+
+
 Legături nevalabile .[#toc-invalid-links]
 =========================================
 
diff --git a/application/ro/how-it-works.texy b/application/ro/how-it-works.texy
index 7dacddf162..c1cfda33f3 100644
--- a/application/ro/how-it-works.texy
+++ b/application/ro/how-it-works.texy
@@ -22,18 +22,18 @@ Structura directoarelor arată cam așa:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← cursuri de bază necesare
+│   │   └── <b>RouterFactory.php</b> ← configurare adrese URL
+│   ├── <b>UI/</b>                   ← prezentări, șabloane & co.
+│   │   ├── <b>@layout.latte</b>     ← șablon de prezentare partajată
+│   │   └── <b>Home/</b>             ← Directorul de prezentatori de acasă
+│   │       ├── <b>HomePresenter.php</b> ← Clasa de prezentator de acasă
+│   │       └── <b>default.latte</b> ← șablon pentru acțiune default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ Aplicațiile scrise în Nette sunt împărțite în mai multe așa-numite prezen
 
 Aplicația începe prin a cere așa-numitului router să decidă care dintre prezentatori să transmită cererea curentă pentru procesare. Routerul decide a cui este responsabilitatea. Acesta se uită la URL-ul de intrare `https://example.com/product/123`, care dorește să `show` un produs cu `id: 123` ca acțiune. Este un bun obicei să se scrie perechile prezentator + acțiune separate de două puncte ca `Product:show`.
 
-Astfel, routerul a transformat URL-ul într-o pereche `Presenter:action` + parametri, în cazul nostru `Product:show` + `id: 123`. Puteți vedea cum arată un router în fișierul `app/Router/RouterFactory.php` și îl vom descrie în detaliu în capitolul [Routing |Routing].
+Astfel, routerul a transformat URL-ul într-o pereche `Presenter:action` + parametri, în cazul nostru `Product:show` + `id: 123`. Puteți vedea cum arată un router în fișierul `app/Core/RouterFactory.php` și îl vom descrie în detaliu în capitolul [Routing |Routing].
 
 Să mergem mai departe. Aplicația cunoaște deja numele prezentatorului și poate continua. Prin crearea unui obiect `ProductPresenter`, care este codul prezentatorului `Product`. Mai exact, solicită containerului DI crearea prezentatorului, deoarece producerea de obiecte este sarcina acestuia.
 
@@ -121,12 +121,9 @@ Așadar, a fost apelată metoda `renderShow(123)`, al cărei cod este un exemplu
 
 Ulterior, prezentatorul returnează răspunsul. Acesta poate fi o pagină HTML, o imagine, un document XML, trimiterea unui fișier de pe disc, JSON sau redirecționarea către o altă pagină. Este important de reținut că, dacă nu spunem în mod explicit cum să răspundem (ceea ce este cazul `ProductPresenter`), răspunsul va fi redarea șablonului cu o pagină HTML. De ce? Ei bine, pentru că în 99% din cazuri dorim să desenăm un șablon, așa că prezentatorul ia acest comportament ca fiind implicit și dorește să ne ușureze munca. Acesta este punctul de vedere al lui Nette.
 
-Nici măcar nu trebuie să precizăm ce șablon să desenăm, el derivă calea către acesta conform unei logici simple. În cazul prezentatorului `Product` și al acțiunii `show`, el încearcă să vadă dacă unul dintre aceste fișiere șablon există în raport cu directorul în care se află clasa `ProductPresenter`:
+Nici măcar nu trebuie să specificăm ce șablon să redăm; cadrul va deduce singur calea. În cazul acțiunii `show`, acesta încearcă pur și simplu să încarce șablonul `show.latte` din directorul cu clasa `ProductPresenter`. De asemenea, încearcă să găsească aspectul în fișierul `@layout.latte` (mai multe informații despre [căutarea șabloanelor |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-De asemenea, va încerca să găsească aspectul în fișierul `@layout.latte` și apoi va reda șablonul. Acum sarcina prezentatorului și a întregii aplicații este finalizată. În cazul în care șablonul nu există, va fi returnată o pagină cu eroarea 404. Puteți citi mai multe despre prezentatori pe pagina [Prezentatori |Presenters].
+Ulterior, șabloanele sunt redate. Acest lucru încheie sarcina prezentatorului și a întregii aplicații, iar activitatea este finalizată. În cazul în care șablonul nu există, ar fi returnată o pagină de eroare 404. Puteți citi mai multe despre prezentatori pe pagina [Prezentatori |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Doar pentru a fi siguri, să încercăm să recapitulăm întregul proces cu un
 3) routerul decodifică URL-ul ca o pereche `Home:default`
 4) este creat un obiect `HomePresenter`
 5) se apelează metoda `renderDefault()` (dacă există)
-6) este redat un șablon `templates/Home/default.latte` cu un layout `templates/@layout.latte`
+6) este redat un șablon `default.latte` cu un layout `@layout.latte`
 
 
 Este posibil să fi întâlnit acum o mulțime de concepte noi, dar noi credem că acestea au sens. Crearea de aplicații în Nette este o joacă de copii.
diff --git a/application/ro/modules.texy b/application/ro/modules.texy
index bc8e11b0d2..300b63f579 100644
--- a/application/ro/modules.texy
+++ b/application/ro/modules.texy
@@ -2,29 +2,31 @@ Module
 ******
 
 .[perex]
-În Nette, modulele reprezintă unitățile logice care alcătuiesc o aplicație. Acestea includ prezentatori, șabloane, eventual și componente și clase de model.
+Modulele aduc claritate aplicațiilor Nette, facilitând divizarea ușoară în unități logice.
 
-Un singur director pentru prezentatori și unul pentru șabloane nu ar fi suficient pentru proiectele reale. A avea zeci de fișiere într-un singur dosar este cel puțin neorganizat. Cum se poate ieși din asta? Pur și simplu le împărțim în subdirectoare pe disc și în spații de nume în cod. Și asta este exact ceea ce fac modulele Nette.
-
-Așadar, să uităm de un singur dosar pentru prezentatori și șabloane și să creăm în schimb module, de exemplu `Admin` și `Front`.
+Similar cu organizarea fișierelor în foldere pe un hard disk, în Nette putem împărți în module prezentatorii, șabloanele și alte clase auxiliare. Cum funcționează acest lucru în practică? Pur și simplu prin încorporarea de noi subdirectoare în structură. Iată un exemplu de structură cu două module, Front și Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Această structură de directoare va fi reflectată de spațiile de nume ale claselor, astfel încât, de exemplu, `DashboardPresenter` va fi în spațiul de nume `App\Modules\Admin\Presenters`:
+Această structură de directoare se reflectă în spațiile de nume ale claselor, astfel încât, de exemplu, `DashboardPresenter` se află în spațiul de nume `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Prezentatorul `Dashboard` din cadrul modulului `Admin` este referit în cadrul aplicației folosind notația de două puncte ca `Admin:Dashboard`, iar acțiunea `default` ca `Admin:Dashboard:default`.
-Și de unde știe Nette proper că `Admin:Dashboard` reprezintă clasa `App\Modules\Admin\Presenters\DashboardPresenter`? Acest lucru este determinat de [cartografierea |#mapping] din configurație.
-Așadar, structura dată nu este prestabilită și o puteți modifica în funcție de nevoile dumneavoastră.
+În aplicație, ne referim la prezentatorul `Dashboard` din cadrul modulului `Admin` folosind notația două puncte ca `Admin:Dashboard`. Pentru acțiunea `default`, ne referim la acesta ca `Admin:Dashboard:default`.
+
+Structura prezentată nu este rigidă; [o |#mapping] puteți [personaliza complet |#mapping] în funcție [de nevoile dumneavoastră |#mapping] în cadrul configurației. .[tip]
 
-Modulele pot conține, bineînțeles, toate celelalte elemente în afară de prezentatori și șabloane, cum ar fi componente, clase de modele etc.
+Modulele pot include toate celelalte fișiere, cum ar fi componentele și clasele auxiliare, pe lângă prezentatori și șabloane. Dacă vă gândiți unde să le plasați pe acestea, luați în considerare utilizarea unui dosar `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Module imbricate .[#toc-nested-modules]
 ---------------------------------------
 
-Modulele nu trebuie să formeze doar o structură plată, ci puteți crea și submodule, de exemplu:
+Modulele pot avea mai multe niveluri de anvelopare, similar cu o structură de directoare pe un disc:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Astfel, modulul `Blog` este împărțit în submodulele `Admin` și `Front`. Din nou, acest lucru se va reflecta în spațiile de nume, care vor fi `App\Modules\Blog\Admin\Presenters` etc. Prezentatorul `Dashboard` din interiorul submodulului este denumit `Blog:Admin:Dashboard`.
+Modulul `Blog` este împărțit în submodulele `Admin` și `Front`. Acest lucru se reflectă și în spațiile de nume, care apar apoi ca `App\UI\Blog\Admin` și similar. Pentru a ne referi la prezentatorul `Dashboard` din cadrul submodulului `Admin`, ne referim la acesta ca `Blog:Admin:Dashboard`.
+
+Nesting-ul poate fi atât de adânc cât este necesar, permițând crearea de sub-submodule.
 
-Anveloparea poate merge cât de adânc doriți, astfel încât pot fi create sub-submodule.
+De exemplu, dacă în administrație aveți mulți prezentatori legați de gestionarea comenzilor, cum ar fi `OrderDetail`, `OrderEdit`, , `OrderDispatch`, etc., puteți crea un modul `Order` în care vor fi organizați prezentatori precum `Detail`, `Edit`, `Dispatch`, și alții.
 
 
 Crearea de legături .[#toc-creating-links]
@@ -102,47 +118,66 @@ A se vedea [capitolul privind rutarea |routing#Modules].
 Cartografiere .[#toc-mapping]
 -----------------------------
 
-Definește regulile prin care numele clasei este derivat din numele prezentatorului. Le scriem în [configurație |configuration] sub cheia `application › mapping`.
+Cartografierea definește regulile de derivare a numelui clasei din numele prezentatorului. Aceste reguli sunt specificate în [configurație |configuration] la cheia `application › mapping`.
 
-Să începem cu un exemplu care nu folosește module. Vom dori doar ca clasele de prezentator să aibă spațiul de nume `App\Presenters`. Aceasta înseamnă că un prezentator precum `Home` ar trebui să se mapeze la clasa `App\Presenters\HomePresenter`. Acest lucru poate fi realizat prin următoarea configurație:
+Structurile de directoare menționate anterior pe această pagină se bazează pe următoarea cartografiere:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Numele prezentatorului este înlocuit cu un asterisc în masca clasei, iar rezultatul este numele clasei. Ușor!
+Cum funcționează cartografierea? Pentru o mai bună înțelegere, să ne imaginăm mai întâi o aplicație fără module. Dorim ca clasele de prezentatori să se încadreze în spațiul de nume `App\UI`, astfel încât prezentatorul `Home` să fie asociat cu clasa `App\UI\HomePresenter`. Acest lucru poate fi realizat cu această configurație:
 
-Dacă împărțim prezentatorii în module, putem avea propria mapare pentru fiecare modul:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Această cartografiere funcționează prin înlocuirea asteriscului din masca `App\UI\*Presenter` cu numele prezentatorului `Home`, rezultând numele final al clasei `App\UI\HomePresenter`. Simplu!
+
+Cu toate acestea, după cum puteți vedea în exemplele din acest capitol și din alte capitole, plasăm clasele de prezentatori în subdirectoare eponime, de exemplu, prezentatorul `Home` este mapat în clasa `App\UI\Home\HomePresenter`. Acest lucru se realizează prin dublarea asteriscului (necesită Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Acum, să trecem la maparea prezentatorilor în module. Putem defini mape specifice pentru fiecare modul:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Acum, prezentatorul `Front:Home` se referă la clasa `App\Modules\Front\Presenters\HomePresenter` și prezentatorul `Admin:Dashboard` la clasa `App\Modules\Admin\Presenters\DashboardPresenter`.
+În conformitate cu această configurație, prezentatorul `Front:Home` se mapează la clasa `App\UI\Front\Home\HomePresenter`, în timp ce prezentatorul `Api:OAuth` se mapează la clasa `App\Api\OAuthPresenter`.
 
-Este mai practic să creăm o regulă generală (stea) care să le înlocuiască pe primele două. Asteriscul suplimentar va fi adăugat la masca clasei doar pentru modul:
+Deoarece modulele `Front` și `Admin` au o abordare similară de cartografiere și este posibil să existe mai multe astfel de module, este posibil să se creeze o regulă generală care să le înlocuiască. Un nou asterisc pentru modul este adăugat la masca clasei:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Dar ce se întâmplă dacă folosim module imbricate și avem un prezentator `Admin:User:Edit`? În acest caz, segmentul cu un asterisc care reprezintă modulul pentru fiecare nivel se repetă pur și simplu, iar rezultatul este clasa `App\Modules\Admin\User\Presenters\EditPresenter`.
+Pentru modulele imbricate pe mai multe niveluri, cum ar fi prezentatorul `Admin:User:Edit`, segmentul de asterisc se repetă pentru fiecare nivel, rezultând clasa `App\UI\Admin\User\Edit\EditPresenter`.
 
-O notație alternativă este utilizarea unui array format din trei segmente în loc de un șir de caractere. Această notație este echivalentă cu cea anterioară:
+O notație alternativă constă în utilizarea unei matrice compuse din trei segmente în locul unui șir de caractere. Această notație este echivalentă cu cea anterioară:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Valoarea implicită este `*: *Module\*Presenter`.
+Dacă avem doar o singură regulă în configurație, cea generală, putem scrie pe scurt:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/ro/presenters.texy b/application/ro/presenters.texy
index c4e64bfad0..56eef37cb0 100644
--- a/application/ro/presenters.texy
+++ b/application/ro/presenters.texy
@@ -60,7 +60,7 @@ Similar cu metoda `render<View>()`. În timp ce `render<View>()` este destinată
 
 Este important ca `action<Action>()` este apelat înainte de `render<View>()`, astfel încât în interiorul acesteia să putem eventual să schimbăm următorul curs al ciclului de viață, adică să schimbăm șablonul care va fi redat și, de asemenea, metoda `render<View>()` care va fi apelată, folosind `setView('otherView')`.
 
-Parametrii din cerere sunt trecuți către metodă. Este posibil și recomandat să se precizeze tipurile pentru parametri, de exemplu `actionShow(int $id, string $slug = null)` - dacă parametrul `id` lipsește sau dacă nu este un număr întreg, prezentatorul returnează [eroarea 404 |#Error 404 etc.] și încheie operațiunea.
+Parametrii din cerere sunt trecuți către metodă. Este posibil și recomandat să se precizeze tipurile pentru parametri, de exemplu `actionShow(int $id, ?string $slug = null)` - dacă parametrul `id` lipsește sau dacă nu este un număr întreg, prezentatorul returnează [eroarea 404 |#Error 404 etc.] și încheie operațiunea.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */);
 Eroare 404 etc. .[#toc-error-404-etc]
 =====================================
 
-Atunci când nu putem îndeplini cererea deoarece, de exemplu, articolul pe care dorim să îl afișăm nu există în baza de date, vom arunca eroarea 404 folosind metoda `error(string $message = null, int $httpCode = 404)`, care reprezintă eroarea HTTP 404:
+Atunci când nu putem îndeplini cererea deoarece, de exemplu, articolul pe care dorim să îl afișăm nu există în baza de date, vom arunca eroarea 404 folosind metoda `error(?string $message = null, int $httpCode = 404)`, care reprezintă eroarea HTTP 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parametrii cererii .[#toc-request-parameters]
+=============================================
+
+Prezentatorul, ca și fiecare componentă, își obține parametrii din cererea HTTP. Valorile acestora pot fi recuperate cu ajutorul metodei `getParameter($name)` sau `getParameters()`. Valorile sunt șiruri de caractere sau rețele de șiruri de caractere, în esență date brute obținute direct din URL.
+
+Pentru mai multă comoditate, recomandăm ca parametrii să fie accesibili prin intermediul proprietăților. Este suficient să îi adnotați cu ajutorul caracterului `#[Parameter]` atribut:
+
+```php
+use Nette\Application\Attributes\Parameter;  // această linie este importantă
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // trebuie să fie publică
+}
+```
+
+Pentru proprietăți, sugerăm să se precizeze tipul de date (de exemplu, `string`). Apoi, Nette va transforma automat valoarea pe baza acestuia. Valorile parametrilor pot fi, de asemenea, [validate |#Validation of Parameters].
+
+Atunci când creați o legătură, puteți seta direct valoarea parametrilor:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Parametrii persistenți .[#toc-persistent-parameters]
 ====================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Dacă `$this->lang` are o valoare, cum ar fi `'en'`, atunci legăturile create folosind `link()` sau `n:href` vor conține și parametrul `lang=en`. Iar atunci când se face clic pe link, acesta va fi din nou `$this->lang = 'en'`.
 
-Pentru proprietăți, vă recomandăm să includeți tipul de date (de exemplu, `string`) și puteți include și o valoare implicită. Valorile parametrilor pot fi [validate |#Validation of Persistent Parameters].
+Pentru proprietăți, vă recomandăm să includeți tipul de date (de exemplu, `string`) și puteți include și o valoare implicită. Valorile parametrilor pot fi [validate |#Validation of Parameters].
 
 Parametrii persistenți sunt trecuți în mod implicit între toate acțiunile unui anumit prezentator. Pentru a-i transmite între mai mulți prezentatori, trebuie să îi definiți fie:
 
@@ -307,18 +333,12 @@ Aprofundare .[#toc-going-deeper]
 Ceea ce am arătat până acum în acest capitol va fi probabil suficient. Rândurile următoare sunt destinate celor care sunt interesați de prezentatori în profunzime și doresc să știe totul.
 
 
-Cerință și parametri .[#toc-requirement-and-parameters]
+Validarea parametrilor .[#toc-validation-of-parameters]
 -------------------------------------------------------
 
-Cererea gestionată de prezentator este obiectul [api:Nette\Application\Request] și este returnată de metoda prezentatorului `getRequest()`. Acesta include o matrice de parametri și fiecare dintre ei aparține fie unora dintre componente, fie direct prezentatorului (care este de fapt tot o componentă, deși una specială). Astfel, Nette redistribuie parametrii și pasează între componentele individuale (și prezentator) prin apelarea metodei `loadState(array $params)`. Parametrii pot fi obținuți prin metoda `getParameters(): array`, folosind individual `getParameter($name)`. Valorile parametrilor sunt șiruri de caractere sau array-uri de șiruri de caractere, acestea fiind practic date brute obținute direct de la un URL.
-
+Valorile [parametrilor de cerere |#request parameters] și ale [parametrilor persistenți |#persistent parameters] primiți de la URL-uri sunt scrise în proprietăți prin metoda `loadState()`. Aceasta verifică, de asemenea, dacă tipul de date specificat în proprietate corespunde, în caz contrar se va răspunde cu o eroare 404 și pagina nu va fi afișată.
 
-Validarea parametrilor persistenți .[#toc-validation-of-persistent-parameters]
-------------------------------------------------------------------------------
-
-Valorile [parametrilor persistenți |#persistent parameters] primite de la URL-uri sunt scrise în proprietăți prin metoda `loadState()`. Aceasta verifică, de asemenea, dacă tipul de date specificat în proprietate se potrivește, în caz contrar se va răspunde cu o eroare 404 și pagina nu va fi afișată.
-
-Nu vă încredeți niciodată orbește în parametrii persistenți, deoarece aceștia pot fi ușor suprascriși de către utilizator în URL. De exemplu, iată cum verificăm dacă `$this->lang` se află printre limbile acceptate. O modalitate bună de a face acest lucru este să suprascrieți metoda `loadState()` menționată mai sus:
+Nu vă încredeți niciodată orbește în parametri, deoarece aceștia pot fi ușor suprascriși de către utilizator în URL. De exemplu, iată cum verificăm dacă `$this->lang` se află printre limbile acceptate. O modalitate bună de a face acest lucru este să suprascrieți metoda `loadState()` menționată mai sus:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Salvarea și restaurarea cererii .[#toc-save-and-restore-the-request]
 --------------------------------------------------------------------
 
-Puteți salva cererea curentă într-o sesiune sau o puteți restaura din sesiune și permite prezentatorului să o execute din nou. Acest lucru este util, de exemplu, atunci când un utilizator completează un formular și login-ul său expiră. Pentru a nu pierde date, înainte de redirecționarea către pagina de autentificare, salvăm cererea curentă în sesiune folosind `$reqId = $this->storeRequest()`, care returnează un identificator sub forma unui șir scurt și îl transmite ca parametru către prezentatorul de autentificare.
+Cererea pe care o gestionează prezentatorul este un obiect [api:Nette\Application\Request] și este returnată de metoda prezentatorului `getRequest()`.
+
+Puteți salva cererea curentă într-o sesiune sau o puteți restaura din sesiune și permite prezentatorului să o execute din nou. Acest lucru este util, de exemplu, atunci când un utilizator completează un formular și login-ul său expiră. Pentru a nu pierde date, înainte de redirecționarea către pagina de conectare, salvăm cererea curentă în sesiune cu ajutorul aplicației `$reqId = $this->storeRequest()`, care returnează un identificator sub forma unui șir scurt și îl transmite ca parametru către prezentatorul de conectare.
 
 După conectare, apelăm metoda `$this->restoreRequest($reqId)`, care preia cererea din sesiune și o transmite acesteia. Metoda verifică dacă cererea a fost creată de același utilizator ca și cel care s-a logat acum este. Dacă un alt utilizator se conectează sau dacă cheia nu este validă, nu face nimic și programul continuă.
 
@@ -362,7 +384,7 @@ Redirecționarea nu are loc cu o cerere AJAX sau POST, deoarece ar duce la pierd
 De asemenea, puteți invoca manual canonizarea folosind metoda `canonicalize()`, care, ca și metoda `link()`, primește ca argumente prezentatorul, acțiunile și parametrii. Aceasta creează o legătură și o compară cu URL-ul curent. Dacă este diferit, redirecționează către link-ul generat.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// redirecționează dacă $slug este diferit de $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Restricții de acces Utilizarea `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+----------------------------------------------------------------------------------------------------------
+
+Aplicația `#[Requires]` oferă opțiuni avansate pentru restricționarea accesului la prezentatori și la metodele acestora. Acesta poate fi utilizat pentru a specifica metodele HTTP, pentru a solicita cereri AJAX, pentru a limita accesul la aceeași origine și pentru a restricționa accesul doar la redirecționare. Atributul poate fi aplicat atât claselor de prezentatori, cât și metodelor individuale, cum ar fi `action<Action>()`, `render<View>()`, `handle<Signal>()`, și `createComponent<Name>()`.
+
+Puteți specifica aceste restricții:
+- pe metodele HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- care necesită o cerere AJAX: `#[Requires(ajax: true)]`
+- accesul numai de la aceeași origine: `#[Requires(sameOrigin: true)]`
+- acces numai prin redirecționare: `#[Requires(forward: true)]`
+- restricții privind anumite acțiuni: `#[Requires(actions: 'default')]`
+
+Pentru detalii, consultați [Cum se utilizează Requires |best-practices:attribute-requires].
+
+
+Verificarea metodei HTTP .[#toc-http-method-check]
+--------------------------------------------------
+
+În Nette, prezentatorii verifică automat metoda HTTP a fiecărei cereri primite, în primul rând din motive de securitate. În mod implicit, sunt permise metodele `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Dacă doriți să activați metode suplimentare, cum ar fi `OPTIONS`, puteți utiliza opțiunea `#[Requires]` attribute (din aplicația Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+În versiunea 3.1, verificarea se efectuează în `checkHttpMethod()`, care verifică dacă metoda specificată în cerere este inclusă în matricea `$presenter->allowedMethods`. Adăugați o metodă de genul următor:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Este esențial să subliniem faptul că, dacă activați metoda `OPTIONS`, trebuie să o gestionați în mod corespunzător și în prezentator. Această metodă este adesea utilizată ca o așa-numită cerere de preflight, pe care browserele o trimit automat înainte de cererea efectivă atunci când este necesar să se determine dacă cererea este permisă din punctul de vedere al politicii CORS (Cross-Origin Resource Sharing). Dacă permiteți această metodă, dar nu implementați un răspuns adecvat, aceasta poate duce la inconsecvențe și la potențiale probleme de securitate.
+
+
 Lecturi suplimentare .[#toc-further-reading]
 ============================================
 
diff --git a/application/ro/routing.texy b/application/ro/routing.texy
index 4f80ca99be..d70bec707c 100644
--- a/application/ro/routing.texy
+++ b/application/ro/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Notație avansată .[#toc-advanced-notation]
 ------------------------------------------
 
-Al doilea parametru al traseului, pe care îl scriem adesea în formatul `Presenter:action`, este o abreviere, pe care o putem scrie și sub forma unui câmp, în care indicăm direct valorile (implicite) ale parametrilor individuali:
+Ținta unei rute, scrisă de obicei sub forma `Presenter:action`, poate fi exprimată, de asemenea, cu ajutorul unei matrice care definește parametrii individuali și valorile lor implicite:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Sau putem folosi această formă, observați rescrierea expresiei regulate de validare:
+Pentru o specificație mai detaliată, se poate utiliza o formă și mai extinsă, în care, pe lângă valorile implicite, pot fi stabilite și alte proprietăți ale parametrilor, cum ar fi o expresie regulată de validare (a se vedea parametrul `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Aceste formate mai vorbărețe sunt utile pentru adăugarea altor metadate.
+Este important de reținut faptul că, dacă parametrii definiți în matrice nu sunt incluși în masca de cale, valorile lor nu pot fi modificate, nici măcar folosind parametrii de interogare specificați după un semn de întrebare în URL.
 
 
 Filtre și traduceri .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integrare .[#toc-integration]
 =============================
 
-Pentru a conecta routerul nostru la aplicație, trebuie să informăm containerul DI despre acesta. Cel mai simplu este să pregătim fabrica care va construi obiectul router și să spunem configurației containerului să o folosească. Să spunem că scriem o metodă în acest scop `App\Router\RouterFactory::createRouter()`:
+Pentru a conecta routerul nostru la aplicație, trebuie să informăm containerul DI despre acesta. Cel mai simplu este să pregătim fabrica care va construi obiectul router și să spunem configurației containerului să o folosească. Să spunem că scriem o metodă în acest scop `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Apoi scriem în [configurație |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Orice dependență, cum ar fi o conexiune la o bază de date etc., este transmisă metodei factory ca parametru al acesteia folosind [autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Prin utilizare separată se înțelege utilizarea capacităților routerului în
 Deci, din nou, vom crea o metodă care va construi un router, de exemplu:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Sau vom crea obiecte direct:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/ro/templates.texy b/application/ro/templates.texy
index abcead647e..043a5fb016 100644
--- a/application/ro/templates.texy
+++ b/application/ro/templates.texy
@@ -34,35 +34,81 @@ Iar acesta ar putea fi șablonul de acțiune:
 Acesta definește blocul `content`, care este inserat în locul lui `{include content}` în machetă și, de asemenea, redefinește blocul `title`, care suprascrie `{block title}` în machetă. Încercați să vă imaginați rezultatul.
 
 
-Căutați șabloane .[#toc-search-for-templates]
----------------------------------------------
+Căutarea șablonului .[#toc-template-lookup]
+-------------------------------------------
+
+În prezentări, nu trebuie să specificați ce șablon trebuie redat; cadrul va determina automat calea, ceea ce vă ușurează codificarea.
+
+Dacă utilizați o structură de directoare în care fiecare prezentator are propriul director, plasați pur și simplu șablonul în acest director sub numele acțiunii (de exemplu, view). De exemplu, pentru acțiunea `default`, utilizați șablonul `default.latte`:
 
-Calea către șabloane este dedusă conform unei logici simple. Se încearcă să se vadă dacă unul dintre aceste fișiere șablon există în raport cu directorul în care se află clasa presenter, unde `<Presenter>` este numele prezentatorului curent și `<view>` este numele acțiunii curente:
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Dacă utilizați o structură în care prezentatorii sunt împreună într-un singur director, iar șabloanele într-un dosar `templates`, salvați-l fie într-un fișier `<Presenter>.<view>.latte` sau `<Presenter>/<view>.latte`:
 
-Dacă șablonul nu este găsit, se va încerca căutarea în directorul `templates` cu un nivel mai sus, adică la același nivel cu directorul cu clasa de prezentator.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
 
-Dacă șablonul nu este găsit nici acolo, răspunsul este o [eroare 404 |presenters#Error 404 etc.].
+Directorul `templates` poate fi, de asemenea, plasat un nivel mai sus, la același nivel cu directorul cu clasele de prezentatori.
 
-De asemenea, puteți schimba vizualizarea folosind `$this->setView('otherView')`. Sau, în loc să căutați, specificați direct numele fișierului șablon folosind `$this->template->setFile('/path/to/template.latte')`.
+În cazul în care șablonul nu este găsit, prezentatorul răspunde cu [eroarea 404 - page not found |presenters#Error 404 etc].
+
+Puteți schimba vizualizarea folosind `$this->setView('anotherView')`. De asemenea, este posibilă specificarea directă a fișierului șablon cu `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Puteți modifica căile în care sunt căutate șabloanele prin suprascrierea metodei [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], care returnează o matrice de posibile căi de acces la fișiere.
+Fișierele în care sunt căutate șabloanele pot fi modificate prin suprascrierea metodei [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], care returnează o matrice de nume de fișiere posibile.
+
+
+Căutarea șabloanelor de prezentare .[#toc-layout-template-lookup]
+-----------------------------------------------------------------
+
+De asemenea, Nette caută automat fișierul de machetare.
+
+Dacă folosiți o structură de directoare în care fiecare prezentator are propriul director, plasați macheta fie în folderul cu prezentatorul, dacă este specifică doar acestuia, fie la un nivel superior, dacă este comună mai multor prezentatori:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Dacă utilizați o structură în care prezentatorii sunt grupați într-un singur director, iar șabloanele se află într-un dosar `templates`, macheta va fi așteptată în următoarele locuri:
 
-Prezentarea este așteptată în următoarele fișiere:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` aspect comun pentru mai mulți prezentatori
+Dacă prezentatorul se află într-un [modul |modules], se va căuta și mai sus în arborele de directoare, în funcție de structura de anvelopare a modulului.
 
-`<Presenter>` este numele prezentatorului curent și `<layout>` este numele structurii, care este în mod implicit `'layout'`. Numele poate fi schimbat cu `$this->setLayout('otherLayout')`, astfel încât să se încerce să se utilizeze fișierele `@otherLayout.latte`.
+Numele prezentării poate fi schimbat folosind `$this->setLayout('layoutAdmin')` și apoi va fi așteptat în fișierul `@layoutAdmin.latte`. De asemenea, puteți specifica direct fișierul șablon de prezentare folosind `$this->setLayout('/path/to/template.latte')`.
 
-De asemenea, puteți specifica direct numele de fișier al șablonului de machetă cu `$this->setLayout('/path/to/template.latte')`. Utilizarea `$this->setLayout(false)` va dezactiva căutarea de machete.
+Utilizarea `$this->setLayout(false)` sau a etichetei `{layout none}` în interiorul șablonului dezactivează căutarea de layout.
 
 .[note]
-Puteți modifica căile de căutare a șabloanelor prin suprascrierea metodei [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], care returnează o matrice de posibile căi de acces la fișiere.
+Fișierele în care sunt căutate șabloanele de prezentare pot fi modificate prin suprascrierea metodei [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], care returnează o matrice de nume de fișiere posibile.
 
 
 Variabilele din șablon .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ Adnotarea `@property-read` este pentru IDE și analiza statică, va face ca auto
 Vă puteți permite și luxul de a șopti în șabloane, trebuie doar să instalați pluginul în PhpStorm și să specificați numele clasei la începutul șablonului, consultați articolul "Latte: cum se tastează sistemul":https://blog.nette.org/ro/latte-cum-se-utilizeaza-sistemul-de-tipuri:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte versiunea 3 oferă o metodă mai avansată prin crearea unei [extensii |latte:creating-extension] pentru fiecare proiect web. Iată un exemplu aproximativ al unei astfel de clase:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ O înregistrăm folosind [configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternativ, traducătorul poate fi setat cu ajutorul [configurației |configurat
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Traducătorul poate fi apoi utilizat, de exemplu, ca filtru `|translate`, cu parametri suplimentari trecuți la metoda `translate()` (a se vedea `foo, bar`):
diff --git a/application/ru/@home.texy b/application/ru/@home.texy
index 6ba4943c53..4b38017f75 100644
--- a/application/ru/@home.texy
+++ b/application/ru/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | версия пакета         | совместимая версия PHP
 |-----------------------|-----------------------
-| Nette Application 4.0 | PHP 8.0 – 8.1
-| Nette Application 3.1 | PHP 7.2 – 8.1
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 – 8.0
 | Nette Application 2.4 | PHP 5.6 – 8.0
 
diff --git a/application/ru/ajax.texy b/application/ru/ajax.texy
index 6009fc864c..ffcb026607 100644
--- a/application/ru/ajax.texy
+++ b/application/ru/ajax.texy
@@ -3,10 +3,10 @@ AJAX и сниппеты
 
 <div class=perex>
 
-Современные веб-приложения сегодня работают наполовину на сервере, а наполовину в браузере. AJAX является жизненно важным объединяющим фактором. Какую поддержку предлагает фреймворк Nette?
-- отправка фрагментов шаблонов (так называемых *сниппетов*)
+В эпоху современных веб-приложений, когда функциональность часто разрывается между сервером и браузером, AJAX является необходимым связующим элементом. Какие возможности предлагает Nette Framework в этой области?
+- передача частей шаблона, так называемых сниппетов
 - передача переменных между PHP и JavaScript
-- Отладка приложений AJAX
+- инструменты для отладки AJAX-запросов
 
 </div>
 
@@ -14,29 +14,32 @@ AJAX и сниппеты
 Запрос AJAX .[#toc-ajax-request]
 ================================
 
-AJAX-запрос не отличается от классического запроса - к ведущему обращаются с определенным представлением и параметрами. Ведущий также решает, как ответить на него: он может использовать свою собственную процедуру, которая возвращает фрагмент HTML-кода (HTML snippet), XML-документ, JSON-объект или JavaScript-код.
+AJAX-запрос принципиально не отличается от классического HTTP-запроса. Вызывается презентатор с определенными параметрами. Как ответить на запрос, зависит от ведущего - он может вернуть данные в формате JSON, отправить часть HTML-кода, XML-документ и т.д.
 
-На стороне сервера AJAX-запрос может быть обнаружен с помощью сервисного метода, [инкапсулирующего HTTP-запрос |http:request] `$httpRequest->isAjax()` (определяет на основе HTTP-заголовка `X-Requested-With`). Внутри презентатора доступен ярлык в виде метода `$this->isAjax()`.
+На стороне браузера мы инициируем AJAX-запрос с помощью функции `fetch()`:
 
-Существует предварительно обработанный объект `payload`, предназначенный для отправки данных в браузер в формате JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Успешно';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// обработка ответа
+});
 ```
 
-Для полного контроля над выводом JSON используйте метод `sendJson` в презентере. Это немедленно прервет работу презентера, и вы обойдетесь без шаблона:
+На стороне сервера AJAX-запрос распознается методом `$httpRequest->isAjax()` сервиса, [инкапсулирующего HTTP-запрос |http:request]. Он использует HTTP-заголовок `X-Requested-With`, поэтому его необходимо отправить. Внутри презентатора можно использовать метод `$this->isAjax()`.
+
+Если необходимо отправить данные в формате JSON, используйте метод [`sendJson()` |presenters#Sending a response] метод. Метод также завершает работу презентера.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Если мы хотим отправить HTML, мы можем установить специальный шаблон для AJAX-запросов:
+Если вы планируете отвечать с помощью специального шаблона, предназначенного для AJAX, то это можно сделать следующим образом:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
-Naja
-====
+Фрагменты .[#toc-snippets]
+==========================
+
+Наиболее мощным инструментом, предлагаемым Nette для связи сервера с клиентом, являются сниппеты. С их помощью можно превратить обычное приложение в AJAX-приложение, затратив минимум усилий и написав несколько строк кода. Пример Fifteen демонстрирует, как это работает, а его код можно найти на [GitHub |https://github.com/nette-examples/fifteen].
+
+Сниппеты, или вырезки, позволяют обновлять только отдельные части страницы, а не перезагружать ее целиком. Это быстрее и эффективнее, а также обеспечивает более комфортную работу пользователя. Возможно, сниппеты напомнят вам Hotwire для Ruby on Rails или Symfony UX Turbo. Интересно, что компания Nette представила сниппеты на 14 лет раньше.
 
-[Библиотека Naja |https://naja.js.org] используется для обработки AJAX-запросов на стороне браузера. [Установите |https://naja.js.org/#/guide/01-install-setup-naja] его как пакет node.js (для использования с Webpack, Rollup, Vite, Parcel и другими):
+Как работают сниппеты? При первой загрузке страницы (не-AJAX-запрос) загружается вся страница, включая все сниппеты. Когда пользователь взаимодействует со страницей (например, нажимает кнопку, отправляет форму и т.д.), вместо загрузки всей страницы выполняется AJAX-запрос. Код в презентере выполняет это действие и решает, какие фрагменты необходимо обновить. Nette рендерит эти фрагменты и отправляет их в виде массива JSON. Затем код обработки в браузере вставляет полученные фрагменты обратно на страницу. Таким образом, передается только код измененных фрагментов, что позволяет экономить пропускную способность и ускорять загрузку по сравнению с передачей всего содержимого страницы.
+
+
+Naja .[#toc-naja]
+-----------------
+
+Для работы со сниппетами на стороне браузера используется [библиотека Naja |https://naja.js.org]. [Установите ее |https://naja.js.org/#/guide/01-install-setup-naja] как пакет node.js (для использования с такими приложениями, как Webpack, Rollup, Vite, Parcel и другими):
 
 ```shell
 npm install naja
 ```
 
-...или вставить непосредственно в шаблон страницы:
+... или вставьте ее непосредственно в шаблон страницы:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Чтобы создать AJAX-запрос из обычной ссылки (сигнала) или отправки формы, просто пометьте соответствующую ссылку, форму или кнопку классом `ajax`:
+Сначала нужно [инициализировать |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] библиотеку:
+
+```js
+naja.initialize();
+```
+
+Чтобы превратить обычную ссылку (сигнал) или отправку формы в AJAX-запрос, достаточно пометить соответствующую ссылку, форму или кнопку классом `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ npm install naja
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Сниппеты
-========
-
-Однако существует гораздо более мощный инструмент встроенной поддержки AJAX — сниппеты. Их использование позволяет превратить обычное приложение в AJAX-приложение с помощью всего нескольких строк кода. Как всё это работает, показано в примере Fifteen, код которого также доступен в сборке или на [GitHub |https://github.com/nette-examples/fifteen].
-
-Принцип работы сниппетов заключается в том, что вся страница передается во время начального (т. е. не-AJAX) запроса и затем с каждым AJAX [subrequest |components#Signal] (запрос того же представления того же презентера) только код измененных частей передается в хранилище `payload`, упомянутое ранее.
-
-Сниппеты могут напомнить вам Hotwire для Ruby on Rails или Symfony UX Turbo, но Nette придумал их четырнадцатью годами раньше.
-
-
-Инвалидация .[#toc-invalidation-of-snippets]
-============================================
+Перерисовка фрагментов .[#toc-redrawing-snippets]
+-------------------------------------------------
 
-Каждый потомок класса [Control |components] (которым является и Presenter) способен помнить, были ли какие-либо изменения во время запроса, требующие повторного отображения. Существует несколько способов справиться с этим: `redrawControl()` и `isControlInvalid()`. Пример:
+Каждый объект класса [Control |components] (в том числе и сам Presenter) хранит информацию о том, произошли ли изменения, требующие его перерисовки. Для этого используется метод `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Объект должен повторно отображаться после того, как пользователь вошел в систему
+	// после входа в систему необходимо перерисовать соответствующую часть
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Однако Nette обеспечивает ещё более тонкое разрешение, чем целые компоненты. Перечисленные методы принимают имя так называемого «фрагмента» в качестве необязательного параметра. «Фрагмет» это, по сути, элемент в вашем шаблоне, помеченный для этой цели макросом Latte, подробнее об этом позже. Таким образом, можно попросить компонент перерисовать только *часть* своего шаблона. Если весь компонент недействителен, то все его фрагменты отображаются заново. Компонент является «недействительным», если любой из его субкомпонентов является недействительным.
 
-```php
-$this->isControlInvalid(); // -> false
-
-$this->redrawControl('header'); // аннулирует фрагмент с именем 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, по крайней мере один фрагмент недействителен
+Nette также позволяет более тонко контролировать, что именно нужно перерисовывать. Упомянутый выше метод может принимать в качестве аргумента имя фрагмента. Таким образом, можно аннулировать (то есть принудительно перерисовать) на уровне части шаблона. Если аннулируется весь компонент, то перерисовывается и каждый его фрагмент:
 
-$this->redrawControl(); // делает недействительным весь компонент, каждый фрагмент
-$this->isControlInvalid('footer'); // -> true
+```php
+// аннулирует фрагмент 'header'
+$this->redrawControl('header');
 ```
 
-Компонент, получивший сигнал, автоматически помечается для перерисовки.
-
-Благодаря перерисовке фрагментов мы точно знаем, какие части каких элементов должны быть перерисованы.
-
-
-Тег `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
-
-Рендеринг страницы происходит точно так же, как и при обычном запросе: загружаются одни и те же шаблоны и т. д. Однако самое важное — это не допустить попадания в выходной сигнал тех частей, которые не должны попасть в выходной сигнал; остальные части должны быть связаны с идентификатором и отправлены пользователю в формате, понятном для обработчика JavaScript.
-
 
-Синтаксис
----------
+Фрагменты в Latte .[#toc-snippets-in-latte]
+-------------------------------------------
 
-Если в шаблоне есть элемент управления или фрагмент, мы должны обернуть его с помощью парного тега `{snippet} ... {/snippet}` — отрисованный фрагмент будет «вырезан» и отправится в браузер. Он также заключит его в вспомогательный тег `<div>` (можно использовать другой). В следующем примере определен сниппет с именем `header`. Он также может представлять собой шаблон компонента:
+Использовать сниппеты в Latte очень просто. Чтобы определить часть шаблона как сниппет, достаточно обернуть ее в теги `{snippet}` и `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ $this->isControlInvalid('footer'); // -> true
 {/snippet}
 ```
 
-Если вы хотите создать сниппет с другим содержащим элементом, отличным от `<div>`, или добавить пользовательские атрибуты к элементу, вы можете использовать следующее определение:
+Сниппет создает элемент `<div>` в HTML-странице со специально сгенерированным `id`. При перерисовке сниппета содержимое этого элемента обновляется. Поэтому при первоначальном рендеринге страницы все сниппеты также должны быть рендерированы, даже если они изначально могут быть пустыми.
+
+Также можно создать сниппет с элементом, отличным от `<div>` с помощью атрибута n:attribute:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ $this->isControlInvalid('footer'); // -> true
 ```
 
 
-Динамические сниппеты
-=====================
+Области фрагментов .[#toc-snippet-areas]
+----------------------------------------
 
-В Nette вы также можете определить сниппеты с динамическим именем, основанным на параметре времени выполнения. Это наиболее подходит для различных списков, где нам нужно изменить только одну строку, но мы не хотим переносить весь список вместе с ней. Примером этого может быть:
+Имена сниппетов также могут быть выражениями:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Существует один статический сниппет `itemsContainer`, содержащий несколько динамических сниппетов: `пункт-0`, `пункт-1` и так далее.
+Таким образом, мы получим несколько фрагментов типа `item-0`, `item-1`, и т.д. Если мы напрямую аннулируем динамический сниппет (например, `item-1`), то ничего не будет перерисовано. Причина в том, что сниппеты работают как настоящие выдержки, и непосредственно отрисовываются только они сами. Однако в шаблоне технически нет фрагмента с именем `item-1`. Он появляется только при выполнении окружающего сниппета кода, в данном случае цикла foreach. Поэтому часть шаблона, которую необходимо выполнить, мы пометим тегом `{snippetArea}`:
 
-Вы не можете перерисовать динамический фрагмент напрямую (перерисовка `item-1` не имеет эффекта), вы должны перерисовать его родительский фрагмент (в данном примере `itemsContainer`). При этом выполняется код родительского сниппета, но браузеру передаются только его вложенные сниппеты. Если вы хотите передать только один из вложенных сниппетов, вам нужно изменить ввод для родительского сниппета, чтобы не генерировать другие вложенные сниппеты.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-В приведенном примере необходимо убедиться, что при AJAX-запросе в массив `$list` будет добавлен только один элемент, поэтому цикл `foreach` будет выводить только один динамический фрагмент.
+И перерисуем как отдельный фрагмент, так и всю общую область:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * Этот метод возвращает данные для списка.
-	 * Обычно это просто запрос данных из модели.
-	 * Для целей этого примера данные жёстко закодированы.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Также необходимо убедиться, что массив `$items` содержит только те элементы, которые должны быть перерисованы.
 
-Сниппеты во включенном шаблоне
-==============================
-
-Может случиться так, что сниппет находится в шаблоне, который включается из другого шаблона. В этом случае необходимо обернуть код включения во втором шаблоне макросом `snippetArea`, затем перерисовать как snippetArea, так и сам сниппет.
-
-Макрос `snippetArea` гарантирует, что код внутри него будет выполнен, но браузеру будет отправлен только фактический фрагмент включенного шаблона.
+При вставке другого шаблона в основной с помощью тега `{include}`, содержащего сниппеты, необходимо снова обернуть включаемый шаблон в `snippetArea` и сделать недействительными и сниппет, и область вместе:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Вы также можете сочетать его с динамическими сниппетами.
 
+Сниппеты в компонентах .[#toc-snippets-in-components]
+-----------------------------------------------------
 
-Добавление и удаление
-=====================
-
-Если добавить новый элемент в список и аннулировать `itemsContainer`, AJAX-запрос вернет фрагменты, включая новый, но javascript-обработчик не сможет его отобразить. Это происходит потому, что нет HTML-элемента с вновь созданным ID.
-
-В этом случае самый простой способ — обернуть весь список в ещё один сниппет и признать его недействительным:
+Вы можете создавать сниппеты внутри [компонентов |components], и Nette будет автоматически перерисовывать их. Однако есть одно ограничение: для перерисовки сниппетов вызывается метод `render()` без параметров. Таким образом, передача параметров в шаблоне не работает:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Добавить</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Отправка пользовательских данных .[#toc-sending-user-data]
+----------------------------------------------------------
+
+Наряду со сниппетами можно отправлять клиенту любые дополнительные данные. Для этого достаточно записать их в объект `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-То же самое относится и к удалению элемента. Можно было бы отправить пустой сниппет, но обычно списки могут быть постраничными, и было бы сложно реализовать удаление одного элемента и загрузку другого (который раньше находился на другой странице постраничного списка).
-
 
-Отправка параметров компоненту
-==============================
+Параметры отправки .[#toc-sending-parameters]
+=============================================
 
-Когда мы отправляем параметры компоненту через AJAX-запрос, будь то сигнальные или постоянные параметры, мы должны предоставить их глобальное имя, которое также содержит имя компонента. Полное имя параметра возвращает метод `getParameterId()`.
+Когда мы отправляем в компонент через AJAX-запрос параметры, будь то сигнальные или постоянные, мы должны указать их глобальное имя, которое также содержит имя компонента. Полное имя параметра возвращает метод `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-И обработать метод с соответствующими параметрами в компоненте.
+handle метод с соответствующими параметрами в компоненте:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/ru/bootstrap.texy b/application/ru/bootstrap.texy
index 071d2c9fc5..82e18f8d6b 100644
--- a/application/ru/bootstrap.texy
+++ b/application/ru/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Конфигуратор отвечает за настройку среды и служб приложения.
+		$this->configurator = new Configurator;
+		// Задайте директорию для временных файлов, создаваемых Nette (например, скомпилированных шаблонов).
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette умный, и режим разработки включается автоматически,
+		// или вы можете включить его для определенного IP-адреса, откомментировав следующую строку:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Включает Tracy: основной инструмент отладки в виде "армейского ножа".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: автозагрузка всех классов в заданной директории
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Загрузка конфигурационных файлов
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php
 =========
 
-В случае веб-приложений начальным файлом является `index.php`, который находится в общедоступном каталоге `www/`. Он позволяет классу `Bootstrap` инициализировать среду и возвращает `$configurator`, который создает контейнер DI. Затем он получает сервис `Application`, запускающий веб-приложение:
+Начальным файлом для веб-приложений является `index.php`, расположенный в публичной директории `www/`. Он использует класс `Bootstrap` для инициализации среды и создания контейнера DI. Затем он получает из контейнера службу `Application`, которая запускает веб-приложение:
 
 ```php
-// инициализируем среду + получаем объект Configurator
-$configurator = App\Bootstrap::boot();
-// создаем DI-контейнер
-$container = $configurator->createContainer();
-// DI-контейнер создайет объект Nette\Application\Application
+$bootstrap = new App\Bootstrap;
+// Инициализация среды + создание DI-контейнера
+$container = $bootstrap->bootWebApplication();
+// DI-контейнер создает объект Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// запускаем приложение Nette
+// Запуск приложения Nette и обработка входящего запроса
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Nette различает два основных режима, в которых
 Если вы хотите включить режим разработки в других случаях, например, для программистов, получающих доступ с определенного IP-адреса, вы можете использовать `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // один или более IP-адресов
+$this->configurator->setDebugMode('23.75.345.200'); // один или более IP-адресов
 ```
 
 Мы определенно рекомендуем сочетать IP-адрес с файлом cookie. Мы будем хранить секретный токен в cookie `nette-debug', например, `secret1234`, и режим разработки будет активирован для программистов с такой комбинацией IP и cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Можно полностью отключить режим разработчика, даже для localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Обратите внимание, что значение `true` жестко включает режим разработчика, чего никогда не должно происходить на рабочем сервере.
@@ -90,7 +115,7 @@ $configurator->setDebugMode(false);
 Для облегчения отладки мы включим замечательный инструмент [Tracy |tracy:]. В режиме разработчика он визуализирует ошибки, а в режиме производства — записывает ошибки в указанный каталог:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ $configurator->enableTracy($appDir . '/log');
 Nette использует кэш для DI-контейнера, RobotLoader, шаблонов и т. д. Поэтому необходимо задать путь к директории, где будет храниться кэш:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 В Linux или macOS установите [права на запись |nette:troubleshooting#Setting-Directory-Permissions] для каталогов `log/` и `temp/`.
@@ -112,7 +137,7 @@ RobotLoader
 Обычно мы хотим автоматически загружать классы с помощью [RobotLoader |robot-loader:], поэтому мы должны запустить его и позволить ему загрузить классы из каталога, в котором находится `Bootstrap.php` (т. е. `__DIR__`) и все его подкаталоги:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ $configurator->createRobotLoader()
 Configurator позволяет указать часовой пояс для вашего приложения.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ $configurator->setTimeZone('Europe/Prague');
 Файлы конфигурации загружаются с помощью `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Метод `addConfig()` может быть вызван несколько раз для добавления нескольких файлов.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ if (PHP_SAPI === 'cli') {
 Параметры, используемые в файлах конфигурации, могут быть определены [в секции `parameters`|dependency-injection:configuration#parameters] и подхвачены (или перезаписаны) методом `addStaticParameters()` (у него есть алиас `addParameters()`). Важно, что разные значения параметров вызывают генерацию дополнительных DI-контейнеров, то есть дополнительных классов.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ $configurator->addStaticParameters([
 Можно также добавить динамические параметры в контейнер. Их разные значения, в отличие от статических параметров, не приведут к генерации новых DI-контейнеров.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Переменные среды могут быть легко доступны с использованием динамических параметров. Мы можем получить доступ к ним через `%env.variable%` в файлах конфигурации.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ $configurator->addDynamicParameters([
 - `%wwwDir%` - абсолютный путь к директории, содержащей входной файл `index.php`
 - `%tempDir%` - абсолютный путь к директории для временных файлов.
 - `%vendorDir%` - абсолютный путь к директории, в которую Composer устанавливает библиотеки.
+- `%rootDir%` - абсолютный путь к корневому каталогу проекта.
 - `%debugMode%` указывает, находится ли приложение в режиме отладки
 - `%consoleMode%` указывает, поступил ли запрос через командную строку
 
@@ -225,7 +252,7 @@ services:
 Создаём новый экземпляр и вставляем его в Bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Разные среды .[#toc-different-environments]
 ===========================================
 
-Не стесняйтесь настроить класс `Bootstrap` в соответствии с вашими потребностями. Вы можете добавлять параметры в метод `boot()` для разделения веб-проектов, или добавлять другие методы, такие как `bootForTests()`, которые инициализируют среду для модульных тестов, `bootForCli()` для скриптов, вызываемых из командной строки, и так далее.
+Не стесняйтесь настраивать класс `Bootstrap` в соответствии с вашими потребностями. Вы можете добавить параметры в метод `bootWebApplication()`, чтобы различать веб-проекты. Также можно добавить другие методы, например `bootTestEnvironment()` для инициализации окружения для модульных тестов, `bootConsoleApplication()` для скриптов, вызываемых из командной строки, и так далее.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Инициализация тестера Nette Tester
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Инициализация Nette Tester
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/ru/components.texy b/application/ru/components.texy
index 65adfeff51..31c39481d0 100644
--- a/application/ru/components.texy
+++ b/application/ru/components.texy
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // делаем редирект
 ```
 
 
+Перенаправление после сигнала .[#toc-redirection-after-a-signal]
+================================================================
+
+После обработки сигнала компонента часто следует перенаправление. Эта ситуация похожа на ситуацию с формами - после отправки формы мы также делаем перенаправление, чтобы предотвратить повторную отправку данных при обновлении страницы в браузере.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Поскольку компонент - это многократно используемый элемент и обычно не должен иметь прямой зависимости от конкретных презентаторов, методы `redirect()` и `link()` автоматически интерпретируют параметр как сигнал компонента:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Если вам нужно перенаправить на другого ведущего или действие, вы можете сделать это через ведущего:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Постоянные параметры .[#toc-persistent-parameters]
 ==================================================
 
@@ -347,7 +369,7 @@ services:
 Наконец, мы будем использовать эту фабрику в нашем презентере:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ interface PollControlFactory
 Компоненты в Nette Application - это многократно используемые части веб-приложения, которые мы встраиваем в страницы, о чем и пойдет речь в этой главе. Каковы возможности такого компонента?
 
 1) он может быть отображен в шаблоне
-2) он знает, какую часть себя отображать во время [AJAX-запроса |ajax#invalidation] (сниппеты)
+2) он знает [, какую часть себя от |ajax#snippets] рисовывать при AJAX-запросе (сниппеты)
 3) он имеет возможность хранить свое состояние в URL (постоянные параметры)
 4) имеет возможность реагировать на действия пользователя (сигналы)
 5) создает иерархическую структуру (где корнем является ведущий)
diff --git a/application/ru/configuration.texy b/application/ru/configuration.texy
index 0216233dfd..0121aa4071 100644
--- a/application/ru/configuration.texy
+++ b/application/ru/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# отображает вкладку "Nette Application" на синем экране Tracy?
 	debugger: ...           # (bool) по умолчанию true
 
-	# будет ли вызываться презентер ошибок при ошибке?
-	catchExceptions: ...    # (bool) по умолчанию true на «боевом» сервере
+	# будет ли вызываться error-presenter при ошибке?
+	# имеет значение только в режиме разработчика
+	catchExceptions: ...    # (bool) по умолчанию равно true
 
 	# имя презентера ошибок
-	errorPresenter: Error   # (string) по умолчанию 'Nette:Error'
+	errorPresenter: Error   # (string|array) по умолчанию 'Nette:Error'
+
+	# определяет псевдонимы для ведущих и событий
+	aliases: ...
 
 	# определяет правила для преобразования имени ведущего в класс
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) по умолчанию false
 ```
 
-Поскольку в режиме разработки презентеры ошибок по умолчанию не вызываются, а ошибки отображаются Tracy, изменение значения `catchExceptions` на `true` помогает проверить корректность работы презентеров ошибок во время разработки.
+Начиная с версии `nette/application` 3.2 можно определить пару презентеров ошибок:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # для Nette\Application\BadRequestException
+		5xx: Error5xx   # для других исключений
+```
 
 Опция `silentLinks` определяет, как Nette ведет себя в режиме разработчика, когда генерация ссылок не удается (например, из-за отсутствия презентера и т. д.). Значение по умолчанию `false` означает, что Nette запускает `E_USER_WARNING`. Установка значения `true` подавляет это сообщение об ошибке. В производственной среде всегда вызывается `E_USER_WARNING`. Мы также можем повлиять на это поведение, установив переменную презентера [$invalidLinkMode |creating-links#Invalid-Links].
 
+[Псевдонимы упрощают обращение к |creating-links#aliases] часто используемым ведущим.
+
 Карта [mapping определяет правила |modules#Mapping], по которым имя класса выводится из имени ведущего.
 
 
@@ -82,6 +95,9 @@ latte:
 	# включает [проверку сгенерированного кода |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) по умолчанию равно null
 
+	# устанавливает локаль
+	locale: cs_CZ        # (string) по умолчанию null
+
 	# класс $this->template
 	templateClass: App\MyTemplateClass # по умолчанию Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ latte:
 ```neon
 latte:
 	расширения:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/ru/creating-links.texy b/application/ru/creating-links.texy
index 3a4dbb4805..02cd240f36 100644
--- a/application/ru/creating-links.texy
+++ b/application/ru/creating-links.texy
@@ -38,7 +38,7 @@
 <a n:href="Product:show $product->id, lang: en">подробнее</a>
 ```
 
-Если метод `ProductPresenter::renderShow()` не имеет `$lang` в своей сигнатуре, он может прочитать значение параметра, используя `$lang = $this->getParameter('lang')`.
+Если метод `ProductPresenter::renderShow()` не имеет в своей сигнатуре `$lang`, то он может получить значение параметра с помощью `$lang = $this->getParameter('lang')` или из [свойства |presenters#Request Parameters].
 
 Если параметры хранятся в массиве, их можно расширить с помощью оператора `(expand)` (что-то вроде оператора `...` в PHP, но работает с ассоциативными массивами):
 
@@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 <a n:href="this">обновить</a>
 ```
 
-При этом передаются все параметры, указанные в сигнатуре метода `render<View>()` или `action<Action>()`. Таким образом, если мы находимся на страницах `Product:show` и `id:123`, ссылка на `this` также будет передавать этот параметр.
+В то же время все параметры, указанные в сигнатуре `action<Action>()` или `render<View>()` метода, если `action<Action>()` не определены, передаются. Таким образом, если мы находимся на страницах `Product:show` и `id:123`, то ссылка на `this` также будет передавать этот параметр.
 
 Конечно, можно указать параметры напрямую:
 
@@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 Если мы хотим сделать ссылку на презентеры в шаблоне компонента, мы используем тег `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">главная страница</a>
+<a href={plink Home:default}>главная страница</a>
 ```
 
 or in the code
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Псевдонимы .[#toc-aliases]{data-version:v3.2.2}
+===============================================
+
+Иногда полезно назначить легко запоминающийся псевдоним для пары Ведущий:действие. Например, вы можете назвать домашнюю страницу `Front:Home:default` просто `home` или `Admin:Dashboard:default` - `admin`.
+
+Псевдонимы задаются в [конфигурации |configuration] под ключом `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+В ссылках они записываются с использованием символа at, например:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Они поддерживаются во всех методах, работающих со ссылками, таких как `redirect()` и подобные.
+
+
 Недействительные ссылки .[#toc-invalid-links]
 =============================================
 
diff --git a/application/ru/how-it-works.texy b/application/ru/how-it-works.texy
index 02bdce2b15..6e3908f7e0 100644
--- a/application/ru/how-it-works.texy
+++ b/application/ru/how-it-works.texy
@@ -22,18 +22,18 @@
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← каталог с приложением
-│   ├── <b>Presenters/</b>           ← классы презентеров
-│   │   ├── <b>HomePresenter.php</b>  ← Класс презентера главной страницы
-│   │   └── <b>templates/</b>        ← директория шаблонов
-│   │       ├── <b>@layout.latte</b> ← шаблон общего макета
-│   │       └── <b>Home/</b>         ← шаблоны презентера главной страницы
-│   │           └── <b>default.latte</b>  ← шаблон действия `default`
-│   ├── <b>Router/</b>               ← конфигурация URL-адресов
+│   ├── <b>Core/</b>                 ← основные необходимые классы
+│   │   └── <b>RouterFactory.php</b> ← настройка URL-адресов
+│   ├── <b>UI/</b>                   ← презентаторы, шаблоны и др.
+│   │   ├── <b>@layout.latte</b>     ← шаблон общего макета
+│   │   └── <b>Home/</b>             ← Главная директория ведущих
+│   │       ├── <b>HomePresenter.php</b> ← Класс презентера дома
+│   │       └── <b>default.latte</b> ← шаблон для действий default
 │   └── <b>Bootstrap.php</b>         ← загрузочный класс Bootstrap
 ├── <b>bin/</b>                      ← скрипты командной строки
 ├── <b>config/</b>                   ← файлы конфигурации
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← журналы ошибок
 ├── <b>temp/</b>                     ← временные файлы, кэш, …
 ├── <b>vendor/</b>                   ← библиотеки, установленные через Composer
@@ -91,7 +91,7 @@ Nette — это наставник, который направляет вас
 
 Приложение начинает работу с того, что просит так называемый маршрутизатор решить, какому из презентеров передать текущий запрос на обработку. Маршрутизатор решает, чья это ответственность. Он просматривает входной URL `https://example.com/product/123` и, основываясь на том, как он настроен, решает, что это задание, например, для **презентера** `Product`, который хочет `показать` продукт с `id: 123` как действие. Хорошей привычкой является написание пар презентер + действие, разделенных двоеточием: `Продукт:показать`.
 
-Поэтому маршрутизатор преобразовал URL в пару `Presenter:action` + параметры, в нашем случае `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Router/RouterFactory.php`, и мы подробно опишем его в главе [Маршрутизация |routing].
+Поэтому маршрутизатор преобразовал URL в пару `Presenter:action` + параметры, в нашем случае `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Core/RouterFactory.php`, и мы подробно опишем его в главе [Маршрутизация |routing].
 
 Давайте двигаться дальше. Приложение уже знает имя презентера и может продолжить работу. Путем создания объекта `ProductPresenter`, который является кодом презентера `Product`. Точнее, он просит контейнер DI создать презентера, потому что создание объектов — это его работа.
 
@@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 После этого презентер возвращает ответ. Это может быть HTML-страница, изображение, XML-документ, отправка файла с диска, JSON или перенаправление на другую страницу. Важно отметить, что если мы явно не указываем, как реагировать (что имеет место в случае с `ProductPresenter`), ответом будет отображение шаблона с HTML-страницей. Почему? Ну, потому что в 99% случаев мы хотим отобразить шаблон, поэтому презентер принимает такое поведение по умолчанию и хочет облегчить нашу работу. Это точка зрения Nette.
 
-Нам даже не нужно указывать, какой шаблон нужно вывести, он сам выводит путь к нему в соответствии с простой логикой. В случае с презентером `Product` и действием `show`, он пытается проверить, существует ли один из этих файлов шаблонов относительно каталога, в котором находится класс `ProductPresenter`:
+Нам даже не нужно указывать, какой шаблон рендерить, фреймворк сам определит путь. В случае с действием `show` он просто попытается загрузить шаблон `show.latte` в директории с классом `ProductPresenter`. Он также попытается найти макет в файле `@layout.latte` (подробнее о [поиске шаблонов |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-И затем он отображает шаблон. Теперь задача презентера и всего приложения выполнена. Если шаблон не существует, будет возвращена страница с ошибкой 404. Подробнее о презентерах вы можете прочитать на странице [Презентеры |presenters].
+Затем происходит рендеринг шаблонов. На этом задача ведущего и всего приложения завершена, и работа закончена. Если шаблон не существует, будет возвращена страница с ошибкой 404. Подробнее о презентерах можно прочитать на странице [Презентеры |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 3) маршрутизатор декодирует URL как пару `Home:default`
 4) создается объект `HomePresenter`
 5) вызывается метод `renderDefault()` (если существует)
-6) шаблон `templates/Home/default.latte` с макетом `templates/@layout.latte` отрисован
+6) шаблон `default.latte` с макетом `@layout.latte` отрисован
 
 
 Возможно, сейчас вы столкнулись с множеством новых понятий, но мы считаем, что они имеют смысл. Создавать приложения в Nette — проще простого.
diff --git a/application/ru/modules.texy b/application/ru/modules.texy
index b8d3e626c2..8159f0a30d 100644
--- a/application/ru/modules.texy
+++ b/application/ru/modules.texy
@@ -2,29 +2,31 @@
 ******
 
 .[perex]
-В Nette модули представляют собой логические единицы, из которых состоит приложение. Они включают ведущие, шаблоны, возможно, компоненты и классы моделей.
+Модули вносят ясность в приложения Nette, облегчая разделение на логические блоки.
 
-Одного компонента для презентаторов и одного для шаблонов будет недостаточно для реальных проектов. Наличие десятков файлов в одной папке по меньшей мере неорганизованно. Как выйти из этого положения? Мы просто разделяем их на подкаталоги на диске и на пространства имен в коде. И это именно то, что делают модули Nette.
-
-Поэтому давайте забудем о единой папке для ведущих и шаблонов и вместо этого создадим модули, например, `Admin` и `Front`.
+Подобно организации файлов в папки на жестком диске, в Nette мы можем разделить презентаторы, шаблоны и другие вспомогательные классы на модули. Как это работает на практике? Просто путем включения в структуру новых подкаталогов. Вот пример структуры с двумя модулями - Front и Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← директория с модулями
-│   ├── <b>Admin/</b>            ← модуль Admin
-│   │   ├── <b>Presenters/</b>   ← его презентеры
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← модуль Front
-│       └── <b>Presenters/</b>   ← его презентеры
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Эта структура каталогов будет отражена в пространствах имен классов, так, например, `DashboardPresenter` будет находиться в пространстве `App\Modules\Admin\Presenters`:
+Эта структура каталогов отражается в пространствах имен классов, так, например, `DashboardPresenter` находится в пространстве имен `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Ведущий `Dashboard` внутри модуля `Admin` обозначается в приложении с помощью двойной точечной нотации как `Admin:Dashboard`, а его действие `default` обозначается как `Admin:Dashboard:default`.
-А откуда Nette знает, что `Admin:Dashboard` представляет класс `App\Modules\Admin\Presenters\DashboardPresenter`? Мы говорим об этом, используя [отображение |#Mapping] в конфигурации.
-Таким образом, приведенная структура не является фиксированной, и вы можете изменять ее по своему усмотрению.
+В приложении мы ссылаемся на ведущего `Dashboard` в модуле `Admin` через двоеточие как `Admin:Dashboard`. Для его действия `default` мы ссылаемся на него как на `Admin:Dashboard:default`.
+
+Представленная структура не является жесткой; вы можете [полностью настроить ее под свои нужды |#mapping] в конфигурации. .[tip]
 
-Модули, конечно, могут содержать все другие части, помимо презентаторов и шаблонов, такие как компоненты, классы моделей и т.д.
+Модули могут включать в себя все остальные файлы, такие как компоненты и вспомогательные классы, в дополнение к ведущим и шаблонам. Если вы раздумываете над тем, где их разместить, рассмотрите возможность использования папки `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Вложенные модули .[#toc-nested-modules]
 ---------------------------------------
 
-Модули не обязательно должны формировать только плоскую структуру, вы также можете создавать, например, подмодули:
+Модули могут иметь несколько уровней вложенности, подобно структуре каталогов на диске:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← директория с модулями
-│   ├── <b>Blog/</b>             ← модуль Blog
-│   │   ├── <b>Admin/</b>        ← подмодуль Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← подмодуль Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← модуль Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Таким образом, модуль `Blog` разбивается на подмодули `Admin` и `Front`. И опять же это будет отражено в пространствах имен, которые будут `App\Modules\Blog\Admin\Presenters` и т.д. Ведущий `Dashboard` внутри подмодуля называется `Blog:Admin:Dashboard`.
+Модуль `Blog` делится на подмодули `Admin` и `Front`. Это также отражено в пространствах имен, которые отображаются как `App\UI\Blog\Admin` и аналогично. Для обозначения ведущего `Dashboard` в подмодуле `Admin` мы обозначаем его как `Blog:Admin:Dashboard`.
+
+Вложенность может быть настолько глубокой, насколько это необходимо, что позволяет создавать подмодули.
 
-Ветвление может быть настолько глубоким, насколько вы захотите, поэтому вы можете создавать подмодули.
+Например, если в администрировании есть много ведущих, связанных с управлением заказами, таких как `OrderDetail`, `OrderEdit`, `OrderDispatch`, и т. д., можно создать модуль `Order`, в котором будут организованы ведущие `Detail`, `Edit`, `Dispatch`, и другие.
 
 
 Создание ссылок .[#toc-creating-links]
@@ -102,47 +118,66 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 Составление карты .[#toc-mapping]
 ---------------------------------
 
-Определяет правила, по которым имя класса выводится из имени ведущего. Мы записываем их в [конфигурацию |configuration] под ключом `application › mapping`.
+Mapping определяет правила получения имени класса из имени ведущего. Эти правила задаются в [конфигурации |configuration] под ключом `application › mapping`.
 
-Начнем с примера, в котором не используются модули. Мы просто хотим, чтобы классы ведущего имели пространство имен `App\Presenters`. То есть мы хотим, чтобы ведущий, например, `Home` отображался на класс `App\Presenters\HomePresenter`. Этого можно достичь с помощью следующей конфигурации:
+Структуры каталогов, упомянутые ранее на этой странице, основаны на следующем отображении:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Имя презентера заменяется звездочкой, и в результате получается название класса. Легко!
+Как работает отображение? Для лучшего понимания давайте сначала представим себе приложение без модулей. Мы хотим, чтобы классы ведущих относились к пространству имен `App\UI`, так что ведущий `Home` отображается на класс `App\UI\HomePresenter`. Этого можно добиться с помощью следующей конфигурации:
 
-Если мы разделим докладчиков на модули, то для каждого модуля у нас может быть свой маппинг:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Это сопоставление работает путем замены звездочки в маске `App\UI\*Presenter` на имя ведущего `Home`, в результате чего мы получаем конечное имя класса `App\UI\HomePresenter`. Просто!
+
+Однако, как вы можете видеть в примерах этой и других глав, мы размещаем классы ведущих в одноименных подкаталогах, например, ведущий `Home` отображается на класс `App\UI\Home\HomePresenter`. Это достигается удвоением звездочки (требуется Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Теперь перейдем к сопоставлению ведущих с модулями. Для каждого модуля мы можем определить конкретное сопоставление:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Теперь презентер `Front:Home` определяется классом `App\Modules\Front\HomePresenter`, а презентер `Admin:Dashboard` — `App\AdminModule\DashboardPresenter`.
+Согласно этой конфигурации, ведущий `Front:Home` соотносится с классом `App\UI\Front\Home\HomePresenter`, а ведущий `Api:OAuth` - с классом `App\Api\OAuthPresenter`.
 
-Удобнее будет создать общее правило (звездочка), которое заменит первые два правила и добавит дополнительную звездочку только для модуля:
+Поскольку модули `Front` и `Admin` имеют схожий подход к отображению и, скорее всего, таких модулей будет больше, можно создать общее правило, которое заменит их. В маску класса добавляется новая звездочка для модуля:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Но что если мы используем несколько вложенных модулей и у нас есть, например, ведущий `Admin:User:Edit`? В этом случае сегмент со звездочкой, представляющий модуль для каждого уровня, будет просто повторяться, и результатом будет класс `App\Modules\Admin\User\Presenters\EditPresenter`.
+Для многоуровневых вложенных модулей, таких как ведущий `Admin:User:Edit`, сегмент звездочки повторяется для каждого уровня, в результате чего получается класс `App\UI\Admin\User\Edit\EditPresenter`.
 
 Альтернативной нотацией является использование массива, состоящего из трех сегментов, вместо строки. Эта нотация эквивалентна предыдущей:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Значение по умолчанию - `*: *Module\*Presenter`.
+Если у нас в конфигурации только одно правило, общее, то можно написать коротко:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/ru/presenters.texy b/application/ru/presenters.texy
index 70b5df9ace..ac48e3a344 100644
--- a/application/ru/presenters.texy
+++ b/application/ru/presenters.texy
@@ -60,7 +60,7 @@ class ArticlePresenter extends Nette\Application\UI\Presenter
 
 Важно, что `action<Action>()` вызывается перед `render<View>()`, поэтому внутри него мы можем, возможно, изменить следующий ход жизненного цикла, т. е. изменить шаблон, который будет отображаться, а также метод `render<View>()`, который будет вызываться, используя `setView('otherView')`.
 
-В метод передаются параметры из запроса. Можно и рекомендуется указывать типы для параметров, например `actionShow(int $id, string $slug = null)` — если параметр `id` отсутствует или если он не является целым числом, презентер возвращает [ошибку 404|#Error-404-etc] и завершает операцию.
+В метод передаются параметры из запроса. Можно и рекомендуется указывать типы для параметров, например `actionShow(int $id, ?string $slug = null)` — если параметр `id` отсутствует или если он не является целым числом, презентер возвращает [ошибку 404|#Error-404-etc] и завершает операцию.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */);
 Ошибка 404 и т. д. .[#toc-error-404-etc]
 ========================================
 
-Когда мы не можем выполнить запрос, потому что, например, статья, которую мы хотим отобразить, не существует в базе данных, мы выбросим ошибку 404, используя метод `error(string $message = null, int $httpCode = 404)`, который представляет HTTP-ошибку 404:
+Когда мы не можем выполнить запрос, потому что, например, статья, которую мы хотим отобразить, не существует в базе данных, мы выбросим ошибку 404, используя метод `error(?string $message = null, int $httpCode = 404)`, который представляет HTTP-ошибку 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Параметры запроса .[#toc-request-parameters]
+============================================
+
+Ведущий, как и каждый компонент, получает свои параметры из HTTP-запроса. Их значения могут быть получены с помощью метода `getParameter($name)` или `getParameters()`. Значения представляют собой строки или массивы строк, по сути, необработанные данные, полученные непосредственно из URL.
+
+Для большего удобства рекомендуется сделать параметры доступными через свойства. Для этого достаточно аннотировать их с помощью `#[Parameter]` атрибутом:
+
+```php
+use Nette\Application\Attributes\Parameter;  // эта строка очень важна
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // должна быть публичной
+}
+```
+
+Для свойств рекомендуется указывать тип данных (например, `string`). В этом случае Nette будет автоматически приводить значение на его основе. Значения параметров также могут быть [проверены |#Validation of Parameters].
+
+При создании ссылки можно непосредственно задать значение параметров:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Постоянные параметры .[#toc-persistent-parameters]
 ==================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Если `$this->lang` имеет значение, например, `'en'`, то ссылки, созданные с помощью `link()` или `n:href`, также будут содержать параметр `lang=en`. И когда ссылка будет щелкнута, она снова станет `$this->lang = 'en'`.
 
-Для свойств рекомендуется указывать тип данных (например, `string`), а также можно указать значение по умолчанию. Значения параметров могут быть [проверены |#Validation of Persistent Parameters].
+Для свойств рекомендуется указывать тип данных (например, `string`), а также можно указать значение по умолчанию. Значения параметров могут быть [проверены |#Validation of Parameters].
 
 Постоянные параметры по умолчанию передаются между всеми действиями данного ведущего. Чтобы передать их между несколькими ведущими, необходимо определить их либо:
 
@@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Того, что мы показали до сих пор в этой главе, вероятно, будет достаточно. Следующие строки предназначены для тех, кто интересуется презентерами досконально и хочет знать всё.
 
 
-Требования и параметры .[#toc-requirement-and-parameters]
----------------------------------------------------------
-
-Запрос, обрабатываемый ведущим, представляет собой объект [api:Nette\Application\Request] и возвращается методом ведущего `getRequest()`. Он включает в себя массив параметров, и каждый из них принадлежит либо какому-то из компонентов, либо непосредственно ведущему (который на самом деле тоже является компонентом, хотя и специальным). Поэтому Nette перераспределяет параметры и передает их между отдельными компонентами (и ведущим), вызывая метод `loadState(array $params)`. Параметры могут быть получены методом `getParameters(): array`, индивидуально с помощью `getParameter($name)`. Значения параметров представляют собой строки или массивы строк, в основном это необработанные данные, полученные непосредственно из URL.
+Валидация параметров .[#toc-validation-of-parameters]
+-----------------------------------------------------
 
+Значения [параметров запроса |#request parameters] и [постоянных параметров |#persistent parameters], получаемых из URL, записываются в свойства методом `loadState()`. При этом также проверяется соответствие типа данных, указанного в свойстве, в противном случае выдается ответ с ошибкой 404 и страница не отображается.
 
-Валидация постоянных параметров .[#toc-validation-of-persistent-parameters]
----------------------------------------------------------------------------
-
-Значения [постоянных параметров |#persistent parameters], полученных из URL, записываются в свойства методом `loadState()`. Он также проверяет, соответствует ли тип данных, указанный в свойстве, в противном случае выдается ошибка 404 и страница не отображается.
-
-Никогда не доверяйте слепо постоянным параметрам, так как они могут быть легко перезаписаны пользователем в URL. Например, так мы проверяем, входит ли `$this->lang` в число поддерживаемых языков. Хороший способ сделать это - переопределить метод `loadState()`, упомянутый выше:
+Никогда не следует слепо доверять параметрам, так как они могут быть легко перезаписаны пользователем в URL. Например, так мы проверяем, входит ли `$this->lang` в число поддерживаемых языков. Хороший способ сделать это - переопределить метод `loadState()`, упомянутый выше:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Сохранение и восстановление запроса .[#toc-save-and-restore-the-request]
 ------------------------------------------------------------------------
 
-Вы можете сохранить текущий запрос в сессии или восстановить его из сессии и позволить презентеру выполнить его снова. Это полезно, например, когда пользователь заполняет форму, а срок действия его логина истекает. Чтобы не потерять данные, перед перенаправлением на страницу регистрации мы сохраняем текущий запрос в сессию с помощью функции `$reqId = $this->storeRequest()`, которая возвращает идентификатор в виде короткой строки и передает его в качестве параметра презентеру для регистрации.
+Запрос, который обрабатывает ведущий, представляет собой объект [api:Nette\Application\Request] и возвращается методом ведущего `getRequest()`.
+
+Вы можете сохранить текущий запрос в сессии или восстановить его из сессии и позволить ведущему выполнить его снова. Это удобно, например, когда пользователь заполняет форму, а его логин истекает. Чтобы не потерять данные, перед перенаправлением на страницу входа в систему мы сохраняем текущий запрос в сессии с помощью метода `$reqId = $this->storeRequest()`, который возвращает идентификатор в виде короткой строки и передает его в качестве параметра презентеру входа в систему.
 
 После входа в систему мы вызываем метод `$this->restoreRequest($reqId)`, который забирает запрос у сессии и пересылает его ей. Метод проверяет, что запрос был создан тем же пользователем, который сейчас вошел в систему. Если другой пользователь вошел в систему или ключ недействителен, он ничего не делает, и программа продолжает работу.
 
@@ -362,7 +384,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Вы также можете вызвать канонизацию вручную с помощью метода `canonicalize()`, который, как и метод `link()`, получает в качестве аргументов презентера, действия и параметры. Он создает ссылку и сравнивает её с текущим URL. Если они отличаются, то происходит перенаправление на сгенерированную ссылку.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// перенаправляет, если $slug отличается от $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Ограничение доступа с помощью `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+---------------------------------------------------------------------------------------------------------
+
+Атрибут `#[Requires]` предоставляет расширенные возможности для ограничения доступа к ведущим и их методам. С его помощью можно указать HTTP-методы, потребовать AJAX-запросы, ограничить доступ к одному и тому же источнику и ограничить доступ только пересылкой. Атрибут может применяться как к классам ведущих, так и к отдельным методам, таким как `action<Action>()`, `render<View>()`, `handle<Signal>()`, и `createComponent<Name>()`.
+
+Вы можете указать эти ограничения:
+- на методы HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- требующих AJAX-запроса: `#[Requires(ajax: true)]`
+- доступ только из одного источника: `#[Requires(sameOrigin: true)]`
+- доступ только через переадресацию: `#[Requires(forward: true)]`
+- ограничения на определенные действия: `#[Requires(actions: 'default')]`
+
+Подробнее см. в разделе [Как использовать Requires атрибут |best-practices:attribute-requires].
+
+
+Проверка метода HTTP .[#toc-http-method-check]
+----------------------------------------------
+
+В Nette ведущие автоматически проверяют HTTP-метод каждого входящего запроса, прежде всего, из соображений безопасности. По умолчанию разрешены методы `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Если вы хотите разрешить дополнительные методы, такие как `OPTIONS`, вы можете использовать атрибут `#[Requires]` атрибут (из Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+В версии 3.1 проверка осуществляется в методе `checkHttpMethod()`, который проверяет, включен ли указанный в запросе метод в массив `$presenter->allowedMethods`. Добавьте метод следующим образом:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Важно подчеркнуть, что если вы разрешаете метод `OPTIONS`, то должны правильно обработать его и в своем презентаторе. Этот метод часто используется в качестве так называемого preflight-запроса, который браузеры автоматически отправляют перед фактическим запросом, когда необходимо определить, разрешен ли запрос с точки зрения политики CORS (Cross-Origin Resource Sharing). Если разрешить этот метод, но не реализовать соответствующий ответ, это может привести к несоответствиям и потенциальным проблемам безопасности.
+
+
 Дальнейшее чтение .[#toc-further-reading]
 =========================================
 
diff --git a/application/ru/routing.texy b/application/ru/routing.texy
index dd37c4fd4d..3363e2d1d5 100644
--- a/application/ru/routing.texy
+++ b/application/ru/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Расширенная нотация .[#toc-advanced-notation]
 ---------------------------------------------
 
-Второй параметр маршрута, который мы часто пишем в формате `Presenter:action`, является аббревиатурой, которую мы также можем написать в виде поля, где мы непосредственно указываем значения (по умолчанию) отдельных параметров:
+Цель маршрута, обычно записываемая в виде `Presenter:action`, также может быть выражена с помощью массива, определяющего отдельные параметры и их значения по умолчанию:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Или мы можем использовать эту форму, обратите внимание на переписывание регулярного выражения проверки:
+Для более детальной спецификации можно использовать еще более расширенную форму, в которой помимо значений по умолчанию можно задать другие свойства параметров, например, регулярное выражение для проверки (см. параметр `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Эти более подробные форматы полезны для добавления дополнительных метаданных.
+Важно отметить, что если параметры, определенные в массиве, не включены в маску пути, их значения не могут быть изменены, даже с помощью параметров запроса, указанных после вопросительного знака в URL.
 
 
 Фильтры и переводы .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Интеграция .[#toc-integration]
 ==============================
 
-Чтобы подключить наш маршрутизатор к приложению, мы должны сообщить о нем контейнеру DI. Самый простой способ - это подготовить фабрику, которая будет создавать объект маршрутизатора, и сообщить конфигурации контейнера, чтобы она его использовала. Допустим, мы напишем для этого метод `App\Router\RouterFactory::createRouter()`:
+Чтобы подключить наш маршрутизатор к приложению, мы должны сообщить о нем контейнеру DI. Самый простой способ - это подготовить фабрику, которая будет создавать объект маршрутизатора, и сообщить конфигурации контейнера, чтобы она его использовала. Допустим, мы напишем для этого метод `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ class RouterFactory
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Любые зависимости, такие как подключение к базе данных и т.д., передаются методу фабрики в качестве параметров с помощью [autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ $router->addRoute(/* ... */);
 Итак, мы снова добавим метод, который будет создавать, например, маршрутизатор:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Или мы будем создавать объекты напрямую:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/ru/templates.texy b/application/ru/templates.texy
index 75f2c784d0..4be9f83e4d 100644
--- a/application/ru/templates.texy
+++ b/application/ru/templates.texy
@@ -34,35 +34,81 @@ Nette использует систему шаблонов [Latte |latte:]. Latt
 Он определяет блок `content`, который вставляется вместо `{include content}` в макете, а также переопределяет блок `title`, который перезаписывает `{block title}` в макете. Попытайтесь представить себе результат.
 
 
-Поиск шаблонов .[#toc-search-for-templates]
--------------------------------------------
+Поиск шаблонов .[#toc-template-lookup]
+--------------------------------------
+
+В презентаторах вам не нужно указывать, какой шаблон должен быть отображен; фреймворк автоматически определит путь, облегчая вам кодирование.
+
+Если вы используете структуру каталогов, в которой у каждого ведущего есть своя директория, просто поместите шаблон в эту директорию под именем действия (т. е. представления). Например, для действия `default` используйте шаблон `default.latte`:
 
-Путь к шаблонам определяется ведущим с помощью простой логики. Он попытается проверить, есть ли один из этих файлов, расположенный относительно каталога класса ведущего, где `<Presenter>` это имя текущего ведущего, а `<view>` это имя текущего события:
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Если вы используете структуру, в которой ведущие находятся в одном каталоге, а шаблоны - в папке `templates`, сохраните их либо в файле `<Presenter>.<view>.latte` или `<Presenter>/<view>.latte`:
 
-Если шаблон не найден, он попытается выполнить поиск в каталоге `templates` на один уровень выше, т.е. на том же уровне, что и каталог с классом ведущего.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
 
-Если шаблон не найден и там, ответом будет [ошибка 404 |presenters#Error 404 etc.].
+Каталог `templates` можно также разместить на один уровень выше, на том же уровне, что и каталог с классами ведущих.
 
-Вы также можете изменить вид с помощью `$this->setView('jineView')`. Или, вместо прямого поиска, укажите имя файла шаблона с помощью `$this->template->setFile('/path/to/template.latte')`.
+Если шаблон не найден, ведущий отвечает [ошибкой 404 - страница не найдена |presenters#Error 404 etc].
+
+Изменить вид можно с помощью `$this->setView('anotherView')`. Также можно напрямую указать файл шаблона с помощью `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Файлы, в которых производится поиск шаблонов, можно изменить, наложив метод [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], который возвращает массив возможных имен файлов.
+Файлы, в которых производится поиск шаблонов, можно изменить, переопределив метод [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], который возвращает массив возможных имен файлов.
+
+
+Поиск шаблонов макета .[#toc-layout-template-lookup]
+----------------------------------------------------
+
+Nette также автоматически ищет файл макета.
+
+Если вы используете структуру каталогов, в которой у каждого ведущего есть своя директория, поместите макет либо в папку с ведущим, если он предназначен только для него, либо на уровень выше, если он общий для нескольких ведущих:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Если вы используете структуру, в которой ведущие сгруппированы в одном каталоге, а шаблоны находятся в папке `templates`, макет будет находиться в следующих местах:
 
-В этих файлах ожидается компоновка:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` макет, общий для нескольких докладчиков
+Если ведущий находится в [модуле |modules], он также будет искать дальше по дереву каталогов в соответствии с вложенностью модуля.
 
-Где `<Presenter>` это имя текущего ведущего и `<layout>` это имя макета, которое по умолчанию равно `'layout'`. Имя может быть изменено с помощью `$this->setLayout('jinyLayout')`, поэтому будут опробованы файлы `@jinyLayout.latte`.
+Имя макета можно изменить с помощью `$this->setLayout('layoutAdmin')`, и тогда оно будет ожидаться в файле `@layoutAdmin.latte`. Вы также можете напрямую указать файл шаблона макета с помощью `$this->setLayout('/path/to/template.latte')`.
 
-Вы также можете напрямую указать имя файла шаблона макета с помощью `$this->setLayout('/path/to/template.latte')`. Использование `$this->setLayout(false)` отключает отслеживание макета.
+Использование тега `$this->setLayout(false)` или `{layout none}` внутри шаблона отключает поиск макета.
 
 .[note]
-Файлы, в которых производится поиск шаблонов макета, можно изменить, наложив метод [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], который возвращает массив возможных имен файлов.
+Файлы, в которых производится поиск шаблонов макетов, можно изменить, переопределив метод [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], который возвращает массив возможных имен файлов.
 
 
 Переменные в шаблоне .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
 Вы также можете позволить себе роскошь шептать в шаблонах, просто установите плагин Latte в PhpStorm и поместите имя класса в начало шаблона, более подробную информацию смотрите в статье "Latte: как набирать систему":https://blog.nette.org/ru/latte-kak-ispol-zovat-sistemu-tipov:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte версии 3 предлагает более продвинутый способ создания [расширения |latte:creating-extension] для каждого веб-проекта. Вот краткий пример такого класса:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ protected function beforeRender(): void
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Транслятор можно использовать, например, в качестве фильтра `|translate`, передав дополнительные параметры в метод `translate()` (см. `foo, bar`):
diff --git a/application/sl/@home.texy b/application/sl/@home.texy
index e78407b83e..bb639d5c54 100644
--- a/application/sl/@home.texy
+++ b/application/sl/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | različica | združljivo s PHP
 |-----------|-------------------
-| Nette Application 4.0 | PHP 8.0 - 8.2
-| Nette Application 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/sl/ajax.texy b/application/sl/ajax.texy
index 1d982a2057..320e94b27c 100644
--- a/application/sl/ajax.texy
+++ b/application/sl/ajax.texy
@@ -3,10 +3,10 @@ AJAX in sličice
 
 <div class=perex>
 
-Sodobne spletne aplikacije danes tečejo pol na strežniku in pol v brskalniku. AJAX je ključni povezovalni dejavnik. Kakšno podporo ponuja ogrodje Nette?
-- pošiljanje fragmentov predlog (tako imenovanih *snippets*)
+V dobi sodobnih spletnih aplikacij, kjer je funkcionalnost pogosto razpeta med strežnikom in brskalnikom, je AJAX bistven povezovalni element. Katere možnosti ponuja ogrodje Nette na tem področju?
+- pošiljanje delov predloge, tako imenovanih snippets
 - posredovanje spremenljivk med PHP in JavaScriptom
-- razhroščevanje aplikacij AJAX
+- orodja za razhroščevanje zahtevkov AJAX
 
 </div>
 
@@ -14,29 +14,32 @@ Sodobne spletne aplikacije danes tečejo pol na strežniku in pol v brskalniku.
 Zahteva AJAX .[#toc-ajax-request]
 =================================
 
-Zahteva AJAX se ne razlikuje od klasične zahteve - predvajalnik se pokliče z določenim pogledom in parametri. Prav tako je od predstavnika odvisno, kako se bo nanjo odzval: uporabi lahko svojo rutino, ki vrne fragment kode HTML (fragment HTML), dokument XML, objekt JSON ali kodo JavaScript.
+Zahteva AJAX se v osnovi ne razlikuje od klasične zahteve HTTP. Predlagatelj se pokliče z določenimi parametri. Od predstavnika je odvisno, kako se bo odzval na zahtevo - lahko vrne podatke v obliki JSON, pošlje del kode HTML, dokument XML itd.
 
-Na strani strežnika je mogoče zahtevo AJAX zaznati s storitveno metodo, ki [enkapsulira zahtevo HTTP |http:request] `$httpRequest->isAjax()` (zazna na podlagi glave HTTP `X-Requested-With`). Znotraj predstavnika je na voljo bližnjica v obliki metode `$this->isAjax()`.
+Na strani brskalnika sprožimo zahtevo AJAX s funkcijo `fetch()`:
 
-Na voljo je vnaprej obdelan objekt, imenovan `payload`, namenjen pošiljanju podatkov brskalniku v obliki JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// obdelava odziva
+});
 ```
 
-Za popoln nadzor nad izpisom JSON uporabite metodo `sendJson` v svojem predstavitvenem programu. S tem se takoj zaključi predstavitveni program, vi pa boste opravili brez predloge:
+Na strani strežnika zahtevo AJAX prepozna metoda `$httpRequest->isAjax()` storitve, ki [enkapsulira zahtevo HTTP |http:request]. Uporablja glavo HTTP `X-Requested-With`, zato jo je nujno poslati. V predstavitvenem programu lahko uporabite metodo `$this->isAjax()`.
+
+Če želite poslati podatke v obliki JSON, uporabite metodo [`sendJson()` |presenters#Sending a response] metodo. Metoda tudi zaključi dejavnost predstavitvenega programa.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Če želimo poslati HTML, lahko nastavimo posebno predlogo za zahteve AJAX:
+Če se nameravate odzvati s posebno predlogo, zasnovano za AJAX, lahko to storite na naslednji način:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Utrinki .[#toc-snippets]
+========================
+
+Najzmogljivejše orodje, ki ga ponuja Nette za povezovanje strežnika z odjemalcem, so snippets. Z njimi lahko navadno aplikacijo spremenite v aplikacijo AJAX z minimalnim naporom in nekaj vrsticami kode. Primer Fifteen prikazuje, kako vse to deluje, njegovo kodo pa lahko najdete na [GitHubu |https://github.com/nette-examples/fifteen].
+
+Snippets ali clippings omogočajo posodabljanje samo delov strani, namesto da bi ponovno naložili celotno stran. To je hitrejše in učinkovitejše, poleg tega pa zagotavlja udobnejšo uporabniško izkušnjo. Snippets vas morda spominjajo na Hotwire za Ruby on Rails ali Symfony UX Turbo. Zanimivo pa je, da je Nette snippets predstavil že 14 let prej.
+
+Kako delujejo odlomki? Ob prvem nalaganju strani (zahteva, ki ni zahteva AJAX) se naloži celotna stran, vključno z vsemi snippets. Ko uporabnik komunicira s stranjo (npr. klikne gumb, odda obrazec itd.), se namesto nalaganja celotne strani izvede zahteva AJAX. Koda v predstavniku izvede dejanje in odloči, katere utrinke je treba posodobiti. Nette te utrinke prikaže in jih pošlje v obliki polja JSON. Obdelovalna koda v brskalniku nato vstavi prejete utrinke nazaj na stran. Zato se prenese samo koda spremenjenih izsekov, kar prihrani pasovno širino in pospeši nalaganje v primerjavi s prenosom celotne vsebine strani.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
- [Knjižnica Naja |https://naja.js.org] se uporablja za obdelavo zahtevkov AJAX na strani brskalnika. [Namestite |https://naja.js.org/#/guide/01-install-setup-naja] jo kot paket node.js (za uporabo s programi Webpack, Rollup, Vite, Parcel in drugimi):
+Za obdelavo izsekov na strani brskalnika se uporablja [knjižnica Naja |https://naja.js.org]. [Namestite jo |https://naja.js.org/#/guide/01-install-setup-naja] kot paket node.js (za uporabo z aplikacijami, kot so Webpack, Rollup, Vite, Parcel in druge):
 
 ```shell
 npm install naja
 ```
 
-...ali pa jo vstavite neposredno v predlogo strani:
+... ali jo vstavite neposredno v predlogo strani:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Če želite ustvariti zahtevo AJAX iz običajne povezave (signala) ali oddaje obrazca, preprosto označite ustrezno povezavo, obrazec ali gumb z razredom `ajax`:
+Najprej morate knjižnico [inicializirati |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization]:
+
+```js
+naja.initialize();
+```
+
+Če želite, da običajna povezava (signal) ali oddaja obrazca postane zahteva AJAX, preprosto označite ustrezno povezavo, obrazec ali gumb z razredom `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ npm install naja
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-. .[#toc-snippets]
-==================
-
-Obstaja veliko močnejše orodje vgrajene podpore AJAX - snippets. Z njihovo uporabo je mogoče navadno aplikacijo spremeniti v aplikacijo AJAX z uporabo le nekaj vrstic kode. Kako vse to deluje, je prikazano v primeru Fifteen, katerega koda je na voljo tudi v sestavi ali na [GitHubu |https://github.com/nette-examples/fifteen].
-
-Snippets delujejo tako, da se med začetno zahtevo (tj. zahtevo brez AJAX-a) prenese celotna stran, nato pa se pri vsaki [podpovprašitvi |components#signal] AJAX-a (zahteva istega pogleda istega predstavnika) v prej omenjeno shrambo `payload` prenese le koda spremenjenih delov.
-
-Snippets vas morda spominjajo na Hotwire za Ruby on Rails ali Symfony UX Turbo, vendar jih je Nette zasnoval že štirinajst let prej.
-
+Ponovno risanje utrinkov .[#toc-redrawing-snippets]
+---------------------------------------------------
 
-Neveljavnost nizov (Snippets) .[#toc-invalidation-of-snippets]
-==============================================================
-
-Vsak potomec razreda [Control |components] (kar je tudi Presenter) si lahko zapomni, ali je med zahtevo prišlo do kakšnih sprememb, zaradi katerih je treba ponovno prikazati. Za to obstaja par metod: `redrawControl()` in `isControlInvalid()`. Primer:
+Vsak objekt razreda [Control |components] (vključno s samim Presenterjem) beleži, ali so se zgodile spremembe, ki zahtevajo njegovo ponovno izrisovanje. V ta namen se uporablja metoda `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Objekt se mora ponovno prikazati, ko se uporabnik prijavi
+	// po prijavi je treba ponovno narisati ustrezni del
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Nette pa ponuja še natančnejšo ločljivost kot celotne komponente. Navedeni metodi kot neobvezni parameter sprejmeta ime tako imenovanega "snippeta". "Snippet" je v bistvu element v vaši predlogi, ki je v ta namen označen z oznako Latte, več o tem pozneje. Tako je mogoče od komponente zahtevati, da na novo nariše samo *delčke* svoje predloge. Če je celotna komponenta razveljavljena, se ponovno izrišejo vse njene sličice. Komponenta je "neveljavna" tudi, če je neveljavna katera koli njena podkomponenta.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // razveljavi odlomek z imenom 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, vsaj en delček je neveljaven
+Nette omogoča tudi natančnejši nadzor nad tem, kaj je treba ponovno narisati. Zgoraj omenjena metoda lahko kot argument sprejme ime izseka. Tako je mogoče razveljaviti (kar pomeni: prisiliti k ponovnemu izrisu) na ravni dela predloge. Če je celotna komponenta razveljavljena, se na novo nariše tudi vsak njen delček:
 
-$this->redrawControl(); // razveljavi celotno komponento, vsak odlomek
-$this->isControlInvalid('footer'); // -> true
+```php
+// razveljavi odlomek 'header'
+$this->redrawControl('header');
 ```
 
-Komponenta, ki prejme signal, je samodejno označena za ponovno izrisovanje.
-
-Zahvaljujoč ponovnemu izrisu snippetov natančno vemo, katere dele katerih elementov je treba ponovno izrisati.
-
-
-Oznaka `{snippet} … {/snippet}` .{toc: Tag snippet}
-===================================================
-
-Prikazovanje strani poteka zelo podobno kot pri običajni zahtevi: naložijo se iste predloge itd. Bistveno pa je, da se izpustijo deli, ki naj ne bi dosegli izpisa; drugi deli se povežejo z identifikatorjem in pošljejo uporabniku v obliki, razumljivi za obdelovalnik JavaScript.
-
 
-Sintaksa .[#toc-syntax]
------------------------
+Utrinki v Latte .[#toc-snippets-in-latte]
+-----------------------------------------
 
-Če je v predlogi kontrolni element ali izsek, ga moramo oviti z uporabo oznake `{snippet} ... {/snippet}` pair - ta bo poskrbela, da bo izrisani izsek "izrezan" in poslan brskalniku. Prav tako ga bo zaprla v pomožno vrstico `<div>` (možno je uporabiti tudi drugačno oznako). V naslednjem primeru je opredeljen izsek z imenom `header`. Prav tako lahko predstavlja predlogo komponente:
+Uporaba snippetov v Latte je zelo preprosta. Če želite del predloge opredeliti kot izsek, ga preprosto ovijte v oznake `{snippet}` in `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Sintaksa .[#toc-syntax]
 {/snippet}
 ```
 
-Snippet tipa, ki ni `<div>` ali izsek z dodatnimi atributi HTML se doseže z uporabo različice atributa:
+Snippet ustvari element `<div>` na strani HTML s posebej ustvarjeno oznako `id`. Pri ponovnem izrisu sličice se vsebina tega elementa posodobi. Zato je treba ob začetnem izrisu strani izrisati tudi vse sličice, čeprav so lahko na začetku prazne.
+
+Fragment lahko ustvarite tudi z elementom, ki ni `<div>` z uporabo atributa n::
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ Snippet tipa, ki ni `<div>` ali izsek z dodatnimi atributi HTML se doseže z upo
 ```
 
 
-Dinamični utrinki .[#toc-dynamic-snippets]
-==========================================
+Območja sličic .[#toc-snippet-areas]
+------------------------------------
 
-V programu Nette lahko na podlagi parametra v času izvajanja določite tudi dinamično ime snippetov. To je najbolj primerno za različne sezname, kjer moramo spremeniti samo eno vrstico, vendar ne želimo skupaj z njo prenesti celotnega seznama. Primer tega je:
+Imena snippetov so lahko tudi izrazi:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Obstaja en statični niz z imenom `itemsContainer`, ki vsebuje več dinamičnih nizov: `item-0`, `item-1` in tako naprej.
+Tako bomo dobili več izsekov, kot so `item-0`, `item-1`, itd. Če bi neposredno razveljavili dinamični snippet (npr. `item-1`), se ne bi nič na novo izrisalo. Razlog za to je, da utrinki delujejo kot pravi izvlečki in se neposredno izrisujejo le oni sami. Vendar v predlogi tehnično ni nobenega odlomka z imenom `item-1`. Pojavi se šele ob izvajanju okoliške kode snippeta, v tem primeru zanke foreach. Zato bomo del predloge, ki ga je treba izvesti, označili z oznako `{snippetArea}`:
 
-Dinamičnega utrinka ne morete narisati neposredno (ponovno narisanje `item-1` nima učinka), temveč morate narisati njegov nadrejeni utrinek (v tem primeru `itemsContainer`). To povzroči, da se izvede koda nadrejenega odlomka, vendar se nato brskalniku pošljejo samo njegovi pododlomki. Če želite poslati samo enega od podnapisov, morate spremeniti vnos za nadrejeni odlomek, da ne bo ustvaril drugih podnapisov.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-V zgornjem primeru morate poskrbeti, da bo za zahtevo AJAX v polje `$list` dodan samo en element, zato bo zanka `foreach` izpisala samo en dinamični odlomek.
+In na novo bomo narisali tako posamezni izsek kot celotno krovno območje:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Prav tako je treba zagotoviti, da polje `$items` vsebuje samo elemente, ki jih je treba ponovno narisati.
 
-Utrinki v vključeni predlogi .[#toc-snippets-in-an-included-template]
-=====================================================================
-
-Lahko se zgodi, da je snippet v predlogi, ki je vključena iz druge predloge. V tem primeru moramo vključitveno kodo v drugi predlogi oviti z oznako `snippetArea`, nato pa ponovno narišemo območje snippetArea in dejanski snippet.
-
-Oznaka `snippetArea` zagotavlja, da se koda v njej izvrši, vendar se brskalniku pošlje le dejanski odlomek iz vključene predloge.
+Pri vstavljanju druge predloge v glavno s pomočjo oznake `{include}`, ki ima izseke, je treba vključeno predlogo ponovno zaviti v `snippetArea` in razveljaviti tako izsek kot območje skupaj:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Kombinirate jo lahko tudi z dinamičnimi utrinki.
 
+Utrinki v sestavinah .[#toc-snippets-in-components]
+---------------------------------------------------
 
-Dodajanje in brisanje .[#toc-adding-and-deleting]
-=================================================
-
-Če na seznam dodate nov element in razveljavite `itemsContainer`, zahteva AJAX vrne odlomke, vključno z novim elementom, vendar ga obdelovalnik javascript ne bo mogel prikazati. Razlog za to je, da ni elementa HTML z novo ustvarjenim ID.
-
-V tem primeru je najpreprostejši način, da celoten seznam zavijete v še en izsek in ga razveljavite:
+V [komponentah |components] lahko ustvarite sličice in Nette jih bo samodejno ponovno narisal. Vendar pa obstaja posebna omejitev: za ponovno izrisovanje snippetov je treba poklicati metodo `render()` brez parametrov. Tako posredovanje parametrov v predlogi ne bo delovalo:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Pošiljanje uporabniških podatkov .[#toc-sending-user-data]
+----------------------------------------------------------
+
+Skupaj z odlomki lahko odjemalcu pošljete vse dodatne podatke. Preprosto jih zapišite v objekt `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Enako velja za brisanje elementa. Možno bi bilo poslati prazen snippet, vendar so običajno seznami lahko oštevilčeni in bi bilo zapleteno izvesti brisanje enega elementa in nalaganje drugega (ki je bil prej na drugi strani oštevilčenega seznama).
-
 
-Pošiljanje parametrov sestavini .[#toc-sending-parameters-to-component]
-=======================================================================
+Pošiljanje parametrov .[#toc-sending-parameters]
+================================================
 
-Ko komponenti prek zahteve AJAX pošiljamo parametre, bodisi signalne bodisi trajne, moramo navesti njihovo globalno ime, ki vsebuje tudi ime komponente. Polno ime parametra vrne metoda `getParameterId()`.
+Ko komponenti z zahtevo AJAX pošiljamo parametre, bodisi signalne bodisi trajne, moramo navesti njihovo globalno ime, ki vsebuje tudi ime komponente. Polno ime parametra vrne metoda `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-In obdela metodo z ustreznimi parametri v komponenti.
+Metoda handle z ustreznimi parametri v komponenti:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/sl/bootstrap.texy b/application/sl/bootstrap.texy
index bc60e3cfe8..33f36e50e8 100644
--- a/application/sl/bootstrap.texy
+++ b/application/sl/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Konfigurator je odgovoren za nastavitev okolja aplikacije in storitev.
+		$this->configurator = new Configurator;
+		// Nastavite imenik za začasne datoteke, ki jih ustvari Nette (npr. sestavljene predloge).
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Program Nette je pameten in razvojni način se vklopi samodejno,
+		// lahko pa ga za določen naslov IP omogočite tako, da odkomentirate naslednjo vrstico:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Omogoči Tracy: najboljše orodje za razhroščevanje "švicarskega noža".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: samodejno naloži vse razrede v danem imeniku
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Nalaganje konfiguracijskih datotek
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Pri spletnih aplikacijah je začetna datoteka `index.php`, ki se nahaja v javnem imeniku `www/`. Omogoča, da razred `Bootstrap` inicializira okolje in vrne `$configurator`, ki ustvari vsebnik DI. Nato pridobi storitev `Application`, ki izvaja spletno aplikacijo:
+Začetna datoteka za spletne aplikacije je `index.php`, ki se nahaja v javnem imeniku `www/`. Uporablja razred `Bootstrap` za inicializacijo okolja in ustvarjanje vsebnika DI. Nato iz vsebnika pridobi storitev `Application`, ki zažene spletno aplikacijo:
 
 ```php
-// inicializacija okolja + pridobitev predmeta Configurator
-$configurator = App\Bootstrap::boot();
-// ustvarite vsebnik DI
-$container = $configurator->createContainer();
+$bootstrap = new App\Bootstrap;
+// Inicializacija okolja + ustvarjanje vsebnika DI
+$container = $bootstrap->bootWebApplication();
 // vsebnik DI ustvari objekt Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// zaženite aplikacijo Nette
+// Zagnati aplikacijo Nette in obdelati vhodno zahtevo
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Izbira načina poteka s samodejnim zaznavanjem, zato običajno ni treba ničesar
 Če želite omogočiti razvojni način v drugih primerih, na primer za programerje, ki dostopajo z določenega naslova IP, lahko uporabite `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // enega ali več naslovov IP.
+$this->configurator->setDebugMode('23.75.345.200'); // enega ali več naslovov IP.
 ```
 
 Vsekakor priporočamo kombinacijo naslova IP s piškotkom. V piškotek `nette-debug` bomo shranili tajni žeton, npr. `secret1234`, razvojni način pa bo aktiviran za programerje s to kombinacijo IP in piškotka.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Razvojni način lahko tudi popolnoma izklopimo, tudi za lokalni gostitelj:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Vrednost `true` vklopi način za razvijalce, kar se na produkcijskem strežniku ne bi smelo zgoditi.
@@ -90,7 +115,7 @@ Orodje za razhroščevanje Tracy .[#toc-debugging-tool-tracy]
 Za lažje razhroščevanje bomo vklopili odlično orodje [Tracy |tracy:]. V načinu za razvijalce vizualizira napake, v produkcijskem načinu pa napake beleži v določen imenik:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Začasne datoteke .[#toc-temporary-files]
 Nette uporablja predpomnilnik za vsebnik DI, RobotLoader, predloge itd. Zato je treba nastaviti pot do imenika, v katerem bo shranjen predpomnilnik:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 V operacijskem sistemu Linux ali macOS nastavite [dovoljenja za pisanje za |nette:troubleshooting#Setting directory permissions] imenike `log/` in `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Običajno bomo želeli samodejno naložiti razrede z [RobotLoaderjem |robot-loader:], zato ga moramo zagnati in mu omogočiti, da naloži razrede iz imenika, kjer se nahaja `Bootstrap.php` (tj. `__DIR__`), in vseh njegovih podimenikov:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Druga možnost je, da uporabimo samo samodejno nalaganje [Composer |best-practic
 Configurator vam omogoča, da določite časovni pas za svojo aplikacijo.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ V razvojnem načinu se vsebnik samodejno posodobi vsakič, ko spremenite kodo al
 Konfiguracijske datoteke se naložijo z uporabo `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Metodo `addConfig()` lahko za dodajanje več datotek pokličete večkrat.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Statični parametri .[#toc-static-parameters]
 Parametre, ki se uporabljajo v konfiguracijskih datotekah, je mogoče opredeliti [v razdelku `parameters` |dependency-injection:configuration#parameters] in jih tudi posredovati (ali prepisati) z metodo `addStaticParameters()` (ima vzdevek `addParameters()`). Pomembno je, da različne vrednosti parametrov povzročijo generiranje dodatnih vsebnikov DI, tj. dodatnih razredov.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Dinamični parametri .[#toc-dynamic-parameters]
 Kontejnerju lahko dodamo tudi dinamične parametre, katerih različne vrednosti za razliko od statičnih parametrov ne bodo povzročile generiranja novih DI kontejnerjev.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Spremenljivke okolja bi lahko preprosto dali na voljo z dinamičnimi parametri. Do njih lahko dostopamo prek spletne strani `%env.variable%` v konfiguracijskih datotekah.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ V konfiguracijskih datotekah lahko uporabite naslednje statične parametre:
 - `%wwwDir%` je absolutna pot do imenika, ki vsebuje vstopno datoteko `index.php`
 - `%tempDir%` je absolutna pot do imenika za začasne datoteke
 - `%vendorDir%` je absolutna pot do imenika, v katerega Composer namesti knjižnice
+- `%rootDir%` je absolutna pot do korenskega imenika projekta
 - `%debugMode%` označuje, ali je aplikacija v načinu odpravljanja napak
 - `%consoleMode%` označuje, ali je bila zahteva poslana prek ukazne vrstice
 
@@ -225,7 +252,7 @@ services:
 Ustvarite nov primerek in ga vstavite v bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Različna okolja .[#toc-different-environments]
 ==============================================
 
-Razred `Bootstrap` lahko prilagodite svojim potrebam. Metodi `boot()` lahko dodate parametre za razlikovanje med spletnimi projekti ali dodate druge metode, kot so `bootForTests()`, ki inicializira okolje za teste enote, `bootForCli()` za skripte, ki se kličejo iz ukazne vrstice, in tako naprej.
+Ne oklevajte, če želite razred `Bootstrap` prilagoditi svojim potrebam. Metodi `bootWebApplication()` lahko dodate parametre za razlikovanje med spletnimi projekti. Lahko pa dodate tudi druge metode, na primer `bootTestEnvironment()` za inicializacijo okolja za teste enote, `bootConsoleApplication()` za skripte, ki se kličejo iz ukazne vrstice, in tako naprej.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
 {
-	$configurator = self::boot();
 	Tester\Environment::setup(); // Inicializacija Nette Testerja
-	return $configurator;
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
+{
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/sl/components.texy b/application/sl/components.texy
index 9947ac0b0f..344d660993 100644
--- a/application/sl/components.texy
+++ b/application/sl/components.texy
@@ -230,6 +230,28 @@ V predlogi so ta sporočila na voljo v spremenljivki `$flashes` kot objekti `std
 ```
 
 
+Preusmeritev po signalu .[#toc-redirection-after-a-signal]
+==========================================================
+
+Po obdelavi signala komponente pogosto sledi preusmeritev. Ta situacija je podobna obrazcem - po oddaji obrazca prav tako preusmerimo, da preprečimo ponovno oddajo podatkov ob osvežitvi strani v brskalniku.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Ker je komponenta element za večkratno uporabo in običajno ne sme biti neposredno odvisna od določenih predstavnikov, metodi `redirect()` in `link()` samodejno interpretirata parameter kot signal komponente:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Če želite preusmeriti na drug predstavnik ali dejanje, lahko to storite prek predstavnika:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Trajni parametri .[#toc-persistent-parameters]
 ==============================================
 
@@ -347,7 +369,7 @@ services:
 Na koncu bomo to tovarno uporabili v našem predstavitvenem programu:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Komponente poglobljeno .[#toc-components-in-depth]
 Komponente v aplikaciji Nette so ponovno uporabni deli spletne aplikacije, ki jih vgrajujemo v strani, kar je predmet tega poglavja. Kakšne natančno so zmožnosti takšne komponente?
 
 1) mogoče jo je izrisati v predlogi
-2) ve, kateri del sebe naj prikaže med [zahtevo AJAX |ajax#invalidation] (odlomki)
+2) ve, [kateri del sebe |ajax#snippets] naj prikaže med zahtevo AJAX (fragmenti).
 3) ima možnost shranjevanja svojega stanja v naslovu URL (trajni parametri).
 4) ima sposobnost odzivanja na dejanja uporabnika (signali)
 5) ustvarja hierarhično strukturo (kjer je korenski element predstavnik)
diff --git a/application/sl/configuration.texy b/application/sl/configuration.texy
index e05f269f44..179324658b 100644
--- a/application/sl/configuration.texy
+++ b/application/sl/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# prikazuje ploščo "Nette Application" v programu Tracy BlueScreen?
 	debugger: ...           # (bool) privzeto je true
 
-	# ali se ob napaki pokliče error-presenter?
-	catchExceptions: ...    # (bool) privzeto true v produkcijskem načinu
+	# se bo ob napaki poklical predstavnik napak?
+	# učinkuje samo v načinu za razvijalce
+	catchExceptions: ...    # (bool) privzeto true
 
 	# ime programa error-presenter
-	errorPresenter: Error   # (string) privzeto 'Nette:Error'
+	errorPresenter: Error   # (string|array) privzeto 'Nette:Error'
+
+	# določa vzdevke za voditelje in dogodke
+	aliases: ...
 
 	# določa pravila za razrešitev imena predstavnika na razred
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) privzeto je false
 ```
 
-Ker se v razvojnem načinu predstavniki napak privzeto ne kličejo, napake pa prikazuje Tracy, sprememba vrednosti `catchExceptions` v `true` pomaga preveriti, ali predstavniki napak med razvojem delujejo pravilno.
+Od različice `nette/application` 3.2 je mogoče določiti par predstavnikov napak:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # za Nette\Application\BadRequestException
+		5xx: Error5xx   # za druge izjeme
+```
 
 Možnost `silentLinks` določa, kako se Nette obnaša v razvojnem načinu, ko generiranje povezav ne uspe (na primer ker ni predstavnika itd.). Privzeta vrednost `false` pomeni, da Nette sproži `E_USER_WARNING`. Nastavitev na `true` to sporočilo o napaki odpravi. V produkcijskem okolju se vedno sproži `E_USER_WARNING`. Na to obnašanje lahko vplivamo tudi z nastavitvijo spremenljivke presenterja [$invalidLinkMode |creating-links#Invalid Links].
 
+[Psevdonimi poenostavijo sklicevanje na |creating-links#aliases] pogosto uporabljene predstavnike.
+
  [Prikazovanje določa pravila, |modules#mapping] po katerih se ime razreda izpelje iz imena predstavnika.
 
 
@@ -82,6 +95,9 @@ latte:
 	# omogoča [preverjanje ustvarjene kode |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) privzeto je null
 
+	# nastavi krajevni jezik
+	locale: cs_CZ        # (string) privzeto je nič
+
 	# razred $this->template
 	templateClass: App\MyTemplateClass # privzeto je Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ latte:
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/sl/creating-links.texy b/application/sl/creating-links.texy
index 4943feeb98..3f8341829c 100644
--- a/application/sl/creating-links.texy
+++ b/application/sl/creating-links.texy
@@ -38,7 +38,7 @@ Lahko ji posredujemo tudi poimenovane parametre. Naslednja povezava posreduje pa
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-Če metoda `ProductPresenter::renderShow()` v svojem podpisu nima zapisa `$lang`, lahko vrednost parametra prebere z uporabo `$lang = $this->getParameter('lang')`.
+Če metoda `ProductPresenter::renderShow()` v svojem podpisu nima `$lang`, lahko vrednost parametra pridobi z uporabo `$lang = $this->getParameter('lang')` ali iz [lastnosti |presenters#Request Parameters].
 
 Če so parametri shranjeni v polju, jih je mogoče razširiti z operatorjem `...` (ali `(expand)` v Latte 2.x):
 
@@ -140,7 +140,7 @@ Ciljna stran `this` bo ustvarila povezavo do trenutne strani:
 <a n:href="this">refresh</a>
 ```
 
-Hkrati se vsi parametri, navedeni v podpisu `render<View>()` ali `action<Action>()` se prenesejo. Če smo torej na straneh `Product:show` in `id:123`, bo tudi povezava do strani `this` prenesla ta parameter.
+Hkrati se vsi parametri, navedeni v podpisu `action<Action>()` ali . `render<View>()` metode, če je `action<Action>()` niso opredeljeni, se prenesejo. Če smo torej na straneh `Product:show` in `id:123`, bo povezava do strani `this` prenesla tudi ta parameter.
 
 Seveda je mogoče parametre navesti tudi neposredno:
 
@@ -213,7 +213,7 @@ Ker so [komponente |components] ločene enote za večkratno uporabo, ki naj ne b
 Če se želimo v predlogi komponente povezati s predstavniki, uporabimo oznako `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 ali v kodi
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Vzdevki .[#toc-aliases]{data-version:v3.2.2}
+============================================
+
+Včasih je koristno, da paru predavatelj:dejanje dodelite lahko zapomljiv vzdevek. Na primer, domačo stran `Front:Home:default` lahko poimenujete preprosto kot `home` ali `Admin:Dashboard:default` kot `admin`.
+
+Vzdevki so v [konfiguraciji |configuration] opredeljeni pod ključem `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+V povezavah so zapisani s simbolom at, na primer:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Podprte so v vseh metodah, ki delajo s povezavami, na primer `redirect()` in podobno.
+
+
 Neveljavne povezave .[#toc-invalid-links]
 =========================================
 
diff --git a/application/sl/how-it-works.texy b/application/sl/how-it-works.texy
index 9139f15de5..53d08d145d 100644
--- a/application/sl/how-it-works.texy
+++ b/application/sl/how-it-works.texy
@@ -22,18 +22,18 @@ Struktura imenikov je videti nekako takole:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← osnovni potrebni razredi
+│   │   └── <b>RouterFactory.php</b> ← konfiguracija naslovov URL
+│   ├── <b>UI/</b>                   ← predstavitev, predloge in podobno.
+│   │   ├── <b>@layout.latte</b>     ← predloga skupne postavitve
+│   │   └── <b>Home/</b>             ← Domači imenik predstavnikov
+│   │       ├── <b>HomePresenter.php</b> ← Razred HomePresenter
+│   │       └── <b>default.latte</b> ← predloga za akcijo default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ Aplikacije, napisane v okolju Nette, so razdeljene na številne tako imenovane p
 
 Aplikacija se začne tako, da zahteva od tako imenovanega usmerjevalnika, da se odloči, kateremu od predstavnikov bo posredoval trenutno zahtevo v obdelavo. Usmerjevalnik se odloči, čigava je to odgovornost. Pregleda vhodni naslov URL `https://example.com/product/123`, ki želi `show` izdelek z `id: 123` kot dejanjem. Dobra navada je, da se pari predstavnik + akcija, ločeni z dvopičjem, zapišejo kot `Product:show`.
 
-Usmerjevalnik je torej pretvoril naslov URL v par `Presenter:action` + parametri, v našem primeru `Product:show` + `id: 123`. Kako je videti usmerjevalnik, si lahko ogledate v datoteki `app/Router/RouterFactory.php`, podrobno pa ga bomo opisali v poglavju [Usmerjanje |Routing].
+Usmerjevalnik je torej pretvoril naslov URL v par `Presenter:action` + parametri, v našem primeru `Product:show` + `id: 123`. Kako je videti usmerjevalnik, si lahko ogledate v datoteki `app/Core/RouterFactory.php`, podrobno pa ga bomo opisali v poglavju [Usmerjanje |Routing].
 
 Pojdimo naprej. Aplikacija že pozna ime predavatelja in lahko nadaljuje. Z ustvarjanjem predmeta `ProductPresenter`, ki je koda predstavnika `Product`. Natančneje, za ustvarjanje predstavnika zaprosi vsebnik DI, saj je izdelovanje objektov njegova naloga.
 
@@ -121,12 +121,9 @@ Tako je bila klicana metoda `renderShow(123)`, katere koda je izmišljen primer,
 
 Nato predstavnik vrne odgovor. To je lahko stran HTML, slika, dokument XML, pošiljanje datoteke z diska, JSON ali preusmeritev na drugo stran. Pomembno je, da če izrecno ne navedemo, kako odgovoriti (kar je primer `ProductPresenter`), bo odgovor prikaz predloge s stranjo HTML. Zakaj? No, ker v 99 % primerov želimo izrisati predlogo, zato predstavnik to vedenje sprejme kot privzeto in nam želi olajšati delo. To je Nettejeva poanta.
 
-Ni nam treba niti navesti, katero predlogo želimo narisati, on pot do nje izpelje po preprosti logiki. V primeru predstavnika `Product` in akcije `show`, poskuša preveriti, ali obstaja ena od teh datotek s predlogami glede na imenik, v katerem se nahaja razred `ProductPresenter`:
+Sploh nam ni treba navesti, katero predlogo je treba prikazati; ogrodje bo pot določilo samo. V primeru akcije `show` preprosto poskuša naložiti predlogo `show.latte` v imeniku z razredom `ProductPresenter`. Prav tako poskuša najti postavitev v datoteki `@layout.latte` (več o [iskanju predlog |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Prav tako poskuša poiskati postavitev v datoteki `@layout.latte` in nato upodobi predlogo. Zdaj je naloga predstavnika in celotne aplikacije končana. Če predloga ne obstaja, se vrne stran z napako 404. Več o predstavitvah si lahko preberete na strani [Predstavitve |Presenters].
+Nato se predloge izrišejo. S tem je naloga predstavnika in celotne aplikacije končana in delo je opravljeno. Če predloga ne bi obstajala, bi se vrnila stran z napako 404. Več o predstavnikih si lahko preberete na strani [Predstavniki |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Da bi se prepričali, poskusite celoten postopek ponoviti z nekoliko drugačnim
 3) usmerjevalnik dekodira naslov URL kot par `Home:default`
 4) ustvari se objekt `HomePresenter`
 5) kličemo metodo `renderDefault()` (če obstaja)
-6) prikaže se predloga `templates/Home/default.latte` z razporeditvijo `templates/@layout.latte`
+6) prikaže se predloga `default.latte` z razporeditvijo `@layout.latte`
 
 
 Morda ste zdaj naleteli na veliko novih konceptov, vendar verjamemo, da so smiselni. Ustvarjanje aplikacij v programu Nette je zelo enostavno.
diff --git a/application/sl/modules.texy b/application/sl/modules.texy
index d37ea342b1..bda3fd5943 100644
--- a/application/sl/modules.texy
+++ b/application/sl/modules.texy
@@ -2,29 +2,31 @@ Moduli
 ******
 
 .[perex]
-V Nette moduli predstavljajo logične enote, ki sestavljajo aplikacijo. Vključujejo predstavnike, predloge, lahko tudi komponente in razrede modelov.
+Moduli vnašajo jasnost v aplikacije Nette, saj omogočajo enostavno razdelitev na logične enote.
 
-En imenik za predstavnike in en imenik za predloge za prave projekte ne bi bil dovolj. Če je v eni mapi na desetine datotek, je to vsaj neorganizirano. Kako to odpraviti? Preprosto jih razdelimo v podimenike na disku in v imenske prostore v kodi. In točno to naredijo moduli Nette.
-
-Pozabimo torej na eno mapo za predstavnike in predloge in namesto tega ustvarimo module, na primer `Admin` in `Front`.
+Podobno kot pri urejanju datotek v mape na trdem disku, lahko v Nette predstavnike, predloge in druge pomožne razrede razdelimo v module. Kako to deluje v praksi? Preprosto z vključevanjem novih podimenikov v strukturo. Tukaj je primer strukture z dvema moduloma, Front in Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Ta struktura imenikov se bo odražala v imenskih prostorih razredov, tako da bo na primer `DashboardPresenter` v imenskem prostoru `App\Modules\Admin\Presenters`:
+Ta imeniška struktura se odraža v imenskih prostorih razredov, tako da se na primer `DashboardPresenter` nahaja v imenskem prostoru `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Na predvajalnik `Dashboard` znotraj modula `Admin` se v aplikaciji sklicujemo z uporabo zapisa v dvopičju kot na `Admin:Dashboard`, na njegovo akcijo `default` pa kot na `Admin:Dashboard:default`.
-In kako Nette pravilno ve, da `Admin:Dashboard` predstavlja razred `App\Modules\Admin\Presenters\DashboardPresenter`? To je določeno s [preslikavo |#mapping] v konfiguraciji.
-Podana struktura torej ni trdno določena in jo lahko spreminjate glede na svoje potrebe.
+V aplikaciji se na predstavnik `Dashboard` znotraj modula `Admin` sklicujemo z uporabo zapisa v dvopičju kot `Admin:Dashboard`. Za njegovo akcijo `default` se sklicujemo na `Admin:Dashboard:default`.
+
+Predstavljena struktura ni toga; v konfiguraciji [jo |#mapping] lahko v [celoti prilagodite svojim potrebam |#mapping]. .[tip]
 
-Moduli seveda lahko poleg predstavnikov in predlog vsebujejo tudi vse druge elemente, kot so komponente, razredi modelov itd.
+Moduli lahko poleg predstavnikov in predlog vključujejo tudi vse druge datoteke, kot so komponente in pomožni razredi. Če razmišljate, kam jih umestiti, razmislite o uporabi mape `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Vgnezdeni moduli .[#toc-nested-modules]
 ---------------------------------------
 
-Ni nujno, da moduli tvorijo le ravno strukturo, ustvarite lahko tudi podmodule, na primer:
+Moduli so lahko vgrajeni na več ravneh, podobno kot struktura imenikov na disku:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Tako je modul `Blog` razdeljen na podmodula `Admin` in `Front`. Tudi to se bo odražalo v imenskih prostorih, ki bodo `App\Modules\Blog\Admin\Presenters` itd. Predstavnik `Dashboard` znotraj podmodula se imenuje `Blog:Admin:Dashboard`.
+Modul `Blog` je razdeljen na podmodula `Admin` in `Front`. To se odraža tudi v imenskih prostorih, ki so nato prikazani kot `App\UI\Blog\Admin` in podobno. Če se želimo sklicevati na predstavnik `Dashboard` znotraj podmodula `Admin`, ga imenujemo `Blog:Admin:Dashboard`.
+
+Gnezdenje je lahko tako globoko, kot je potrebno, kar omogoča ustvarjanje podmodulov.
 
-Gnezdenje je lahko tako globoko, kot želite, zato lahko ustvarite podmodule.
+Če imate na primer v administraciji veliko predstavnikov, povezanih z upravljanjem naročil, kot so `OrderDetail`, `OrderEdit`, `OrderDispatch` itd., lahko ustvarite modul `Order`, v katerem bodo organizirani predstavniki, kot so `Detail`, `Edit`, `Dispatch` in drugi.
 
 
 Ustvarjanje povezav .[#toc-creating-links]
@@ -102,47 +118,66 @@ Glejte [poglavje o usmerjanju |routing#Modules].
 Kartiranje .[#toc-mapping]
 --------------------------
 
-Določa pravila, po katerih se ime razreda izpelje iz imena predstavnika. Zapišemo jih v [konfiguracijo |configuration] pod ključ `application › mapping`.
+Mapiranje določa pravila za izpeljavo imena razreda iz imena predstavnika. Ta pravila so določena v [konfiguraciji |configuration] pod ključem `application › mapping`.
 
-Začnimo z vzorcem, ki ne uporablja modulov. Želeli bomo le, da imajo razredi predstavnikov imenski prostor `App\Presenters`. To pomeni, da mora biti predstavnik, kot je `Home`, preslikan v razred `App\Presenters\HomePresenter`. To lahko dosežemo z naslednjo konfiguracijo:
+Strukture imenikov, omenjene prej na tej strani, temeljijo na naslednjem preslikavanju:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-V maski razreda se ime predvajalnika nadomesti z zvezdico, rezultat pa je ime razreda. Enostavno!
+Kako deluje kartiranje? Za boljše razumevanje si najprej predstavljajmo aplikacijo brez modulov. Želimo, da razredi predstavnikov spadajo v imenski prostor `App\UI`, tako da se predstavnik `Home` preslika v razred `App\UI\HomePresenter`. To lahko dosežemo s to konfiguracijo:
 
-Če voditelje razdelimo na module, lahko za vsak modul pripravimo lastno preslikavo:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Ta preslikava deluje tako, da zvezdico v maski `App\UI\*Presenter` nadomestimo z imenom predstavnika `Home`, s čimer dobimo končno ime razreda `App\UI\HomePresenter`. Preprosto!
+
+Vendar, kot lahko vidite v primerih v tem in drugih poglavjih, umeščamo predstavitvene razrede v istoimenske podimenike, npr. predstavitveni razred `Home` je preslikan v razred `App\UI\Home\HomePresenter`. To dosežemo s podvojitvijo zvezdice (zahteva program Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Sedaj se lotimo preslikave predstavnikov v module. Za vsak modul lahko opredelimo posebna preslikavanja:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Sedaj je predstavnik `Front:Home` preslikan v razred `App\Modules\Front\Presenters\HomePresenter`, predstavnik `Admin:Dashboard` pa v razred `App\Modules\Admin\Presenters\DashboardPresenter`.
+V skladu s to konfiguracijo se predstavnik `Front:Home` prikaže v razred `App\UI\Front\Home\HomePresenter`, predstavnik `Api:OAuth` pa v razred `App\Api\OAuthPresenter`.
 
-Bolj praktično je ustvariti splošno (zvezdno) pravilo, ki bo nadomestilo prvi dve. Dodatna zvezdica bo dodana maski razreda samo za ta modul:
+Ker imata modula `Front` in `Admin` podoben pristop k preslikavi in ker bo takih modulov verjetno več, je mogoče ustvariti splošno pravilo, ki ju nadomesti. V masko razreda se doda nova zvezdica za modul:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Kaj pa, če uporabljamo vgnezdene module in imamo predvajalnik `Admin:User:Edit`? V tem primeru se segment z zvezdico, ki predstavlja modul za vsako raven, preprosto ponovi in rezultat je razred `App\Modules\Admin\User\Presenters\EditPresenter`.
+Za večnivojske vgnezdene module, kot je predstavnik `Admin:User:Edit`, se segment z zvezdico ponovi za vsako raven, tako da nastane razred `App\UI\Admin\User\Edit\EditPresenter`.
 
 Alternativni zapis je, da namesto niza uporabimo polje, sestavljeno iz treh segmentov. Ta zapis je enakovreden prejšnjemu:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Privzeta vrednost je `*: *Module\*Presenter`.
+Če imamo v konfiguraciji samo eno pravilo, splošno, lahko zapišemo na kratko:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/sl/presenters.texy b/application/sl/presenters.texy
index abfd2f2527..1f1e6b993b 100644
--- a/application/sl/presenters.texy
+++ b/application/sl/presenters.texy
@@ -60,7 +60,7 @@ Podobno kot pri metodi `render<View>()`. Medtem ko `render<View>()` je namenjena
 
 Pomembno je, da `action<Action>()` se pokliče pred `render<View>()`, tako da lahko znotraj njega morebiti spremenimo naslednji potek življenjskega cikla, tj. spremenimo predlogo, ki se bo izrisala, in tudi metodo `render<View>()` ki bo poklicana, z uporabo `setView('otherView')`.
 
-Parametri iz zahteve se posredujejo metodi. Za parametre je mogoče in priporočljivo določiti tipe, npr. `actionShow(int $id, string $slug = null)` - če parameter `id` manjka ali če ni celo število, predstavnik vrne [napako 404 |#Error 404 etc.] in zaključi operacijo.
+Parametri iz zahteve se posredujejo metodi. Za parametre je mogoče in priporočljivo določiti tipe, npr. `actionShow(int $id, ?string $slug = null)` - če parameter `id` manjka ali če ni celo število, predstavnik vrne [napako 404 |#Error 404 etc.] in zaključi operacijo.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ V predlogi so ta sporočila na voljo v spremenljivki `$flashes` kot objekti `std
 Napaka 404 itd. .[#toc-error-404-etc]
 =====================================
 
-Kadar ne moremo izpolniti zahteve, ker na primer članek, ki ga želimo prikazati, ne obstaja v zbirki podatkov, bomo z metodo `error(string $message = null, int $httpCode = 404)`, ki predstavlja napako HTTP 404, vrgli napako 404:
+Kadar ne moremo izpolniti zahteve, ker na primer članek, ki ga želimo prikazati, ne obstaja v zbirki podatkov, bomo z metodo `error(?string $message = null, int $httpCode = 404)`, ki predstavlja napako HTTP 404, vrgli napako 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Parametri zahtevka .[#toc-request-parameters]
+=============================================
+
+Predstavitelj in vsaka komponenta pridobi svoje parametre iz zahteve HTTP. Njihove vrednosti lahko pridobite z metodo `getParameter($name)` ali `getParameters()`. Vrednosti so nizi ali nizi nizov, v bistvu surovi podatki, pridobljeni neposredno iz URL.
+
+Zaradi večjega udobja priporočamo, da so parametri dostopni prek lastnosti. Preprosto jih opišite z ukazom `#[Parameter]` atributom:
+
+```php
+use Nette\Application\Attributes\Parameter;  // ta vrstica je pomembna
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // mora biti javna.
+}
+```
+
+Za lastnosti predlagamo, da navedete vrsto podatkov (npr. `string`). Nette bo na podlagi tega samodejno določil vrednost. Vrednosti parametrov je mogoče tudi [potrditi |#Validation of Parameters].
+
+Pri ustvarjanju povezave lahko neposredno določite vrednost za parametre:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Trajni parametri .[#toc-persistent-parameters]
 ==============================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Če ima `$this->lang` vrednost, kot je `'en'`, bodo povezave, ustvarjene z uporabo `link()` ali `n:href`, vsebovale tudi parameter `lang=en`. In ko boste povezavo kliknili, bo ta spet imela vrednost `$this->lang = 'en'`.
 
-Za lastnosti priporočamo, da vključite podatkovno vrsto (npr. `string`), vključite pa lahko tudi privzeto vrednost. Vrednosti parametrov je mogoče [potrditi |#Validation of Persistent Parameters].
+Za lastnosti priporočamo, da vključite podatkovno vrsto (npr. `string`), vključite pa lahko tudi privzeto vrednost. Vrednosti parametrov je mogoče [potrditi |#Validation of Parameters].
 
 Trajni parametri se privzeto posredujejo med vsemi dejanji določenega predstavnika. Če jih želite posredovati med več predstavniki, jih morate opredeliti:
 
@@ -307,18 +333,12 @@ Poglobitev .[#toc-going-deeper]
 To, kar smo doslej prikazali v tem poglavju, bo verjetno zadostovalo. Naslednje vrstice so namenjene tistim, ki jih predstavniki zanimajo poglobljeno in želijo vedeti vse.
 
 
-Zahteve in parametri .[#toc-requirement-and-parameters]
+Potrjevanje parametrov .[#toc-validation-of-parameters]
 -------------------------------------------------------
 
-Zahteva, ki jo obravnava predstavnik, je objekt [api:Nette\Application\Request] in jo vrne predstavnikova metoda `getRequest()`. Vključuje polje parametrov, vsak od njih pa pripada bodisi kateri od komponent bodisi neposredno predstavniku (ki je pravzaprav tudi komponenta, čeprav posebna). Nette torej parametre prerazporedi in posreduje med posameznimi komponentami (in predstavnikom) tako, da pokliče metodo `loadState(array $params)`. Parametre lahko pridobimo z metodo `getParameters(): array`, posamično pa z metodo `getParameter($name)`. Vrednosti parametrov so nizi ali polja nizov, v bistvu so surovi podatki, pridobljeni neposredno iz naslova URL.
+Vrednosti [parametrov zahteve |#request parameters] in [trajnih parametrov |#persistent parameters], prejetih z naslovov URL, se zapišejo v lastnosti z metodo `loadState()`. Preveri tudi, ali se podatkovna vrsta, navedena v lastnosti, ujema, sicer se odzove z napako 404 in stran se ne prikaže.
 
-
-Potrjevanje trajnih parametrov .[#toc-validation-of-persistent-parameters]
---------------------------------------------------------------------------
-
-Vrednosti [trajnih parametrov |#persistent parameters], prejetih z naslovov URL, se zapišejo v lastnosti z metodo `loadState()`. Preveri tudi, ali se podatkovna vrsta, navedena v lastnosti, ujema, sicer se odzove z napako 404 in stran se ne prikaže.
-
-Nikoli ne zaupajte slepo trajnim parametrom, saj jih lahko uporabnik zlahka prepiše v naslovu URL. Tako na primer preverimo, ali je `$this->lang` med podprtimi jeziki. Dober način za to je, da prekrijete zgoraj omenjeno metodo `loadState()`:
+Parametrom nikoli ne zaupajte na slepo, saj jih lahko uporabnik zlahka prepiše v naslovu URL. Tako na primer preverimo, ali je `$this->lang` med podprtimi jeziki. Dober način za to je, da prekrijete zgoraj omenjeno metodo `loadState()`:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Shranjevanje in obnavljanje zahtevka .[#toc-save-and-restore-the-request]
 -------------------------------------------------------------------------
 
-Trenutni zahtevek lahko shranite v sejo ali pa ga obnovite iz seje in omogočite predavatelju, da ga ponovno izvede. To je na primer uporabno, ko uporabnik izpolni obrazec in mu poteče prijava. Da ne bi izgubili podatkov, pred preusmeritvijo na stran za prijavo shranimo trenutno zahtevo v sejo z uporabo `$reqId = $this->storeRequest()`, ki vrne identifikator v obliki kratkega niza in ga kot parameter posreduje predstavniku za prijavo.
+Zahteva, ki jo predstavnik obravnava, je objekt [api:Nette\Application\Request] in jo vrne predstavnikova metoda `getRequest()`.
+
+Trenutni zahtevek lahko shranite v sejo ali pa ga obnovite iz seje in omogočite predstavniku, da ga ponovno izvede. To je na primer uporabno, ko uporabnik izpolni obrazec in mu poteče prijava. Da ne bi izgubili podatkov, pred preusmeritvijo na stran za prijavo shranimo trenutno zahtevo v sejo z uporabo `$reqId = $this->storeRequest()`, ki vrne identifikator v obliki kratkega niza in ga kot parameter posreduje predstavniku za prijavo.
 
 Po prijavi pokličemo metodo `$this->restoreRequest($reqId)`, ki prevzame zahtevo iz seje in ji jo posreduje naprej. Metoda preveri, ali je zahtevo ustvaril isti uporabnik, kot je zdaj prijavljeni. Če se prijavi drug uporabnik ali je ključ neveljaven, ne stori ničesar in program se nadaljuje.
 
@@ -362,7 +384,7 @@ Preusmeritev se ne izvede pri zahtevi AJAX ali POST, ker bi povzročila izgubo p
 Kanonizacijo lahko sprožite tudi ročno z metodo `canonicalize()`, ki tako kot metoda `link()` kot argumente prejme predstavnika, dejanja in parametre. Ustvari povezavo in jo primerja s trenutnim naslovom URL. Če se razlikuje, preusmeri na ustvarjeno povezavo.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// preusmeri, če se $slug razlikuje od $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Omejitev dostopa z uporabo `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+------------------------------------------------------------------------------------------------------
+
+. `#[Requires]` atribut zagotavlja napredne možnosti za omejevanje dostopa do predavateljev in njihovih metod. Z njim lahko določite metode HTTP, zahtevate zahteve AJAX, omejite dostop do istega izvora in omejite dostop samo na posredovanje. Atribut je mogoče uporabiti za razrede predstavnikov in posamezne metode, kot so `action<Action>()`, `render<View>()`, `handle<Signal>()`, in `createComponent<Name>()`.
+
+Določite lahko te omejitve:
+- za metode HTTP: `#[Requires(methods: ['GET', 'POST'])]`
+- ki zahteva zahtevo AJAX: `#[Requires(ajax: true)]`
+- dostop samo iz istega izvora: `#[Requires(sameOrigin: true)]`
+- dostop samo prek posredovanja: `#[Requires(forward: true)]`
+- omejitve za določena dejanja: `#[Requires(actions: 'default')]`
+
+Za podrobnosti glejte [Kako uporabljati Requires atribut |best-practices:attribute-requires].
+
+
+Preverjanje metode HTTP .[#toc-http-method-check]
+-------------------------------------------------
+
+V omrežju Nette predstavniki samodejno preverijo metodo HTTP vsake prejete zahteve predvsem iz varnostnih razlogov. Privzeto so dovoljene metode `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Če želite omogočiti dodatne metode, kot je `OPTIONS`, lahko uporabite `#[Requires]` atribut (od različice Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+V različici 3.1 se preverjanje izvaja v `checkHttpMethod()`, ki preveri, ali je metoda, navedena v zahtevi, vključena v polje `$presenter->allowedMethods`. Dodajte metodo, kot je ta:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Ključnega pomena je poudariti, da če omogočite metodo `OPTIONS`, jo morate ustrezno obdelati tudi v svojem predstavitvenem programu. Ta metoda se pogosto uporablja kot tako imenovana zahteva preflight, ki jo brskalniki samodejno pošljejo pred dejansko zahtevo, ko je treba ugotoviti, ali je zahteva dovoljena z vidika politike CORS (Cross-Origin Resource Sharing). Če to metodo dovolite, vendar ne izvedete ustreznega odziva, lahko pride do nedoslednosti in morebitnih varnostnih težav.
+
+
 Nadaljnje branje .[#toc-further-reading]
 ========================================
 
diff --git a/application/sl/routing.texy b/application/sl/routing.texy
index 0f717178bb..bea1f8c1b6 100644
--- a/application/sl/routing.texy
+++ b/application/sl/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Napredni zapis .[#toc-advanced-notation]
 ----------------------------------------
 
-Drugi parameter poti, ki ga pogosto zapišemo v obliki `Presenter:action`, je okrajšava, ki jo lahko zapišemo tudi v obliki polja, kjer neposredno navedemo (privzete) vrednosti posameznih parametrov:
+Cilj poti, ki je običajno zapisan v obliki `Presenter:action`, je mogoče izraziti tudi s poljem, ki določa posamezne parametre in njihove privzete vrednosti:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Lahko pa uporabimo tudi to obliko, pri čemer opazimo prepisovanje regularnega izraza za preverjanje:
+Za podrobnejšo specifikacijo je mogoče uporabiti še bolj razširjeno obliko, v kateri lahko poleg privzetih vrednosti nastavite tudi druge lastnosti parametrov, na primer regularni izraz za preverjanje (glejte parameter `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Te bolj zgovorne oblike so uporabne za dodajanje drugih metapodatkov.
+Pomembno je opozoriti, da če parametri, opredeljeni v polju, niso vključeni v masko poti, njihovih vrednosti ni mogoče spremeniti, niti z uporabo parametrov poizvedbe, določenih za vprašalnim znakom v naslovu URL.
 
 
 Filtri in prevodi .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Integracija .[#toc-integration]
 ===============================
 
-Da bi naš usmerjevalnik povezali z aplikacijo, moramo o tem obvestiti vsebnik DI. Najlažje je pripraviti tovarno, ki bo zgradila objekt usmerjevalnika, in povedati konfiguraciji vsebnika, naj jo uporabi. Recimo, da v ta namen napišemo metodo `App\Router\RouterFactory::createRouter()`:
+Da bi naš usmerjevalnik povezali z aplikacijo, moramo o tem obvestiti vsebnik DI. Najlažje je pripraviti tovarno, ki bo zgradila objekt usmerjevalnika, in povedati konfiguraciji vsebnika, naj jo uporabi. Recimo, da v ta namen napišemo metodo `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Nato zapišemo v [konfiguracijo |dependency-injection:services]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Vse odvisnosti, kot je povezava s podatkovno bazo itd., se metodi tovarne posredujejo kot njeni parametri z uporabo [samodejnega povezovanja |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ Z ločeno uporabo mislimo na uporabo zmožnosti usmerjevalnika v aplikaciji, ki
 Tako bomo ponovno ustvarili metodo, ki bo zgradila usmerjevalnik, na primer:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Ali pa bomo predmete ustvarili neposredno:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/sl/templates.texy b/application/sl/templates.texy
index 66005783a9..06c0ddeb10 100644
--- a/application/sl/templates.texy
+++ b/application/sl/templates.texy
@@ -34,35 +34,81 @@ To pa je lahko predloga za dejanja:
 V njej je opredeljen blok `content`, ki se v postavitev vstavi namesto bloka `{include content}`, prav tako pa je na novo opredeljen blok `title`, ki v postavitvi prepiše blok `{block title}`. Poskusite si predstavljati rezultat.
 
 
-Iskanje predlog .[#toc-search-for-templates]
---------------------------------------------
+Iskanje predloge .[#toc-template-lookup]
+----------------------------------------
 
-Pot do predlog se določi po preprosti logiki. Poskusi preveriti, ali obstaja ena od teh datotek s predlogami glede na imenik, v katerem se nahaja razred presenter, kjer `<Presenter>` je ime trenutnega predstavnika in `<view>` je ime trenutnega dejanja:
+V predstavitvenih programih vam ni treba določiti, katera predloga naj se prikaže; ogrodje samodejno določi pot, kar vam olajša kodiranje.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Če uporabljate imeniško strukturo, v kateri ima vsak predstavnik svoj imenik, preprosto postavite predlogo v ta imenik pod ime dejanja (npr. pogleda). Na primer, za dejanje `default` uporabite predlogo `default.latte`:
 
-Če predloge ne najde, jo poskuša poiskati v imeniku `templates` eno raven višje, tj. na isti ravni kot imenik z razredom predstavnika.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Če predloge ne najde niti tam, se kot odgovor prikaže [napaka 404 |presenters#Error 404 etc.].
+Če uporabljate strukturo, v kateri so predstavniki skupaj v enem imeniku, predloge pa v mapi `templates`, jo shranite bodisi v datoteko `<Presenter>.<view>.latte` ali . `<Presenter>/<view>.latte`:
 
-Pogled lahko spremenite tudi z uporabo `$this->setView('otherView')`. Lahko pa namesto iskanja neposredno določite ime datoteke s predlogo z uporabo `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+Imenik `templates` lahko postavite tudi eno raven višje, na isto raven kot imenik z razredi predavateljev.
+
+Če predloge ni mogoče najti, se predstavitveni program odzove z [napako 404 - stran ni najdena |presenters#Error 404 etc].
+
+Prikaz lahko spremenite z uporabo spletne strani `$this->setView('anotherView')`. Datoteko s predlogo lahko določite tudi neposredno z uporabo `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Poti, po katerih se iščejo predloge, lahko spremenite tako, da nadgradite metodo [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], ki vrne polje možnih poti do datotek.
+Datoteke, v katerih se iščejo predloge, lahko spremenite tako, da nadgradite metodo [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], ki vrne polje možnih imen datotek.
+
+
+Iskanje predlog za postavitev .[#toc-layout-template-lookup]
+------------------------------------------------------------
+
+Nette samodejno poišče tudi datoteko z maketo.
+
+Če uporabljate imeniško strukturo, v kateri ima vsak predavatelj svoj imenik, postavite postavitev bodisi v mapo s predavateljem, če je namenjena samo njemu, bodisi za stopnjo višje, če je skupna več predavateljem:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Če uporabljate strukturo, v kateri so predstavniki združeni v enem imeniku, predloge pa so v mapi `templates`, bo postavitev pričakovana na naslednjih mestih:
 
-Postavitev se pričakuje v naslednjih datotekah:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` postavitev, ki je skupna več predstavnikom
+Če je predstavnik v [modulu |modules], se bo poiskal tudi naprej po drevesu imenika v skladu z gnezdenjem modula.
 
-`<Presenter>` je ime trenutnega predavatelja in `<layout>` je ime postavitve, ki je privzeto `'layout'`. Ime lahko spremenite s `$this->setLayout('otherLayout')`, tako da se bodo poskušale uporabiti datoteke `@otherLayout.latte`.
+Ime postavitve lahko spremenite z uporabo spletne strani `$this->setLayout('layoutAdmin')`, nato pa jo boste pričakali v datoteki `@layoutAdmin.latte`. Datoteko s predlogo postavitve lahko določite tudi neposredno z uporabo `$this->setLayout('/path/to/template.latte')`.
 
-Ime datoteke za predlogo postavitve lahko določite tudi neposredno z uporabo `$this->setLayout('/path/to/template.latte')`. Z uporabo spletne strani `$this->setLayout(false)` bo iskanje postavitve onemogočeno.
+Uporaba `$this->setLayout(false)` ali oznake `{layout none}` znotraj predloge onemogoči iskanje postavitve.
 
 .[note]
-Poti, po katerih se iščejo predloge, lahko spremenite tako, da nadgradite metodo [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], ki vrne polje možnih poti do datotek.
+Datoteke, v katerih se iščejo predloge postavitve, lahko spremenite tako, da nadgradite metodo [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], ki vrne polje možnih imen datotek.
 
 
 Spremenljivke v predlogi .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ Opomba `@property-read` je namenjena IDE in statični analizi, zaradi nje bo del
 Privoščite si lahko tudi razkošje šepetanja v predlogah, samo namestite vtičnik Latte v PhpStorm in na začetku predloge navedite ime razreda, glejte članek "Latte: kako vtipkati sistem":https://blog.nette.org/sl/latte-kako-uporabljati-sistem-tipov:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Različica Latte 3 ponuja naprednejši način z ustvarjanjem [razširitve |latte:creating-extension] za vsak spletni projekt. Tukaj je približni primer takega razreda:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ Registriramo ga z uporabo [konfiguracije|configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Prevajalnik lahko nastavimo tudi s [konfiguracijo |configuration#Latte]:
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Prevajalnik lahko nato uporabimo na primer kot filter `|translate`, pri čemer metodi `translate()` posredujemo dodatne parametre (glej `foo, bar`):
diff --git a/application/tr/@home.texy b/application/tr/@home.texy
index bb31500e7c..89c807617b 100644
--- a/application/tr/@home.texy
+++ b/application/tr/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | sürüm | PHP ile uyumlu
 |-----------|-------------------
-| Nette Uygulama 4.0 | PHP 8.0 - 8.2
-| Nette Uygulama 3.1 | PHP 7.2 - 8.2
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Uygulama 3.0 | PHP 7.1 - 8.0
 | Nette Uygulama 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/tr/ajax.texy b/application/tr/ajax.texy
index 2502de3b69..007283e44d 100644
--- a/application/tr/ajax.texy
+++ b/application/tr/ajax.texy
@@ -3,10 +3,10 @@ AJAX ve Snippet'ler
 
 <div class=perex>
 
-Günümüzde modern web uygulamalarının yarısı sunucuda, yarısı da tarayıcıda çalışmaktadır. AJAX hayati bir birleştirici faktördür. Nette Framework ne gibi destekler sunuyor?
-- Şablon parçaları gönderme (*snippet* olarak adlandırılır)
+İşlevselliğin genellikle sunucu ve tarayıcı arasında yayıldığı modern web uygulamaları çağında, AJAX önemli bir bağlantı unsurudur. Nette Framework bu alanda hangi seçenekleri sunuyor?
+- Şablonun snippet olarak adlandırılan parçalarını gönderme
 - PHP ve JavaScript arasında değişken aktarımı
-- AJAX uygulamaları hata ayıklama
+- AJAX isteklerinde hata ayıklama araçları
 
 </div>
 
@@ -14,29 +14,32 @@ Günümüzde modern web uygulamalarının yarısı sunucuda, yarısı da tarayı
 AJAX İsteği .[#toc-ajax-request]
 ================================
 
-Bir AJAX isteği klasik bir istekten farklı değildir - sunum yapan kişi belirli bir görünüm ve parametrelerle çağrılır. Buna nasıl yanıt verileceği de sunucuya bağlıdır: bir HTML kod parçası (HTML snippet), bir XML belgesi, bir JSON nesnesi veya JavaScript kodu döndüren kendi rutinini kullanabilir.
+Bir AJAX isteği temelde klasik bir HTTP isteğinden farklı değildir. Bir sunucu belirli parametrelerle çağrılır. İsteğe nasıl yanıt verileceği sunucuya bağlıdır - JSON biçiminde veri döndürebilir, HTML kodunun bir bölümünü, bir XML belgesini vb. gönderebilir.
 
-Sunucu tarafında, bir AJAX isteği `$httpRequest->isAjax()` [HTTP isteğini kapsülleyen |http:request] hizmet yöntemi kullanılarak algılanabilir ( `X-Requested-With` HTTP başlığına dayalı olarak algılar). Sunucunun içinde, `$this->isAjax()` yöntemi şeklinde bir kısayol mevcuttur.
+Tarayıcı tarafında, `fetch()` işlevini kullanarak bir AJAX isteği başlatıyoruz:
 
-JSON'da tarayıcıya veri göndermeye adanmış `payload` adında önceden işlenmiş bir nesne vardır.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Success';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// yanıtın işlenmesi
+});
 ```
 
-JSON çıktınız üzerinde tam kontrol sahibi olmak için sunumunuzda `sendJson` yöntemini kullanın. Sunucuyu hemen sonlandırır ve şablon olmadan yaparsınız:
+Sunucu tarafında, bir AJAX isteği, [HTTP isteğini kapsülleyen |http:request] hizmetin `$httpRequest->isAjax()` yöntemi tarafından tanınır. Bu yöntem `X-Requested-With` HTTP başlığını kullanır, bu yüzden bunu göndermek çok önemlidir. Sunucu içinde `$this->isAjax()` yöntemini kullanabilirsiniz.
+
+Verileri JSON biçiminde göndermek istiyorsanız [`sendJson()` |presenters#Sending a response] yöntemi. Yöntem ayrıca sunum yapan kişinin etkinliğini de sonlandırır.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-HTML göndermek istiyorsak, AJAX istekleri için özel bir şablon ayarlayabiliriz:
+AJAX için tasarlanmış özel bir şablonla yanıt vermeyi planlıyorsanız, bunu aşağıdaki şekilde yapabilirsiniz:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
+Parçacıklar .[#toc-snippets]
+============================
+
+Sunucuyu istemciye bağlamak için Nette tarafından sunulan en güçlü araç snippet'lerdir. Bunlarla, sıradan bir uygulamayı minimum çaba ve birkaç satır kodla bir AJAX uygulamasına dönüştürebilirsiniz. Fifteen örneği tüm bunların nasıl çalıştığını göstermektedir ve kodu [GitHub |https://github.com/nette-examples/fifteen]'da bulunabilir.
+
+Parçacıklar veya kırpmalar, tüm sayfayı yeniden yüklemek yerine sayfanın yalnızca bazı bölümlerini güncellemenize olanak tanır. Bu daha hızlı ve daha verimlidir ve ayrıca daha rahat bir kullanıcı deneyimi sağlar. Snippet'ler size Ruby on Rails için Hotwire veya Symfony UX Turbo'yu hatırlatabilir. İlginç bir şekilde, Nette snippet'leri 14 yıl önce tanıtmıştı.
+
+Parçacıklar nasıl çalışır? Sayfa ilk yüklendiğinde (AJAX olmayan bir istek), tüm snippet'ler dahil olmak üzere sayfanın tamamı yüklenir. Kullanıcı sayfayla etkileşime girdiğinde (örneğin, bir düğmeye tıkladığında, bir form gönderdiğinde vb.), sayfanın tamamını yüklemek yerine bir AJAX isteği yapılır. Sunucudaki kod eylemi gerçekleştirir ve hangi parçacıkların güncellenmesi gerektiğine karar verir. Nette bu parçacıkları işler ve bir JSON dizisi şeklinde gönderir. Tarayıcıdaki işleme kodu daha sonra alınan parçacıkları sayfaya geri ekler. Bu nedenle, yalnızca değiştirilen parçacıkların kodu aktarılır, bant genişliğinden tasarruf edilir ve tüm sayfa içeriğinin aktarılmasına kıyasla yükleme hızlandırılır.
+
+
 Naja .[#toc-naja]
-=================
+-----------------
 
-[Naja kütüphanesi |https://naja.js.org], tarayıcı tarafında AJAX isteklerini işlemek için kullanılır. Bir node.js paketi olarak [yükleyin |https://naja.js.org/#/guide/01-install-setup-naja] (Webpack, Rollup, Vite, Parcel ve daha fazlası ile kullanmak için):
+Tarayıcı tarafında snippet'leri işlemek için [Naja kütüphanesi |https://naja.js.org] kullanılır. [Bunu |https://naja.js.org/#/guide/01-install-setup-naja] bir node.js paketi olarak [yükleyin |https://naja.js.org/#/guide/01-install-setup-naja] (Webpack, Rollup, Vite, Parcel ve diğerleri gibi uygulamalarla kullanmak için):
 
 ```shell
 npm install naja
 ```
 
-...veya doğrudan sayfa şablonuna ekleyin:
+... veya doğrudan sayfa şablonuna ekleyin:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Normal bir bağlantıdan (sinyal) veya form gönderiminden bir AJAX isteği oluşturmak için ilgili bağlantıyı, formu veya düğmeyi `ajax` sınıfıyla işaretlemeniz yeterlidir:
+Öncelikle kütüphaneyi [başlatmanız |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] gerekir:
+
+```js
+naja.initialize();
+```
+
+Sıradan bir bağlantıyı (sinyal) veya form gönderimini AJAX isteği haline getirmek için ilgili bağlantıyı, formu veya düğmeyi `ajax` sınıfıyla işaretlemeniz yeterlidir:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ Normal bir bağlantıdan (sinyal) veya form gönderiminden bir AJAX isteği olu
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Parçacıklar .[#toc-snippets]
-============================
-
-Yerleşik AJAX desteğinin çok daha güçlü bir aracı vardır - snippet'ler. Bunları kullanmak, normal bir uygulamayı yalnızca birkaç satır kod kullanarak bir AJAX uygulamasına dönüştürmeyi mümkün kılar. Tüm bunların nasıl çalıştığı, koduna derlemede veya [GitHub'da |https://github.com/nette-examples/fifteen] da erişilebilen Fifteen örneğinde gösterilmiştir.
-
-Snippet'lerin çalışma şekli, ilk (yani AJAX olmayan) istek sırasında tüm sayfanın aktarılması ve ardından her AJAX [alt |components#signal] isteğinde (aynı sunucunun aynı görünümünün isteği) yalnızca değiştirilen parçaların kodunun daha önce bahsedilen `payload` deposuna aktarılmasıdır.
+Parçacıkları Yeniden Çizme .[#toc-redrawing-snippets]
+-----------------------------------------------------
 
-Snippet'ler size Ruby on Rails için Hotwire veya Symfony UX Turbo'yu hatırlatabilir, ancak Nette bunları on dört yıl önce buldu.
-
-
-Snippet'lerin Geçersiz Kılınması .[#toc-invalidation-of-snippets]
-=================================================================
-
-[Control |components] sınıfının her bir torunu (ki bir Presenter da öyledir), bir istek sırasında yeniden oluşturmasını gerektiren herhangi bir değişiklik olup olmadığını hatırlayabilir. Bunu işlemek için bir çift yöntem vardır: `redrawControl()` ve `isControlInvalid()`. Bir örnek:
+ [Control |components] sınıfının her nesnesi (Presenter'ın kendisi de dahil olmak üzere) yeniden çizilmesini gerektirecek değişikliklerin olup olmadığının kaydını tutar. Bu amaç için `redrawControl()` yöntemi kullanılır.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Nesne, kullanıcı giriş yaptıktan sonra yeniden oluşturulmalıdır
+	// giriş yaptıktan sonra ilgili kısmı yeniden çizmek gerekir
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Ancak Nette, tüm bileşenlerden daha da ince bir çözünürlük sunar. Listelenen yöntemler, isteğe bağlı bir parametre olarak "snippet" olarak adlandırılan bir ismi kabul eder. Bir "snippet" temel olarak şablonunuzdaki bir Latte makrosu tarafından bu amaç için işaretlenmiş bir öğedir, daha sonra bu konuda daha fazla bilgi verilecektir. Böylece bir bileşenden şablonunun sadece *parçalarını* yeniden çizmesini istemek mümkündür. Bileşenin tamamı geçersiz kılınırsa, tüm parçacıkları yeniden oluşturulur. Bir bileşen, alt bileşenlerinden herhangi birinin geçersiz olması durumunda da "geçersiz" olur.
-
-```php
-$this->isControlInvalid(); // -> false
 
-$this->redrawControl('header'); // 'header' adlı parçacığı geçersiz kılar
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, en az bir snippet geçersiz
+Nette ayrıca nelerin yeniden çizilmesi gerektiğinin daha iyi kontrol edilmesini sağlar. Yukarıda bahsedilen yöntem, snippet adını bir argüman olarak alabilir. Böylece, şablon parçası düzeyinde geçersiz kılmak (yani yeniden çizmeye zorlamak) mümkündür. Bileşenin tamamı geçersiz kılınırsa, her parçacığı da yeniden çizilir:
 
-$this->redrawControl(); // tüm bileşeni, her parçacığı geçersiz kılar
-$this->isControlInvalid('footer'); // -> true
+```php
+// 'header' parçacığını geçersiz kılar
+$this->redrawControl('header');
 ```
 
-Sinyal alan bir bileşen otomatik olarak yeniden çizilmek üzere işaretlenir.
-
-Snippet yeniden çizimi sayesinde hangi öğelerin hangi kısımlarının yeniden işlenmesi gerektiğini tam olarak biliyoruz.
-
-
-Etiket `{snippet} … {/snippet}` .{toc: Tag snippet}
-===================================================
 
-Sayfanın oluşturulması normal bir istekle çok benzer şekilde ilerler: aynı şablonlar yüklenir, vb. Ancak önemli olan, çıktıya ulaşmaması gereken kısımların dışarıda bırakılmasıdır; diğer kısımlar bir tanımlayıcı ile ilişkilendirilmeli ve bir JavaScript işleyicisi için anlaşılabilir bir biçimde kullanıcıya gönderilmelidir.
+Latte'de Parçacıklar .[#toc-snippets-in-latte]
+----------------------------------------------
 
-
-Sözdizimi .[#toc-syntax]
-------------------------
-
-Şablonda bir kontrol veya snippet varsa, bunu `{snippet} ... {/snippet}` pair etiketini kullanarak sarmalıyız - bu, işlenen snippet'in "kesilip çıkarılmasını" ve tarayıcıya gönderilmesini sağlayacaktır. Ayrıca onu bir yardımcı içine alacaktır `<div>` etiketi (farklı bir etiket kullanmak mümkündür). Aşağıdaki örnekte `header` adında bir snippet tanımlanmıştır. Bir bileşenin şablonunu da temsil edebilir:
+Latte'de snippet'leri kullanmak son derece kolaydır. Şablonun bir bölümünü snippet olarak tanımlamak için, onu `{snippet}` ve `{/snippet}` etiketlerine sarmanız yeterlidir:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ Sözdizimi .[#toc-syntax]
 {/snippet}
 ```
 
-dışındaki bir türden bir snippet `<div>` veya ek HTML öznitelikleri içeren bir snippet, öznitelik varyantı kullanılarak elde edilir:
+Kod parçacığı bir öğe oluşturur `<div>` HTML sayfasında özel olarak oluşturulmuş bir `id`. Bir snippet yeniden çizilirken, bu öğenin içeriği güncellenir. Bu nedenle, sayfa ilk kez render edildiğinde, başlangıçta boş olsalar bile tüm snippet'ler de render edilmelidir.
+
+dışında bir öğe ile de bir snippet oluşturabilirsiniz `<div>` bir n:özniteliği kullanarak:
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ dışındaki bir türden bir snippet `<div>` veya ek HTML öznitelikleri içeren
 ```
 
 
-Dinamik Parçacıklar .[#toc-dynamic-snippets]
-============================================
+Snippet Alanları .[#toc-snippet-areas]
+--------------------------------------
 
-Nette'de ayrıca bir çalışma zamanı parametresine dayalı olarak dinamik bir adla snippet'ler tanımlayabilirsiniz. Bu, sadece bir satırı değiştirmemiz gereken ancak tüm listeyi onunla birlikte aktarmak istemediğimiz çeşitli listeler için en uygun olanıdır. Bunun bir örneği şöyle olabilir:
+Snippet adları ifadeler de olabilir:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Birkaç dinamik snippet içeren `itemsContainer` adında bir statik snippet vardır: `item-0`, `item-1` ve benzeri.
+Bu şekilde, `item-0`, `item-1`, vb. gibi birkaç snippet elde edeceğiz. Dinamik bir snippet'i (örneğin, `item-1`) doğrudan geçersiz kılacak olursak, hiçbir şey yeniden çizilmeyecektir. Bunun nedeni, snippet'lerin gerçek alıntılar olarak işlev görmesi ve yalnızca kendilerinin doğrudan render edilmesidir. Ancak, şablonda teknik olarak `item-1` adında bir snippet yoktur. Yalnızca snippet'in çevresindeki kod, bu durumda foreach döngüsü çalıştırıldığında ortaya çıkar. Bu nedenle, şablonun çalıştırılması gereken kısmını `{snippetArea}` etiketiyle işaretleyeceğiz:
 
-Dinamik bir snippet'i doğrudan yeniden çizemezsiniz ( `item-1` adresinin yeniden çizilmesinin hiçbir etkisi yoktur), üst snippet'ini yeniden çizmeniz gerekir (bu örnekte `itemsContainer`). Bu, üst snippet'in kodunun yürütülmesine neden olur, ancak daha sonra tarayıcıya yalnızca alt snippet'leri gönderilir. Alt snippet'lerden yalnızca birini göndermek istiyorsanız, diğer alt snippet'leri oluşturmamak için ana snippet'in girdisini değiştirmeniz gerekir.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-Yukarıdaki örnekte, bir AJAX isteği için `$list` dizisine yalnızca bir öğe ekleneceğinden emin olmanız gerekir, bu nedenle `foreach` döngüsü yalnızca bir dinamik parçacık yazdıracaktır.
+Ve hem bireysel parçacığı hem de tüm alanı yeniden çizeceğiz:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * This method returns data for the list.
-	 * Usually this would just request the data from a model.
-	 * For the purpose of this example, the data is hard-coded.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Ayrıca `$items` dizisinin yalnızca yeniden çizilmesi gereken öğeleri içerdiğinden emin olmak da önemlidir.
 
-Dahil Edilen Bir Şablondaki Parçacıklar .[#toc-snippets-in-an-included-template]
-================================================================================
-
-Snippet, farklı bir şablondan dahil edilen bir şablonda olabilir. Bu durumda, ikinci şablondaki dahil etme kodunu `snippetArea` makrosuyla sarmamız gerekir, ardından hem snippetArea'yı hem de gerçek snippet'i yeniden çizeriz.
-
-Makro `snippetArea`, içindeki kodun yürütülmesini sağlar, ancak tarayıcıya yalnızca dahil edilen şablondaki gerçek parçacık gönderilir.
+Parçacıkları olan `{include}` etiketini kullanarak ana şablona başka bir şablon eklerken, dahil edilen şablonu tekrar bir `snippetArea` içine sarmak ve hem parçacığı hem de alanı birlikte geçersiz kılmak gerekir:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* dahil.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Ayrıca dinamik snippet'lerle de birleştirebilirsiniz.
-
-
-Ekleme ve Silme .[#toc-adding-and-deleting]
-===========================================
 
-Listeye yeni bir öğe ekler ve `itemsContainer` adresini geçersiz kılarsanız, AJAX isteği yenisini de içeren parçacıkları döndürür, ancak javascript işleyicisi bunu işleyemez. Bunun nedeni, yeni oluşturulan ID'ye sahip bir HTML öğesi olmamasıdır.
+Bileşenlerdeki Snippet'ler .[#toc-snippets-in-components]
+---------------------------------------------------------
 
-Bu durumda, en basit yol tüm listeyi bir parçacığa daha sarmak ve hepsini geçersiz kılmaktır:
+ [Bileşenler |components] içinde parçacıklar oluşturabilirsiniz ve Nette bunları otomatik olarak yeniden çizer. Bununla birlikte, belirli bir sınırlama vardır: parçacıkları yeniden çizmek için, herhangi bir parametre olmadan `render()` yöntemini çağırır. Bu nedenle, şablonda parametre geçmek işe yaramayacaktır:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Add</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Kullanıcı Verilerinin Gönderilmesi .[#toc-sending-user-data]
+------------------------------------------------------------
+
+Parçacıkların yanı sıra, istemciye herhangi bir ek veri gönderebilirsiniz. Bunları `payload` nesnesine yazmanız yeterlidir:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Aynı şey bir öğeyi silmek için de geçerlidir. Boş snippet göndermek mümkün olabilir, ancak genellikle listeler sayfalandırılabilir ve bir öğeyi silip diğerini (sayfalandırılmış listenin farklı bir sayfasında bulunan) yüklemek karmaşık olacaktır.
-
 
-Bileşene Parametre Gönderme .[#toc-sending-parameters-to-component]
-===================================================================
+Parametreleri Gönderme .[#toc-sending-parameters]
+=================================================
 
 AJAX isteği aracılığıyla bileşene parametreler gönderdiğimizde, ister sinyal parametreleri ister kalıcı parametreler olsun, bileşenin adını da içeren global adlarını sağlamalıyız. Parametrenin tam adı `getParameterId()` yöntemini döndürür.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-Ve bileşende karşılık gelen parametrelerle yöntemi işleyin.
+Bileşende ilgili parametreleri içeren bir tutamaç yöntemi:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/tr/bootstrap.texy b/application/tr/bootstrap.texy
index 403f4ee3f7..1513e7fe3a 100644
--- a/application/tr/bootstrap.texy
+++ b/application/tr/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Yapılandırıcı, uygulama ortamını ve hizmetlerini ayarlamaktan sorumludur.
+		$this->configurator = new Configurator;
+		// Nette tarafından oluşturulan geçici dosyalar için dizini ayarlayın (örn. derlenmiş şablonlar)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette akıllıdır ve geliştirme modu otomatik olarak açılır,
+		// ya da aşağıdaki satırın yorumunu kaldırarak belirli bir IP adresi için etkinleştirebilirsiniz:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Tracy'yi etkinleştirir: nihai "İsviçre çakısı" hata ayıklama aracı.
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: verilen dizindeki tüm sınıfları otomatik yükler
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Yapılandırma dosyalarını yükle
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-Web uygulamaları söz konusu olduğunda, başlangıç dosyası `index.php` olup `www/` genel dizininde bulunur. Ortamı başlatmak için `Bootstrap` sınıfına izin verir ve DI konteynerini oluşturan `$configurator` sınıfını döndürür. Daha sonra web uygulamasını çalıştıran `Application` hizmetini elde eder:
+Web uygulamaları için başlangıç dosyası `index.php`, `www/` genel dizininde bulunur. Ortamı başlatmak ve bir DI konteyneri oluşturmak için `Bootstrap` sınıfını kullanır. Ardından, web uygulamasını başlatan kapsayıcıdan `Application` hizmetini alır:
 
 ```php
-// ortamı başlat + Configurator nesnesini al
-$configurator = App\Bootstrap::boot();
-// bir DI konteyneri oluşturun
-$container = $configurator->createContainer();
-// DI container bir Nette\Application\Application nesnesi oluşturur
+$bootstrap = new App\Bootstrap;
+// Ortamı başlatma + bir DI konteyneri oluşturma
+$container = $bootstrap->bootWebApplication();
+// DI konteyneri bir Nette\Application\Application nesnesi oluşturur
 $application = $container->getByType(Nette\Application\Application::class);
-// Nette uygulamasını başlat
+// Nette uygulamasını başlatın ve gelen isteği işleyin
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Mod seçimi otomatik algılama ile yapılır, bu nedenle genellikle herhangi bir
 Geliştirme modunu diğer durumlarda, örneğin belirli bir IP adresinden erişen programcılar için etkinleştirmek istiyorsanız, `setDebugMode()` adresini kullanabilirsiniz:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // bir veya daha fazla IP adresi
+$this->configurator->setDebugMode('23.75.345.200'); // bir veya daha fazla IP adresi
 ```
 
 Bir IP adresini bir çerezle birleştirmenizi kesinlikle öneririz. `nette-debug` çerezine gizli bir belirteç depolayacağız, örneğin `secret1234` ve geliştirme modu, bu IP ve çerez kombinasyonuna sahip programcılar için etkinleştirilecektir.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Ayrıca localhost için bile geliştirici modunu tamamen kapatabiliriz:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 `true` değerinin, bir üretim sunucusunda asla gerçekleşmemesi gereken geliştirici modunu zorlayarak açtığını unutmayın.
@@ -90,7 +115,7 @@ Hata Ayıklama Aracı Tracy .[#toc-debugging-tool-tracy]
 Kolay hata ayıklama için harika araç [Tracy'yi |tracy:] açacağız. Geliştirici modunda hataları görselleştirir ve üretim modunda hataları belirtilen dizine kaydeder:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ Geçici Dosyalar .[#toc-temporary-files]
 Nette, DI konteyneri, RobotLoader, şablonlar vb. için önbelleği kullanır. Bu nedenle, önbelleğin depolanacağı dizinin yolunu ayarlamak gerekir:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 Linux veya macOS üzerinde, `log/` ve `temp/` dizinleri için [yazma izinlerini |nette:troubleshooting#Setting directory permissions] ayarlayın.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Genellikle, [RobotLoader'ı |robot-loader:] kullanarak sınıfları otomatik olarak yüklemek isteyeceğiz, bu yüzden onu başlatmalı ve `Bootstrap.php` 'un bulunduğu dizinden (yani `__DIR__`) ve tüm alt dizinlerinden sınıfları yüklemesine izin vermeliyiz:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ Zaman Dilimi .[#toc-timezone]
 Yapılandırıcı, uygulamanız için bir saat dilimi belirlemenize olanak tanır.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ Geliştirme modunda, kodu veya yapılandırma dosyalarını her değiştirdiğin
 Yapılandırma dosyaları `addConfig()` kullanılarak yüklenir:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Birden fazla dosya eklemek için `addConfig()` yöntemi birden fazla kez çağrılabilir.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ Statik Parametreler .[#toc-static-parameters]
 Yapılandırma dosyalarında kullanılan parametreler [`parameters` bölümünde |dependency-injection:configuration#parameters] tanımlanabilir ve ayrıca `addStaticParameters()` yöntemi ( `addParameters()` takma adı vardır) tarafından geçirilebilir (veya üzerine yazılabilir). Farklı parametre değerlerinin ek DI konteynerlerinin, yani ek sınıfların oluşturulmasına neden olması önemlidir.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ Dinamik Parametreler .[#toc-dynamic-parameters]
 Konteynere dinamik parametreler de ekleyebiliriz, statik parametrelerin aksine farklı değerleri yeni DI konteynerlerinin oluşturulmasına neden olmaz.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Ortam değişkenleri dinamik parametreler kullanılarak kolayca kullanılabilir hale getirilebilir. Bunlara yapılandırma dosyalarındaki `%env.variable%` adresinden erişebiliriz.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ Yapılandırma dosyalarında aşağıdaki statik parametreleri kullanabilirsiniz
 - `%wwwDir%`, `index.php` giriş dosyasını içeren dizinin mutlak yoludur
 - `%tempDir%` geçici dosyalar için dizinin mutlak yoludur
 - `%vendorDir%` Composer'ın kütüphaneleri yüklediği dizinin mutlak yoludur
+- `%rootDir%` projenin kök dizinine giden mutlak yoldur
 - `%debugMode%` uygulamanın hata ayıklama modunda olup olmadığını gösterir
 - `%consoleMode%` isteğin komut satırı üzerinden gelip gelmediğini gösterir
 
@@ -225,7 +252,7 @@ services:
 Yeni bir örnek oluşturun ve bootstrap'e ekleyin:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Farklı Ortamlar .[#toc-different-environments]
 ==============================================
 
-`Bootstrap` sınıfını ihtiyaçlarınıza göre özelleştirmekten çekinmeyin. Web projelerini farklılaştırmak için `boot()` yöntemine parametreler ekleyebilir veya birim testleri için ortamı başlatan `bootForTests()`, komut satırından çağrılan komut dosyaları için `bootForCli()` gibi başka yöntemler ekleyebilirsiniz.
+ `Bootstrap` sınıfını ihtiyaçlarınıza göre özelleştirmekten çekinmeyin. Web projeleri arasında ayrım yapmak için `bootWebApplication()` yöntemine parametreler ekleyebilirsiniz. Alternatif olarak, birim testleri için ortamı başlatmak üzere `bootTestEnvironment()`, komut satırından çağrılan betikler için `bootConsoleApplication()` gibi başka yöntemler de ekleyebilirsiniz.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Nette Tester başlatma
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Nette Tester initialization
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/tr/components.texy b/application/tr/components.texy
index c0f7bd4c4a..cae382b8da 100644
--- a/application/tr/components.texy
+++ b/application/tr/components.texy
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // ve yeniden yönlendir
 ```
 
 
+Sinyalden Sonra Yeniden Yönlendirme .[#toc-redirection-after-a-signal]
+======================================================================
+
+Bir bileşen sinyali işlendikten sonra genellikle yeniden yönlendirme yapılır. Bu durum formlara benzer - bir form gönderildikten sonra, sayfa tarayıcıda yenilendiğinde verilerin yeniden gönderilmesini önlemek için de yönlendirme yaparız.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Bir bileşen yeniden kullanılabilir bir öğe olduğundan ve genellikle belirli sunuculara doğrudan bağımlı olmaması gerektiğinden, `redirect()` ve `link()` yöntemleri parametreyi otomatik olarak bir bileşen sinyali olarak yorumlar:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Farklı bir sunum yapan kişiye veya eyleme yönlendirmeniz gerekiyorsa, bunu sunum yapan kişi aracılığıyla yapabilirsiniz:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Kalıcı Parametreler .[#toc-persistent-parameters]
 =================================================
 
@@ -347,7 +369,7 @@ services:
 Son olarak, bu fabrikayı sunucumuzda kullanacağız:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ Derinlemesine Bileşenler .[#toc-components-in-depth]
 Bir Nette Uygulamasındaki bileşenler, bu bölümün konusu olan sayfalara gömdüğümüz bir web uygulamasının yeniden kullanılabilir parçalarıdır. Böyle bir bileşenin yetenekleri tam olarak nelerdir?
 
 1) bir şablon içinde oluşturulabilir
-2) [AJAX isteği |ajax#invalidation] sırasında hangi bölümünün işleneceğini bilir (snippet'ler)
+2) AJAX isteği sırasında [hangi bölümünün |ajax#snippets] işleneceğini bilir (snippet'ler)
 3) durumunu bir URL'de saklama yeteneğine sahiptir (kalıcı parametreler)
 4) kullanıcı eylemlerine (sinyallere) yanıt verme yeteneğine sahiptir
 5) hiyerarşik bir yapı oluşturur (kökün sunum yapan kişi olduğu)
diff --git a/application/tr/configuration.texy b/application/tr/configuration.texy
index 8949e7d7e8..62d7a3f3f7 100644
--- a/application/tr/configuration.texy
+++ b/application/tr/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# Tracy BlueScreen'de "Nette Application" panelini gösterir?
 	debugger: ...           # (bool) varsayılan olarak true
 
-	# error-presenter hata durumunda çağrılacak mı?
-	catchExceptions: ...    # (bool) üretim modunda varsayılan olarak true
+	# error-presenter hata üzerine çağrılacak mı?
+	# sadece geliştirici modunda etkilidir
+	catchExceptions: ...    # (bool) varsayılan olarak true
 
 	# hata sunucusunun adı
-	errorPresenter: Error   # (string) varsayılan olarak 'Nette:Error'
+	errorPresenter: Error   # (string|array) varsayılan olarak 'Nette:Error'
+
+	# sunum yapanlar ve etkinlikler için takma adlar tanımlar
+	aliases: ...
 
 	# sunum yapan kişinin adını bir sınıfa çözümlemek için kuralları tanımlar
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) varsayılan değer false
 ```
 
-Hata sunucuları geliştirme modunda varsayılan olarak çağrılmadığından ve hatalar Tracy tarafından görüntülendiğinden, `catchExceptions` değerini `true` olarak değiştirmek, hata sunucularının geliştirme sırasında doğru çalıştığını doğrulamaya yardımcı olur.
+`nette/application` sürüm 3.2'den itibaren bir çift hata sunucusu tanımlamak mümkündür:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # Nette\Application\BadRequestException için
+		5xx: Error5xx   # diğer istisnalar için
+```
 
 `silentLinks` seçeneği, bağlantı oluşturma başarısız olduğunda (örneğin, sunum yapan kişi olmadığından vb.) Nette'in geliştirici modunda nasıl davranacağını belirler. Varsayılan değer olan `false`, Nette'in `E_USER_WARNING` adresini tetikleyeceği anlamına gelir. `true` olarak ayarlanması bu hata mesajını bastırır. Bir üretim ortamında, `E_USER_WARNING` her zaman çağrılır. Bu davranışı, sunum yapan değişken [$invalidLinkMode'u |creating-links#Invalid Links] ayarlayarak da etkileyebiliriz.
 
+[Takma adlar |creating-links#aliases], sık kullanılan sunum yapanlara [atıfta bulunmayı kolaylaştırır |creating-links#aliases].
+
 [Eşleme |modules#mapping], sınıf adının sunum yapan kişinin adından türetildiği [kuralları tanımlar |modules#mapping].
 
 
@@ -82,6 +95,9 @@ latte:
 	# [oluşturulan kodun kontrol |latte:develop#Checking Generated Code]edilmesini sağlar
 	phpLinter: ...       # (string) varsayılan null
 
+	# yerel ayarı ayarlar
+	locale: cs_CZ        # (string) varsayılan null
+
 	# $this->template sınıfı
 	templateClass: App\MyTemplateClass # varsayılan olarak Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ Latte sürüm 3 kullanıyorsanız, kullanarak yeni [uzantı |latte:creating-exte
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/tr/creating-links.texy b/application/tr/creating-links.texy
index 1b8325a446..cbdb8c5b7d 100644
--- a/application/tr/creating-links.texy
+++ b/application/tr/creating-links.texy
@@ -38,7 +38,7 @@ Adlandırılmış parametreleri geçmek de mümkündür. Aşağıdaki bağlantı
 <a n:href="Product:show $product->id, lang: en">detail</a>
 ```
 
-`ProductPresenter::renderShow()` yönteminin imzasında `$lang` yoksa, parametrenin değerini `$lang = $this->getParameter('lang')` kullanarak okuyabilir.
+`ProductPresenter::renderShow()` yönteminin imzasında `$lang` yoksa, parametrenin değerini `$lang = $this->getParameter('lang')` kullanarak veya [özellikten |presenters#Request Parameters] alabilir.
 
 Parametreler bir dizide saklanıyorsa, `...` operatörü (veya Latte 2.x'te `(expand)` operatörü) ile genişletilebilirler:
 
@@ -140,7 +140,7 @@ Hedef `this` geçerli sayfaya bir bağlantı oluşturacaktır:
 <a n:href="this">refresh</a>
 ```
 
-Aynı zamanda, imzasında belirtilen tüm parametreler `render<View>()` veya `action<Action>()` yöntemi aktarılır. Yani `Product:show` ve `id:123` sayfalarındaysak, `this` bağlantısı da bu parametreyi geçirecektir.
+Aynı zamanda, imzasında belirtilen tüm parametreler `action<Action>()` veya `render<View>()` yönteminde, eğer `action<Action>()` tanımlanmamışsa, aktarılır. Yani `Product:show` ve `id:123` sayfalarındaysak, `this` bağlantısı da bu parametreyi geçirecektir.
 
 Elbette parametreleri doğrudan belirtmek de mümkündür:
 
@@ -213,7 +213,7 @@ Bileşendeki Bağlantılar .[#toc-links-in-component]
 Bileşen şablonunda sunum yapanlara bağlantı vermek istiyorsak `{plink}` etiketini kullanırız:
 
 ```latte
-<a href="{plink Home:default}">home</a>
+<a href={plink Home:default}>home</a>
 ```
 
 veya kodda
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Takma Adlar .[#toc-aliases]{data-version:v3.2.2}
+================================================
+
+Bazen bir Presenter:action çiftine kolayca hatırlanabilir bir takma ad atamak yararlı olabilir. Örneğin, `Front:Home:default` ana sayfasını basitçe `home` veya `Admin:Dashboard:default` ana sayfasını `admin` olarak adlandırabilirsiniz.
+
+Takma adlar [yapılandırmada |configuration] `application › aliases` anahtarı altında tanımlanır:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+Bağlantılarda, örneğin at sembolü kullanılarak yazılırlar:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+ `redirect()` ve benzeri gibi bağlantılarla çalışan tüm yöntemlerde desteklenirler.
+
+
 Geçersiz Bağlantılar .[#toc-invalid-links]
 ==========================================
 
diff --git a/application/tr/how-it-works.texy b/application/tr/how-it-works.texy
index c083b0f45c..50e09beecc 100644
--- a/application/tr/how-it-works.texy
+++ b/application/tr/how-it-works.texy
@@ -22,18 +22,18 @@ Dizin yapısı şuna benzer:
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← directory with application
-│   ├── <b>Presenters/</b>           ← presenter classes
-│   │   ├── <b>HomePresenter.php</b> ← Home presenter class
-│   │   └── <b>templates/</b>        ← templates directory
-│   │       ├── <b>@layout.latte</b> ← template of shared layout
-│   │       └── <b>Home/</b>         ← templates for Home presenter
-│   │           └── <b>default.latte</b>  ← template for action `default`
-│   ├── <b>Router/</b>               ← configuration of URL addresses
+│   ├── <b>Core/</b>                 ← temel gerekli sınıflar
+│   │   └── <b>RouterFactory.php</b> ← URL adreslerinin yapılandırılması
+│   ├── <b>UI/</b>                   ← presenters, templates & co.
+│   │   ├── <b>@layout.latte</b>     ← paylaşılan düzen şablonu
+│   │   └── <b>Home/</b>             ← Ana Sayfa sunucu dizini
+│   │       ├── <b>HomePresenter.php</b> ← Ev sunucusu sınıfı
+│   │       └── <b>default.latte</b> ← eylem için şablon default
 │   └── <b>Bootstrap.php</b>         ← booting class Bootstrap
 ├── <b>bin/</b>                      ← scripts for the command line
 ├── <b>config/</b>                   ← configuration files
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← error logs
 ├── <b>temp/</b>                     ← temporary files, cache, …
 ├── <b>vendor/</b>                   ← libraries installed by Composer
@@ -91,7 +91,7 @@ Nette'de yazılan uygulamalar, belirli bir web sitesi sayfasını temsil eden s
 
 Uygulama, yönlendirici olarak adlandırılan kişiden mevcut talebin işlenmek üzere hangi sunuculara iletileceğine karar vermesini isteyerek başlar. Yönlendirici bunun kimin sorumluluğunda olduğuna karar verir. `https://example.com/product/123` ile bir ürünü `id: 123` eylem olarak isteyen **sunucu** `Product` için bir iş olduğuna karar verir. Sunucu + eylem çiftlerini iki nokta üst üste ile ayırarak `Product:show` şeklinde yazmak iyi bir alışkanlıktır.
 
-Böylece yönlendirici URL'yi bir `Presenter:action` + parametreler çiftine dönüştürdü, bizim durumumuzda `Product:show` + `id: 123`. Bir yönlendiricinin nasıl göründüğünü `app/Router/RouterFactory.php` dosyasında görebilirsiniz ve bunu [Yönlendirme |Routing] bölümünde ayrıntılı olarak açıklayacağız.
+Böylece yönlendirici URL'yi bir `Presenter:action` + parametreler çiftine dönüştürdü, bizim durumumuzda `Product:show` + `id: 123`. Bir yönlendiricinin nasıl göründüğünü `app/Core/RouterFactory.php` dosyasında görebilirsiniz ve bunu [Yönlendirme |Routing] bölümünde ayrıntılı olarak açıklayacağız.
 
 Devam edelim. Uygulama zaten sunucunun adını biliyor ve devam edebilir. Sunum yapan kişinin kodu olan `ProductPresenter` nesnesini oluşturarak `Product`. Daha doğrusu, DI konteynerinden sunucuyu yaratmasını ister, çünkü nesneleri üretmek onun işidir.
 
@@ -121,12 +121,9 @@ Böylece, kodu kurgusal bir örnek olan `renderShow(123)` yöntemi çağrıldı,
 
 Daha sonra, sunum yapan kişi yanıtı döndürür. Bu bir HTML sayfası, bir resim, bir XML belgesi, diskten bir dosya gönderme, JSON veya başka bir sayfaya yönlendirme olabilir. Daha da önemlisi, nasıl yanıt verileceğini açıkça belirtmezsek ( `ProductPresenter` adresinde olduğu gibi), yanıt şablonu bir HTML sayfası ile işlemek olacaktır. Neden mi? Çünkü vakaların %99'unda bir şablon çizmek isteriz, dolayısıyla sunum yapan kişi bu davranışı varsayılan olarak kabul eder ve işimizi kolaylaştırmak ister. Nette'in amacı da bu.
 
-Hangi şablonun çizileceğini belirtmemize bile gerek yok, basit bir mantıkla o şablona giden yolu türetiyor. Sunucu `Product` ve eylem `show` durumunda, bu şablon dosyalarından birinin `ProductPresenter` sınıfının bulunduğu dizine göre var olup olmadığını görmeye çalışır:
+Hangi şablonun işleneceğini belirtmemize bile gerek yoktur; framework yolu kendisi çıkaracaktır. `show` eylemi söz konusu olduğunda, basitçe `ProductPresenter` sınıfının bulunduğu dizindeki `show.latte` şablonunu yüklemeye çalışır. Ayrıca `@layout.latte` dosyasındaki düzeni bulmaya çalışır ( [şablon arama |templates#Template Lookup] hakkında daha fazla bilgi).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-Ayrıca `@layout.latte` dosyasında düzeni bulmaya çalışacak ve ardından şablonu oluşturacaktır. Artık sunucunun ve tüm uygulamanın görevi tamamlanmıştır. Şablon mevcut değilse, 404 hatalı bir sayfa döndürülecektir. Sunumcular hakkında daha fazla bilgiyi [Sunumcular |Presenters] sayfasında bulabilirsiniz.
+Daha sonra şablonlar işlenir. Bu, sunucunun ve tüm uygulamanın görevini tamamlar ve iş biter. Eğer şablon mevcut değilse, 404 hata sayfası döndürülür. Sunucular hakkında daha fazla bilgi için [Sunucular |presenters] sayfasına bakabilirsiniz.
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ Sadece emin olmak için, tüm süreci biraz farklı bir URL ile özetlemeye çal
 3) yönlendirici URL'yi bir çift olarak çözer `Home:default`
 4) bir `HomePresenter` nesnesi oluşturulur
 5) `renderDefault()` yöntemi çağrılır (eğer varsa)
-6) `templates/@layout.latte` düzenine sahip bir `templates/Home/default.latte` şablonu oluşturulur
+6) `@layout.latte` düzenine sahip bir `default.latte` şablonu oluşturulur
 
 
 Şu anda birçok yeni kavramla karşılaşmış olabilirsiniz, ancak bunların anlamlı olduğuna inanıyoruz. Nette'de uygulama oluşturmak çocuk oyuncağı.
diff --git a/application/tr/modules.texy b/application/tr/modules.texy
index e447d581bd..2fb05dde40 100644
--- a/application/tr/modules.texy
+++ b/application/tr/modules.texy
@@ -2,29 +2,31 @@ Modüller
 ********
 
 .[perex]
-Nette'de modüller bir uygulamayı oluşturan mantıksal birimleri temsil eder. Sunucuları, şablonları, muhtemelen bileşenleri ve model sınıflarını içerirler.
+Modüller, mantıksal birimlere kolayca bölünmeyi kolaylaştırarak Nette uygulamalarına netlik kazandırır.
 
-Sunucular için bir dizin ve şablonlar için bir dizin gerçek projeler için yeterli olmayacaktır. Bir klasörde düzinelerce dosya olması en azından düzensizdir. Bundan nasıl kurtulabiliriz? Basitçe onları diskteki alt dizinlere ve koddaki ad alanlarına böleriz. Nette modüllerinin yaptığı da tam olarak budur.
-
-Sunucular ve şablonlar için tek bir klasör oluşturmayı unutalım ve bunun yerine örneğin `Admin` ve `Front` gibi modüller oluşturalım.
+Dosyaları sabit diskte klasörler halinde düzenlemeye benzer şekilde, Nette'de sunum yapan kişileri, şablonları ve diğer yardımcı sınıfları modüllere bölebiliriz. Bu pratikte nasıl çalışır? Basitçe yapıya yeni alt dizinler ekleyerek. İşte Front ve Admin olmak üzere iki modüllü bir yapı örneği:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Admin/</b>            ← module Admin
-│   │   ├── <b>Presenters/</b>   ← its presenters
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← module Front
-│       └── <b>Presenters/</b>   ← its presenters
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Bu dizin yapısı sınıf ad alanları tarafından yansıtılacaktır, bu nedenle örneğin `DashboardPresenter` `App\Modules\Admin\Presenters` ad alanında olacaktır:
+Bu dizin yapısı sınıfların isim alanlarına da yansıtılır; örneğin `DashboardPresenter`, `App\UI\Admin\Dashboard` isim alanında yer alır:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-`Admin` modülü içindeki `Dashboard` sunumcusuna uygulama içinde iki nokta üst üste gösterimi kullanılarak `Admin:Dashboard` şeklinde ve `default` eylemine `Admin:Dashboard:default` şeklinde referans verilir.
-Peki Nette proper `Admin:Dashboard` 'un `App\Modules\Admin\Presenters\DashboardPresenter` sınıfını temsil ettiğini nasıl biliyor? Bu, yapılandırmadaki [eşleme |#mapping] ile belirlenir.
-Bu nedenle, verilen yapı sabit değildir ve ihtiyaçlarınıza göre değiştirebilirsiniz.
+Uygulamada, `Admin` modülü içindeki `Dashboard` sunumcusuna iki nokta üst üste gösterimini kullanarak `Admin:Dashboard` olarak atıfta bulunuyoruz. `default` eylemi için `Admin:Dashboard:default` olarak adlandırıyoruz.
+
+Sunulan yapı katı değildir; yapılandırmada [ihtiyaçlarınıza göre tamamen özelleştirebilirsiniz |#mapping]. .[tip]
 
-Modüller elbette sunum yapanların ve şablonların yanı sıra bileşenler, model sınıfları vb. gibi diğer tüm öğeleri de içerebilir.
+Modüller, sunucular ve şablonların yanı sıra bileşenler ve yardımcı sınıflar gibi diğer tüm dosyaları da içerebilir. Bunları nereye yerleştireceğinizi düşünüyorsanız, bir `Accessory` klasörü kullanmayı düşünün:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 İç İçe Modüller .[#toc-nested-modules]
 --------------------------------------
 
-Modüller sadece düz bir yapı oluşturmak zorunda değildir, örneğin alt modüller de oluşturabilirsiniz:
+Modüller, diskteki bir dizin yapısına benzer şekilde birden fazla iç içe geçme seviyesine sahip olabilir:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← directory with modules
-│   ├── <b>Blog/</b>             ← module Blog
-│   │   ├── <b>Admin/</b>        ← submodule Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← submodule Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← module Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Böylece, `Blog` modülü `Admin` ve `Front` alt modüllerine bölünmüştür. Yine, bu durum `App\Modules\Blog\Admin\Presenters` vb. isim alanlarına da yansıyacaktır. Alt modülün içindeki `Dashboard` sunucusu `Blog:Admin:Dashboard` olarak adlandırılır.
+ `Blog` modülü `Admin` ve `Front` alt modüllerine ayrılmıştır. Bu aynı zamanda `App\UI\Blog\Admin` ve benzer şekilde görünen isim alanlarına da yansıtılır. `Admin` alt modülü içindeki `Dashboard` sunucusuna atıfta bulunmak için, bunu `Blog:Admin:Dashboard` olarak adlandırıyoruz.
+
+Yerleştirme, alt alt modüllerin oluşturulmasına izin vererek gerektiği kadar derin olabilir.
 
-İç içe geçme istediğiniz kadar derin olabilir, böylece alt alt modüller oluşturulabilir.
+Örneğin, yönetimde `OrderDetail`, `OrderEdit`, `OrderDispatch`, vb. gibi sipariş yönetimiyle ilgili birçok sunucunuz varsa, `Detail`, `Edit`, `Dispatch` ve diğerleri gibi sunucuların düzenleneceği bir `Order` modülü oluşturabilirsiniz.
 
 
 Bağlantı Oluşturma .[#toc-creating-links]
@@ -102,47 +118,66 @@ Yönlendirme .[#toc-routing]
 Haritalama .[#toc-mapping]
 --------------------------
 
-Sınıf adının sunum yapan kişinin adından türetildiği kuralları tanımlar. Bunları [yapılandırmada |configuration] `application › mapping` anahtarının altına yazıyoruz.
+Eşleme, sınıf adının sunum yapan kişinin adından türetilmesine ilişkin kuralları tanımlar. Bu kurallar [yapılandırmada |configuration] `application › mapping` anahtarı altında belirtilir.
 
-Modül kullanmayan bir örnekle başlayalım. Sadece sunum yapan sınıfların `App\Presenters` ad alanına sahip olmasını isteyeceğiz. Bu, `Home` gibi bir sunucunun `App\Presenters\HomePresenter` sınıfıyla eşleşmesi gerektiği anlamına gelir. Bu, aşağıdaki yapılandırma ile gerçekleştirilebilir:
+Bu sayfada daha önce bahsedilen dizin yapıları aşağıdaki eşleştirmeye dayanmaktadır:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Sunum yapan kişinin adı sınıf maskesindeki yıldız işaretiyle değiştirilir ve sonuç sınıf adı olur. Kolay!
+Eşleme nasıl çalışır? Daha iyi anlamak için öncelikle modülsüz bir uygulama hayal edelim. Sunucu sınıflarının `App\UI` ad alanı altında olmasını istiyoruz, böylece `Home` sunucusu `App\UI\HomePresenter` sınıfıyla eşleşir. Bu, şu yapılandırma ile gerçekleştirilebilir:
 
-Sunum yapanları modüllere ayırırsak, her modül için kendi eşlememizi yapabiliriz:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Bu eşleme, `App\UI\*Presenter` maskesindeki yıldız işaretini `Home` sunum yapan kişi adıyla değiştirerek çalışır ve sonuçta `App\UI\HomePresenter` nihai sınıf adı elde edilir. Çok basit!
+
+Ancak, bu ve diğer bölümlerdeki örneklerde görebileceğiniz gibi, sunum yapan sınıfları isimsiz alt dizinlere yerleştiriyoruz, örneğin, `Home` sunum yapan `App\UI\Home\HomePresenter` sınıfıyla eşleştirilmiştir. Bu, yıldız işaretinin iki katına çıkarılmasıyla elde edilir (Nette Application 3.2 gerektirir):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Şimdi, sunum yapan kişileri modüllerle eşleştirmeye geçelim. Her modül için özel eşlemeler tanımlayabiliriz:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Şimdi `Front:Home` sunucusu `App\Modules\Front\Presenters\HomePresenter` sınıfıyla ve `Admin:Dashboard` sunucusu `App\Modules\Admin\Presenters\DashboardPresenter` sınıfıyla eşleşir.
+Bu yapılandırmaya göre, `Front:Home` sunucusu `App\UI\Front\Home\HomePresenter` sınıfıyla eşleşirken, `Api:OAuth` sunucusu `App\Api\OAuthPresenter` sınıfıyla eşleşir.
 
-İlk ikisini değiştirmek için genel bir (yıldız) kural oluşturmak daha pratiktir. Ekstra yıldız işareti sadece modül için sınıf maskesine eklenecektir:
+ `Front` ve `Admin` modülleri benzer bir eşleme yaklaşımına sahip olduğundan ve bu türden daha fazla modül olması muhtemel olduğundan, bunların yerini alan genel bir kural oluşturmak mümkündür. Sınıf maskesine modül için yeni bir yıldız işareti eklenir:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Peki ya iç içe modüller kullanıyorsak ve bir sunumcumuz varsa `Admin:User:Edit`? Bu durumda, her seviye için modülü temsil eden yıldız işaretli bölüm basitçe tekrarlanır ve sonuç `App\Modules\Admin\User\Presenters\EditPresenter` sınıfı olur.
+Sunum yapan kişi `Admin:User:Edit` gibi çok seviyeli iç içe modüller için yıldız işareti segmenti her seviye için tekrarlanır ve `App\UI\Admin\User\Edit\EditPresenter` sınıfı ortaya çıkar.
 
-Alternatif bir gösterim, bir dize yerine üç segmentten oluşan bir dizi kullanmaktır. Bu gösterim bir öncekine eşdeğerdir:
+Alternatif bir gösterim, dize yerine üç segmentten oluşan bir dizi kullanmaktır. Bu gösterim bir öncekine eşdeğerdir:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Varsayılan değer `*: *Module\*Presenter`'dur.
+Konfigürasyonda sadece bir kuralımız varsa, genel olanı, kısaca yazabiliriz:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/tr/presenters.texy b/application/tr/presenters.texy
index 35e16c86d9..78a564da6d 100644
--- a/application/tr/presenters.texy
+++ b/application/tr/presenters.texy
@@ -60,7 +60,7 @@ Yönteme benzer şekilde `render<View>()`. O sırada `render<View>()` 'de daha s
 
 Bu önemlidir `action<Action>()` daha önce çağrılır `render<View>()`Bu nedenle, içinde muhtemelen yaşam döngüsünün bir sonraki seyrini değiştirebiliriz, yani oluşturulacak şablonu ve ayrıca yöntemi değiştirebiliriz `render<View>()` `setView('otherView')` kullanılarak çağrılacaktır.
 
-İstekten gelen parametreler yönteme aktarılır. Parametreler için tür belirtmek mümkündür ve önerilir, örneğin `actionShow(int $id, string $slug = null)` - `id` parametresi eksikse veya tamsayı değilse, sunum yapan kişi [404 hatası |#Error 404 etc.] döndürür ve işlemi sonlandırır.
+İstekten gelen parametreler yönteme aktarılır. Parametreler için tür belirtmek mümkündür ve önerilir, örneğin `actionShow(int $id, ?string $slug = null)` - `id` parametresi eksikse veya tamsayı değilse, sunum yapan kişi [404 hatası |#Error 404 etc.] döndürür ve işlemi sonlandırır.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */);
 Hata 404 vb. .[#toc-error-404-etc]
 ==================================
 
-Örneğin görüntülemek istediğimiz makale veritabanında bulunmadığı için isteği yerine getiremediğimizde, HTTP hatası 404'ü temsil eden `error(string $message = null, int $httpCode = 404)` yöntemini kullanarak 404 hatasını atacağız:
+Örneğin görüntülemek istediğimiz makale veritabanında bulunmadığı için isteği yerine getiremediğimizde, HTTP hatası 404'ü temsil eden `error(?string $message = null, int $httpCode = 404)` yöntemini kullanarak 404 hatasını atacağız:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+İstek Parametreleri .[#toc-request-parameters]
+==============================================
+
+Sunucu ve her bileşen, parametrelerini HTTP isteğinden alır. Değerleri `getParameter($name)` yöntemi veya `getParameters()` kullanılarak alınabilir. Değerler dizeler veya dizelerin dizileridir, esasen doğrudan URL'den elde edilen ham verilerdir.
+
+Daha fazla kolaylık için, parametreleri özellikler aracılığıyla erişilebilir hale getirmenizi öneririz. Bunları basitçe şu şekilde açıklayın `#[Parameter]` nitelik:
+
+```php
+use Nette\Application\Attributes\Parameter;  // bu hat önemli
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // halka açık olmalı
+}
+```
+
+Özellikler için veri türünü belirtmenizi öneririz (örneğin, `string`). Nette daha sonra değeri buna göre otomatik olarak dökecektir. Parametre değerleri de [doğrulanabilir |#Validation of Parameters].
+
+Bir bağlantı oluştururken, parametreler için değeri doğrudan ayarlayabilirsiniz:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Kalıcı Parametreler .[#toc-persistent-parameters]
 =================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
  `$this->lang`, `'en'` gibi bir değere sahipse, `link()` veya `n:href` kullanılarak oluşturulan bağlantılar da `lang=en` parametresini içerecektir. Ve bağlantı tıklandığında, yine `$this->lang = 'en'` olacaktır.
 
-Özellikler için veri türünü eklemenizi öneririz (örn. `string`) ve ayrıca varsayılan bir değer de ekleyebilirsiniz. Parametre değerleri [doğrulanabilir |#Validation of Persistent Parameters].
+Özellikler için veri türünü eklemenizi öneririz (örn. `string`) ve ayrıca varsayılan bir değer de ekleyebilirsiniz. Parametre değerleri [doğrulanabilir |#Validation of Parameters].
 
 Kalıcı parametreler varsayılan olarak belirli bir sunum yapan kişinin tüm eylemleri arasında aktarılır. Bunları birden fazla sunum yapan kişi arasında geçirmek için tanımlamanız gerekir:
 
@@ -307,18 +333,12 @@ Daha Derine Gitmek .[#toc-going-deeper]
 Bu bölümde şimdiye kadar gösterdiklerimiz muhtemelen yeterli olacaktır. Aşağıdaki satırlar, sunum yapanlarla derinlemesine ilgilenen ve her şeyi bilmek isteyenlere yöneliktir.
 
 
-Gereksinim ve Parametreler .[#toc-requirement-and-parameters]
--------------------------------------------------------------
-
-Sunum yapan kişi tarafından ele alınan istek [api:Nette\Application\Request] nesnesidir ve sunum yapan kişinin `getRequest()` yöntemi tarafından döndürülür. Bir dizi parametre içerir ve bunların her biri ya bazı bileşenlere ya da doğrudan sunum yapan kişiye aittir (aslında bu da özel bir bileşen olsa da bir bileşendir). Dolayısıyla Nette parametreleri yeniden dağıtır ve `loadState(array $params)` yöntemini çağırarak tek tek bileşenler (ve sunum yapan kişi) arasında geçiş yapar. Parametreler `getParameters(): array` yöntemiyle, ayrı ayrı `getParameter($name)` kullanılarak elde edilebilir. Parametre değerleri dizeler veya dizelerin dizileridir, temelde doğrudan bir URL'den elde edilen ham verilerdir.
+Parametrelerin Doğrulanması .[#toc-validation-of-parameters]
+------------------------------------------------------------
 
+URL'lerden alınan [istek parametr |#request parameters] eleri ve [kalıcı parametrelerin |#persistent parameters] değerleri `loadState()` metodu tarafından özelliklere yazılır. Ayrıca özellikte belirtilen veri tipinin eşleşip eşleşmediğini kontrol eder, aksi takdirde 404 hatası ile yanıt verir ve sayfa görüntülenmez.
 
-Kalıcı Parametrelerin Doğrulanması .[#toc-validation-of-persistent-parameters]
-------------------------------------------------------------------------------
-
-URL'lerden alınan [kalıcı parametrelerin |#persistent parameters] değerleri `loadState()` metodu tarafından özelliklere yazılır. Ayrıca özellikte belirtilen veri türünün eşleşip eşleşmediğini kontrol eder, aksi takdirde 404 hatası ile yanıt verir ve sayfa görüntülenmez.
-
-Kalıcı parametrelere asla körü körüne güvenmeyin, çünkü bunlar URL'de kullanıcı tarafından kolayca üzerine yazılabilir. Örneğin, `$this->lang` adresinin desteklenen diller arasında olup olmadığını bu şekilde kontrol ediyoruz. Bunu yapmanın iyi bir yolu, yukarıda bahsedilen `loadState()` yöntemini geçersiz kılmaktır:
+URL'de kullanıcı tarafından kolayca üzerine yazılabilecekleri için parametrelere asla körü körüne güvenmeyin. Örneğin, `$this->lang` adresinin desteklenen diller arasında olup olmadığını bu şekilde kontrol ederiz. Bunu yapmanın iyi bir yolu, yukarıda bahsedilen `loadState()` yöntemini geçersiz kılmaktır:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Talebi Kaydetme ve Geri Yükleme .[#toc-save-and-restore-the-request]
 --------------------------------------------------------------------
 
-Geçerli isteği bir oturuma kaydedebilir veya oturumdan geri yükleyebilir ve sunucunun tekrar yürütmesine izin verebilirsiniz. Bu, örneğin bir kullanıcı bir formu doldurduğunda ve oturum açma süresi dolduğunda kullanışlıdır. Veri kaybetmemek için, oturum açma sayfasına yönlendirmeden önce, kısa bir dize biçiminde bir tanımlayıcı döndüren ve oturum açma sunucusuna parametre olarak ileten `$reqId = $this->storeRequest()` adresini kullanarak geçerli isteği oturuma kaydederiz.
+Sunum yapan kişinin ele aldığı istek bir [api:Nette\Application\Request] nesnesidir ve sunum yapan kişinin `getRequest()` yöntemi tarafından döndürülür.
+
+Geçerli isteği bir oturuma kaydedebilir veya oturumdan geri yükleyebilir ve sunum yapan kişinin bunu tekrar yürütmesine izin verebilirsiniz. Bu, örneğin bir kullanıcı bir formu doldurduğunda ve oturum açma süresi dolduğunda kullanışlıdır. Verileri kaybetmemek için, oturum açma sayfasına yönlendirmeden önce, kısa bir dize biçiminde bir tanımlayıcı döndüren ve oturum açma sunucusuna parametre olarak ileten `$reqId = $this->storeRequest()` adresini kullanarak geçerli isteği oturuma kaydederiz.
 
 Oturum açtıktan sonra, isteği oturumdan alan ve ona ileten `$this->restoreRequest($reqId)` yöntemini çağırıyoruz. Yöntem, isteğin şu anda oturum açmış olan kullanıcıyla aynı kullanıcı tarafından oluşturulduğunu doğrular. Başka bir kullanıcı giriş yaparsa veya anahtar geçersizse, hiçbir şey yapmaz ve program devam eder.
 
@@ -362,7 +384,7 @@ Yeniden yönlendirme bir AJAX veya POST isteği ile gerçekleşmez çünkü veri
 Ayrıca, `link()` yöntemi gibi sunum yapan kişiyi, eylemleri ve parametreleri bağımsız değişken olarak alan `canonicalize()` yöntemini kullanarak kanonlaştırmayı manuel olarak da çağırabilirsiniz. Bir bağlantı oluşturur ve bunu geçerli URL ile karşılaştırır. Farklıysa, oluşturulan bağlantıya yönlendirir.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// eğer $slug, $realSlug'dan farklıysa yönlendirir
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Erişim Kısıtlaması Kullanımı `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+--------------------------------------------------------------------------------------------------------
+
+Bu `#[Requires]` özniteliği, sunum yapanlara ve yöntemlerine erişimi kısıtlamak için gelişmiş seçenekler sağlar. HTTP yöntemlerini belirtmek, AJAX istekleri gerektirmek, erişimi aynı kaynakla sınırlamak ve erişimi yalnızca yönlendirme ile kısıtlamak için kullanılabilir. Öznitelik, sunum yapan sınıfların yanı sıra aşağıdaki gibi bireysel yöntemlere de uygulanabilir `action<Action>()`, `render<View>()`, `handle<Signal>()`ve `createComponent<Name>()`.
+
+Bu kısıtlamaları belirtebilirsiniz:
+- HTTP yöntemleri üzerinde: `#[Requires(methods: ['GET', 'POST'])]`
+- AJAX isteği gerektiriyor: `#[Requires(ajax: true)]`
+- yalnızca aynı kaynaktan erişim: `#[Requires(sameOrigin: true)]`
+- yalnızca yönlendirme yoluyla erişim: `#[Requires(forward: true)]`
+- belirli eylemlere ilişkin kısıtlamalar: `#[Requires(actions: 'default')]`
+
+Ayrıntılar için, bkz [Nasıl kullanılır Requires öznitelik |best-practices:attribute-requires].
+
+
+HTTP Yöntem Kontrolü .[#toc-http-method-check]
+----------------------------------------------
+
+Nette'de sunum yapanlar, öncelikle güvenlik nedenleriyle gelen her isteğin HTTP yöntemini otomatik olarak doğrular. Varsayılan olarak `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` yöntemlerine izin verilir.
+
+ `OPTIONS` gibi ek yöntemleri etkinleştirmek istiyorsanız `#[Requires]` özniteliği (Nette Uygulaması v3.2'den):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Sürüm 3.1'de doğrulama, istekte belirtilen yöntemin `$presenter->allowedMethods` dizisine dahil edilip edilmediğini kontrol eden `checkHttpMethod()` içinde gerçekleştirilir. Bunun gibi bir yöntem ekleyin:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+ `OPTIONS` yöntemini etkinleştirirseniz, bunu sunucunuzda da düzgün bir şekilde ele almanız gerektiğini vurgulamak çok önemlidir. Bu yöntem genellikle, tarayıcıların CORS (Cross-Origin Resource Sharing) politikası açısından isteğe izin verilip verilmediğini belirlemek için gerekli olduğunda asıl istekten önce otomatik olarak gönderdiği bir ön kontrol isteği olarak kullanılır. Bu yönteme izin verir ancak uygun bir yanıt uygulamazsanız, tutarsızlıklara ve potansiyel güvenlik sorunlarına yol açabilir.
+
+
 Daha Fazla Okuma .[#toc-further-reading]
 ========================================
 
diff --git a/application/tr/routing.texy b/application/tr/routing.texy
index cbd1656234..3a0b50b5d3 100644
--- a/application/tr/routing.texy
+++ b/application/tr/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Gelişmiş Notasyon .[#toc-advanced-notation]
 -------------------------------------------
 
-Genellikle `Presenter:action` biçiminde yazdığımız rotanın ikinci parametresi, tek tek parametrelerin (varsayılan) değerlerini doğrudan belirttiğimiz bir alan biçiminde de yazabileceğimiz bir kısaltmadır:
+Genellikle `Presenter:action` şeklinde yazılan bir rotanın hedefi, tek tek parametreleri ve bunların varsayılan değerlerini tanımlayan bir dizi kullanılarak da ifade edilebilir:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Ya da bu formu kullanabiliriz, doğrulama düzenli ifadesinin yeniden yazıldığına dikkat edin:
+Daha ayrıntılı bir belirtim için, varsayılan değerlere ek olarak, doğrulama düzenli ifadesi gibi diğer parametre özelliklerinin de ayarlanabildiği daha da genişletilmiş bir form kullanılabilir (bkz. `id` parametresi):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Bu daha konuşkan formatlar diğer meta verileri eklemek için kullanışlıdır.
+Dizide tanımlanan parametreler yol maskesine dahil edilmemişse, URL'de bir soru işaretinden sonra belirtilen sorgu parametreleri kullanılsa bile değerlerinin değiştirilemeyeceğine dikkat etmek önemlidir.
 
 
 Filtreler ve Çeviriler .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Entegrasyon .[#toc-integration]
 ===============================
 
-Yönlendiricimizi uygulamaya bağlamak için DI konteynerine bunu söylemeliyiz. Bunun en kolay yolu router nesnesini oluşturacak fabrikayı hazırlamak ve container konfigürasyonuna bunu kullanmasını söylemektir. Diyelim ki bu amaçla bir metot yazdık `App\Router\RouterFactory::createRouter()`:
+Yönlendiricimizi uygulamaya bağlamak için DI konteynerine bunu söylemeliyiz. Bunun en kolay yolu router nesnesini oluşturacak fabrikayı hazırlamak ve container konfigürasyonuna bunu kullanmasını söylemektir. Diyelim ki bu amaçla bir metot yazdık `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ Daha sonra [yapılandırmaya |dependency-injection:services] yazıyoruz:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Veritabanı bağlantısı vb. gibi tüm bağımlılıklar, [otomatik |dependency-injection:autowiring] bağlantı kullanılarak fabrika yöntemine parametreleri olarak aktarılır:
@@ -663,7 +663,7 @@ Ayrı kullanımla, yönlendiricinin yeteneklerinin Nette Uygulaması ve sunucula
 Bu yüzden yine örneğin bir yönlendirici oluşturacak bir yöntem oluşturacağız:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Ya da doğrudan nesneler oluşturacağız:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/tr/templates.texy b/application/tr/templates.texy
index d817bc2d45..bd2fea6eee 100644
--- a/application/tr/templates.texy
+++ b/application/tr/templates.texy
@@ -34,35 +34,81 @@ Bu da eylem şablonu olabilir:
 Düzende `{include content}` yerine eklenen `content` bloğunu tanımlar ve ayrıca düzende `{block title}` 'un üzerine yazılan `title` bloğunu yeniden tanımlar. Sonucu hayal etmeye çalışın.
 
 
-Şablon Arama .[#toc-search-for-templates]
------------------------------------------
+Şablon Arama .[#toc-template-lookup]
+------------------------------------
+
+Sunucularda, hangi şablonun işleneceğini belirtmenize gerek yoktur; çerçeve yolu otomatik olarak belirleyerek kodlamayı sizin için kolaylaştıracaktır.
+
+Her sunucunun kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, şablonu bu dizine eylemin adı (yani görünüm) altında yerleştirmeniz yeterlidir. Örneğin, `default` eylemi için `default.latte` şablonunu kullanın:
 
-Şablonların yolu basit bir mantığa göre çıkarılır. Sunucu sınıfının bulunduğu dizine göre bu şablon dosyalarından birinin var olup olmadığına bakılır, burada `<Presenter>` geçerli sunum yapan kişinin adı ve `<view>` geçerli eylemin adıdır:
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Sunucuların tek bir dizinde ve şablonların `templates` klasöründe bir arada olduğu bir yapı kullanıyorsanız, bunu bir dosyaya kaydedin `<Presenter>.<view>.latte` veya `<Presenter>/<view>.latte`:
 
-Şablon bulunamazsa, `templates` dizininde bir seviye yukarıda, yani sunum yapan sınıfın bulunduğu dizinle aynı seviyede arama yapmaya çalışacaktır.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
 
-Şablon orada da bulunamazsa, yanıt [404 hatası |presenters#Error 404 etc.] olur.
+ `templates` dizini, sunum yapan sınıfların bulunduğu dizinle aynı seviyede, bir seviye daha yükseğe de yerleştirilebilir.
 
-Ayrıca `$this->setView('otherView')` adresini kullanarak görünümü değiştirebilirsiniz. Ya da arama yapmak yerine `$this->template->setFile('/path/to/template.latte')` adresini kullanarak şablon dosyasının adını doğrudan belirtin.
+Şablon bulunamazsa, sunum yapan kişi [404 - sayfa bulunamadı hatası |presenters#Error 404 etc] ile yanıt verir.
+
+Görünümü `$this->setView('anotherView')` adresini kullanarak değiştirebilirsiniz. Şablon dosyasını `$this->template->setFile('/path/to/template.latte')` ile doğrudan belirtmek de mümkündür.
 
 .[note]
-Olası dosya yollarından oluşan bir dizi döndüren [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] yöntemini geçersiz kılarak şablonların arandığı yolları değiştirebilirsiniz.
+Şablonların arandığı dosyalar, olası dosya adlarından oluşan bir dizi döndüren [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()] yöntemi geçersiz kılınarak değiştirilebilir.
+
+
+Düzen Şablonu Arama .[#toc-layout-template-lookup]
+--------------------------------------------------
+
+Nette ayrıca otomatik olarak yerleşim dosyasını arar.
+
+Her sunum yapan kişinin kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, düzeni ya sadece sunum yapan kişiye özelse sunum yapan kişinin bulunduğu klasöre ya da birden fazla sunum yapan kişi için ortaksa bir üst seviyeye yerleştirin:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Sunum yapanların tek bir dizinde gruplandığı ve şablonların `templates` klasöründe bulunduğu bir yapı kullanıyorsanız, düzen aşağıdaki yerlerde beklenecektir:
 
-Düzen aşağıdaki dosyalarda beklenmektedir:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` birden fazla sunumcu için ortak düzen
+Sunucu bir [modüldeyse |modules], modülün iç içe geçmesine göre dizin ağacının daha yukarısında da arama yapacaktır.
 
-`<Presenter>` geçerli sunum yapan kişinin adı ve `<layout>` varsayılan olarak `'layout'` olan düzenin adıdır. İsim `$this->setLayout('otherLayout')` ile değiştirilebilir, böylece `@otherLayout.latte` dosyaları denenecektir.
+Düzenin adı `$this->setLayout('layoutAdmin')` kullanılarak değiştirilebilir ve ardından `@layoutAdmin.latte` dosyasında beklenir. Düzen şablon dosyasını `$this->setLayout('/path/to/template.latte')` adresini kullanarak doğrudan da belirtebilirsiniz.
 
-Düzen şablonunun dosya adını `$this->setLayout('/path/to/template.latte')` adresini kullanarak doğrudan da belirtebilirsiniz. `$this->setLayout(false)` adresini kullanmak düzen aramayı devre dışı bırakacaktır.
+Şablon içinde `$this->setLayout(false)` veya `{layout none}` etiketinin kullanılması düzen aramayı devre dışı bırakır.
 
 .[note]
-Olası dosya yollarından oluşan bir dizi döndüren [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] yöntemini geçersiz kılarak şablonların arandığı yolları değiştirebilirsiniz.
+Düzen şablonlarının arandığı dosyalar, olası dosya adlarından oluşan bir dizi döndüren [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] yöntemi geçersiz kılınarak değiştirilebilir.
 
 
 Şablondaki Değişkenler .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ Sunucudaki `$this->template` nesnesi artık `ArticleTemplate` sınıfının bir
 Şablonlarda da fısıldama lüksünün tadını çıkarabilirsiniz, sadece PhpStorm'da Latte eklentisini kurun ve şablonun başında sınıf adını belirtin, "Latte: sistem nasıl yazılır":https://blog.nette.org/tr/latte-tip-sistemi-nasil-kullanilir makalesine bakın:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte sürüm 3, her web projesi için bir [uzantı |latte:creating-extension] oluşturarak daha gelişmiş bir yol sunar. İşte böyle bir sınıfın kabaca bir örneği:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ Alternatif olarak, çevirmen [yapılandırma |configuration#Latte] kullanılarak
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Çevirmen daha sonra örneğin `|translate` filtresi olarak kullanılabilir ve ek parametreler `translate()` yöntemine aktarılabilir (bkz. `foo, bar`):
diff --git a/application/uk/@home.texy b/application/uk/@home.texy
index c1bd9272d7..fcc2f61317 100644
--- a/application/uk/@home.texy
+++ b/application/uk/@home.texy
@@ -28,8 +28,9 @@ composer require nette/application
 
 | версія пакета | сумісна версія PHP
 |-----------------------|-----------------------
-| Nette Application 4.0 | PHP 8.0 - 8.1
-| Nette Application 3.1 | PHP 7.2 - 8.1
+| Nette Application 4.0 | PHP 8.1 – 8.3
+| Nette Application 3.2 | PHP 8.1 – 8.3
+| Nette Application 3.1 | PHP 7.2 – 8.3
 | Nette Application 3.0 | PHP 7.1 - 8.0
 | Nette Application 2.4 | PHP 5.6 - 8.0
 
diff --git a/application/uk/ajax.texy b/application/uk/ajax.texy
index 657629160c..9a6e49c71c 100644
--- a/application/uk/ajax.texy
+++ b/application/uk/ajax.texy
@@ -1,12 +1,12 @@
-AJAX і сніпети
-**************
+AJAX та сніппети
+****************
 
 <div class=perex>
 
-Сучасні веб-додатки сьогодні працюють наполовину на сервері, а наполовину в браузері. AJAX є життєво важливим об'єднуючим фактором. Яку підтримку пропонує фреймворк Nette?
-- надсилання фрагментів шаблонів (так званих *сніпетів*)
-- передача змінних між PHP і JavaScript
-- Налагодження додатків AJAX
+В епоху сучасних веб-додатків, де функціональність часто поширюється між сервером і браузером, AJAX є важливим сполучним елементом. Які можливості пропонує Nette Framework у цій сфері?
+- надсилання частин шаблону, так званих фрагментів (snippets)
+- передача змінних між PHP та JavaScript
+- інструменти для налагодження AJAX-запитів
 
 </div>
 
@@ -14,29 +14,32 @@ AJAX і сніпети
 AJAX запит .[#toc-ajax-request]
 ===============================
 
-AJAX-запит нічим не відрізняється від класичного запиту - викликається доповідач з певним представленням і параметрами. Як на нього відповісти, також залежить від доповідача: він може використовувати власну процедуру, яка повертає фрагмент HTML-коду (HTML-сніппет), XML-документ, JSON-об'єкт або JavaScript-код.
+AJAX-запит принципово не відрізняється від класичного HTTP-запиту. Викликається презентер з певними параметрами. Ведучий сам вирішує, як відповісти на запит - він може повернути дані у форматі JSON, надіслати частину HTML-коду, XML-документ тощо.
 
-На стороні сервера AJAX-запит можна виявити за допомогою сервісного методу, що [інкапсулює HTTP-запит |http:request] `$httpRequest->isAjax()` (виявляє на основі HTTP-заголовка `X-Requested-With`). Усередині доповідача доступний ярлик у вигляді методу `$this->isAjax()`.
+На стороні браузера ми ініціюємо AJAX-запит за допомогою функції `fetch()`:
 
-Існує попередньо оброблений об'єкт `payload`, призначений для надсилання даних у браузер у форматі JSON.
-
-```php
-public function actionDelete(int $id): void
-{
-	if ($this->isAjax()) {
-		$this->payload->message = 'Успішно';
-	}
-	// ...
-}
+```js
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
+.then(response => response.json())
+.then(payload => {
+	// обробка відповіді
+});
 ```
 
-Для повного контролю над виведенням JSON використовуйте метод `sendJson` у презентері. Це негайно перерве роботу презентера, і ви обійдетеся без шаблону:
+На стороні сервера AJAX-запит розпізнається методом `$httpRequest->isAjax()` сервісу, що [інкапсулює HTTP-запит |http:request]. Він використовує HTTP-заголовок `X-Requested-With`, тому його обов'язково потрібно відправити. У презентері ви можете використовувати метод `$this->isAjax()`.
+
+Якщо ви хочете відправити дані у форматі JSON, використовуйте метод [`sendJson()` |presenters#Sending a response] метод. Метод також завершує роботу доповідача.
 
 ```php
-$this->sendJson(['key' => 'value', /* ... */]);
+public function actionExport(): void
+{
+	$this->sendJson($this->model->getData);
+}
 ```
 
-Якщо ми хочемо надіслати HTML, ми можемо встановити спеціальний шаблон для AJAX-запитів:
+Якщо ви плануєте відповідати за допомогою спеціального шаблону, розробленого для AJAX, ви можете зробити це наступним чином:
 
 ```php
 public function handleClick($param): void
@@ -44,27 +47,43 @@ public function handleClick($param): void
 	if ($this->isAjax()) {
 		$this->template->setFile('path/to/ajax.latte');
 	}
-	// ...
+	//...
 }
 ```
 
 
-Naja .[#toc-naja]
-=================
+Фрагменти .[#toc-snippets]
+==========================
+
+Найпотужнішим інструментом, який пропонує Nette для зв'язку сервера з клієнтом, є сніппети. З їх допомогою ви можете перетворити звичайний додаток на AJAX з мінімальними зусиллями та кількома рядками коду. Приклад Fifteen демонструє, як це все працює, а його код можна знайти на [GitHub |https://github.com/nette-examples/fifteen].
+
+Сніппети, або вирізки, дозволяють оновлювати лише частини сторінки, замість того, щоб перезавантажувати всю сторінку. Це швидше і ефективніше, а також забезпечує більш комфортний користувацький досвід. Сніппети можуть нагадати вам Hotwire для Ruby on Rails або Symfony UX Turbo. Цікаво, що Nette представила сніппети на 14 років раніше.
 
-[Бібліотека Naja |https://naja.js.org] використовується для обробки AJAX-запитів на стороні браузера. [Встановіть |https://naja.js.org/#/guide/01-install-setup-naja] його як пакет node.js (для використання з Webpack, Rollup, Vite, Parcel та іншими):
+Як працюють фрагменти? При першому завантаженні сторінки (не AJAX-запит) завантажується вся сторінка, включаючи всі фрагменти. Коли користувач взаємодіє зі сторінкою (наприклад, натискає кнопку, відправляє форму тощо), замість завантаження всієї сторінки виконується AJAX-запит. Код у презентері виконує дію і вирішує, які фрагменти потрібно оновити. Nette рендерить ці фрагменти і надсилає їх у вигляді масиву JSON. Потім код обробки в браузері вставляє отримані фрагменти назад на сторінку. Таким чином, передається лише код змінених фрагментів, що економить пропускну здатність і прискорює завантаження порівняно з передачею всього вмісту сторінки.
+
+
+Наджа .[#toc-naja]
+------------------
+
+Для обробки фрагментів на стороні браузера використовується [бібліотека Naja |https://naja.js.org]. [Встановіть її |https://naja.js.org/#/guide/01-install-setup-naja] як пакет node.js (для використання з такими додатками, як Webpack, Rollup, Vite, Parcel та іншими):
 
 ```shell
 npm install naja
 ```
 
-...або вставити безпосередньо в шаблон сторінки:
+... або вставте її безпосередньо в шаблон сторінки:
 
 ```html
 <script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
 ```
 
-Щоб створити AJAX-запит зі звичайного посилання (сигналу) або форми, просто позначте відповідне посилання, форму або кнопку класом `ajax`:
+Спочатку потрібно [ініціалізувати |https://naja.js.org/#/guide/01-install-setup-naja?id=initialization] бібліотеку:
+
+```js
+naja.initialize();
+```
+
+Щоб зробити звичайне посилання (сигнал) або відправку форми AJAX-запитом, просто позначте відповідне посилання, форму або кнопку класом `ajax`:
 
 ```html
 <a n:href="go!" class="ajax">Go</a>
@@ -74,64 +93,39 @@ npm install naja
 </form>
 
 or
+
 <form n:name="form">
     <input n:name="submit" class="ajax">
 </form>
 ```
 
 
-Сніпети .[#toc-snippety]
-========================
-
-Однак існує набагато потужніший інструмент вбудованої підтримки AJAX - сніпети. Їхнє використання дає змогу перетворити звичайний застосунок на AJAX-додаток за допомогою лише кількох рядків коду. Як усе це працює, показано в прикладі Fifteen, код якого також доступний у збірці або на [GitHub |https://github.com/nette-examples/fifteen].
-
-Принцип роботи сніпетів полягає в тому, що всю сторінку передають під час початкового (тобто не-AJAX) запиту, а потім із кожним AJAX [subrequest |components#Signal] (запит до того самого подання того самого презентера) тільки код змінених частин передають до сховища `payload`, згаданого раніше.
-
-Сніпети можуть нагадати вам Hotwire для Ruby on Rails або Symfony UX Turbo, але Nette придумав їх чотирнадцятьма роками раніше.
-
-
-Інвалідація .[#toc-invalidation-of-snippets]
-============================================
+Перемальовуємо фрагменти .[#toc-redrawing-snippets]
+---------------------------------------------------
 
-Кожен нащадок класу [Control |components] (яким є і Presenter) здатний пам'ятати, чи були якісь зміни під час запиту, що вимагають повторного відображення. Існує кілька способів впоратися з цим: `redrawControl()` і `isControlInvalid()`. Приклад:
+Кожен об'єкт класу [Control |components] (в тому числі і сам доповідач) зберігає інформацію про те, чи відбулися зміни, які вимагають його перемальовування. Для цього використовується метод `redrawControl()`.
 
 ```php
 public function handleLogin(string $user): void
 {
-	// Об'єкт має повторно відображатися після того, як користувач увійшов у систему
+	// після входу в систему необхідно перемалювати відповідну частину
 	$this->redrawControl();
-	// ...
+	//...
 }
 ```
-Однак Nette забезпечує ще більш тонкий дозвіл, ніж цілі компоненти. Перераховані методи приймають ім'я так званого "фрагмента" як необов'язковий параметр. "Фрагмет" це, по суті, елемент у вашому шаблоні, позначений для цієї мети макросом Latte, докладніше про це пізніше. Таким чином, можна попросити компонент перемалювати тільки *частину* свого шаблону. Якщо весь компонент недійсний, то всі його фрагменти відображаються заново. Компонент є "недійсним", якщо будь-який з його субкомпонентів є недійсним.
 
-```php
-$this->isControlInvalid(); // -> false
-
-$this->redrawControl('header'); // анулює фрагмент з ім'ям 'header'
-$this->isControlInvalid('header'); // -> true
-$this->isControlInvalid('footer'); // -> false
-$this->isControlInvalid(); // -> true, принаймні один фрагмент недійсний
+Nette також дозволяє краще контролювати те, що потрібно перемалювати. Вищезгаданий метод може приймати назву фрагмента як аргумент. Таким чином, його можна анулювати (тобто примусово перемалювати) на рівні частини шаблону. Якщо весь компонент анулюється, кожен його фрагмент також перемальовується:
 
-$this->redrawControl(); // робить недійсним весь компонент, кожен фрагмент
-$this->isControlInvalid('footer'); // -> true
+```php
+// робить недійсним фрагмент 'header'
+$this->redrawControl('header');
 ```
 
-Компонент, який отримав сигнал, автоматично позначається для перемальовування.
-
-Завдяки перемальовуванню фрагментів ми точно знаємо, які частини яких елементів мають бути перемальовані.
-
-
-Тег `{snippet} … {/snippet}` .{toc: Tag snippet}
-================================================
-
-Рендеринг сторінки відбувається так само, як і під час звичайного запиту: завантажуються одні й ті самі шаблони тощо. Однак найважливіше - це не допустити потрапляння до вихідного сигналу тих частин, які не повинні потрапити до вихідного сигналу; інші частини мають бути пов'язані з ідентифікатором і надіслані користувачеві у форматі, зрозумілому для обробника JavaScript.
-
 
-Синтаксис .[#toc-sintaksis]
----------------------------
+Фрагменти в Latte .[#toc-snippets-in-latte]
+-------------------------------------------
 
-Якщо в шаблоні є елемент управління або фрагмент, ми повинні обернути його за допомогою парного тега `{snippet} ... {/snippet}` - відмальований фрагмент буде "вирізаний" і відправиться в браузер. Він також укладе його в допоміжний тег `<div>` (можна використовувати інший). У наступному прикладі визначено сніппет з ім'ям `header`. Він також може являти собою шаблон компонента:
+Використовувати фрагменти в Latte надзвичайно просто. Щоб визначити частину шаблону як фрагмент, просто оберніть його тегами `{snippet}` та `{/snippet}`:
 
 ```latte
 {snippet header}
@@ -139,7 +133,9 @@ $this->isControlInvalid('footer'); // -> true
 {/snippet}
 ```
 
-Якщо ви хочете створити сніппет з іншим елементом, що містить, відмінним від `<div>`, або додати користувацькі атрибути до елемента, ви можете використовувати таке визначення:
+Фрагмент створює елемент `<div>` в HTML-сторінці зі спеціально згенерованим `id`. При перемальовуванні фрагмента вміст цього елемента оновлюється. Тому під час першого відображення сторінки всі сніппети також повинні бути відображені, навіть якщо спочатку вони можуть бути порожніми.
+
+Ви також можете створити фрагмент з елементом, відмінним від `<div>` використовуючи атрибут n::
 
 ```latte
 <article n:snippet="header" class="foo bar">
@@ -148,138 +144,106 @@ $this->isControlInvalid('footer'); // -> true
 ```
 
 
-Динамічні сніпети .[#toc-dinamiceskie-snippety]
-===============================================
+Області фрагментів .[#toc-snippet-areas]
+----------------------------------------
 
-У Nette ви також можете визначити сніпети з динамічним ім'ям, заснованим на параметрі часу виконання. Це найбільше підходить для різних списків, де нам потрібно змінити лише один рядок, але ми не хочемо переносити весь список разом із ним. Прикладом цього може бути:
+Назви фрагментів також можуть бути виразами:
 
 ```latte
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-		<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
-	{/foreach}
-</ul>
+{foreach $items as $id => $item}
+	<li n:snippet="item-{$id}">{$item}</li>
+{/foreach}
 ```
 
-Існує один статичний сніппет `itemsContainer`, що містить кілька динамічних сніпетів: `пункт-0`, `пункт-1` і так далі.
+Таким чином, ми отримаємо кілька фрагментів на кшталт `item-0`, `item-1` і т.д. Якщо ми безпосередньо зробимо недійсним динамічний фрагмент (наприклад, `item-1`), нічого не буде перемальовано. Причина в тому, що сніппети функціонують як справжні уривки, і тільки вони безпосередньо рендерингуються. Однак у шаблоні технічно не існує фрагмента з назвою `item-1`. Він з'являється лише при виконанні коду, що оточує фрагмент, в даному випадку - циклу foreach. Тому ми позначимо частину шаблону, яку потрібно виконати, тегом `{snippetArea}`:
 
-Ви не можете перемалювати динамічний фрагмент безпосередньо (перемальовування `item-1` не має ефекту), ви маєте перемалювати його батьківський фрагмент (у цьому прикладі `itemsContainer`). При цьому виконується код батьківського сніпета, але браузеру передаються тільки його вкладені сніпети. Якщо ви хочете передати тільки один із вкладених сніпетів, вам потрібно змінити введення для батьківського сніпета, щоб не генерувати інші вкладені сніпети.
+```latte
+<ul n:snippetArea="itemsContainer">
+	{foreach $items as $id => $item}
+		<li n:snippet="item-{$id}">{$item}</li>
+	{/foreach}
+</ul>
+```
 
-У наведеному прикладі необхідно переконатися, що під час AJAX-запиту до масиву `$list` буде додано тільки один елемент, тому цикл `foreach` виводитиме тільки один динамічний фрагмент.
+І перемалюємо як окремий фрагмент, так і всю область, що охоплює його:
 
 ```php
-class HomePresenter extends Nette\Application\UI\Presenter
-{
-	/**
-	 * Этот метод возвращает данные для списка.
-	 * Обычно это просто запрос данных из модели.
-	 * Для целей этого примера данные жёстко закодированы.
-	 */
-	private function getTheWholeList(): array
-	{
-		return [
-			'First',
-			'Second',
-			'Third',
-		];
-	}
-
-	public function renderDefault(): void
-	{
-		if (!isset($this->template->list)) {
-			$this->template->list = $this->getTheWholeList();
-		}
-	}
-
-	public function handleUpdate(int $id): void
-	{
-		$this->template->list = $this->isAjax()
-				? []
-				: $this->getTheWholeList();
-		$this->template->list[$id] = 'Updated item';
-		$this->redrawControl('itemsContainer');
-	}
-}
+$this->redrawControl('itemsContainer');
+$this->redrawControl('item-1');
 ```
 
+Важливо також переконатися, що масив `$items` містить лише ті елементи, які потрібно перемалювати.
 
-Сніпети в увімкненому шаблоні .[#toc-snippety-vo-vklyucennom-sablone]
-=====================================================================
-
-Може трапитися так, що сніппет міститься в шаблоні, який вмикається з іншого шаблону. У цьому разі необхідно обернути код включення в другому шаблоні макросом `snippetArea`, потім перемалювати як snippetArea, так і сам сніппет.
-
-Макрос `snippetArea` гарантує, що код усередині нього буде виконано, але браузеру буде надіслано тільки фактичний фрагмент включеного шаблону.
+При вставці іншого шаблону в основний за допомогою тегу `{include}`, який містить фрагменти, необхідно знову загорнути включений шаблон в `snippetArea` і зробити недійсним як фрагмент, так і область разом:
 
 ```latte
-{* parent.latte *}
-{snippetArea wrapper}
-	{include 'child.latte'}
+{snippetArea include}
+	{include 'included.latte'}
 {/snippetArea}
 ```
+
 ```latte
-{* child.latte *}
+{* included.latte *}
 {snippet item}
-...
+	...
 {/snippet}
 ```
+
 ```php
-$this->redrawControl('wrapper');
+$this->redrawControl('include');
 $this->redrawControl('item');
 ```
 
-Ви також можете поєднувати його з динамічними сніпетами.
 
+Сніппети в компонентах .[#toc-snippets-in-components]
+-----------------------------------------------------
 
-Додавання та видалення .[#toc-dobavlenie-i-udalenie]
-====================================================
-
-Якщо додати новий елемент у список і анулювати `itemsContainer`, AJAX-запит поверне фрагменти, включно з новим, але javascript-обробник не зможе його відобразити. Це відбувається тому, що немає HTML-елемента з новоствореним ID.
-
-У цьому випадку найпростіший спосіб - обернути весь список у ще один сніпет і визнати його недійсним:
+Ви можете створювати фрагменти всередині [компонентів |components], і Nette автоматично перемальовуватиме їх. Однак є певне обмеження: для перемальовування фрагментів він викликає метод `render()` без жодних параметрів. Таким чином, передача параметрів у шаблоні не спрацює:
 
 ```latte
-{snippet wholeList}
-<ul n:snippet="itemsContainer">
-	{foreach $list as $id => $item}
-	<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
-	{/foreach}
-</ul>
-{/snippet}
-<a class="ajax" n:href="add!">Добавить</a>
+OK
+{control productGrid}
+
+will not work:
+{control productGrid $arg, $arg}
+{control productGrid:paginator}
 ```
 
+
+Надсилання даних користувача .[#toc-sending-user-data]
+------------------------------------------------------
+
+Разом зі сніппетами ви можете надсилати клієнту будь-які додаткові дані. Просто впишіть їх в об'єкт `payload`:
+
 ```php
-public function handleAdd(): void
+public function actionDelete(int $id): void
 {
-	$this->template->list = $this->getTheWholeList();
-	$this->template->list[] = 'New one';
-	$this->redrawControl('wholeList');
+	//...
+	if ($this->isAjax()) {
+		$this->payload->message = 'Success';
+	}
 }
 ```
 
-Те ж саме стосується і видалення елемента. Можна було б надіслати порожній сніппет, але зазвичай списки можуть бути посторінковими, і було б складно реалізувати видалення одного елемента і завантаження іншого (який раніше перебував на іншій сторінці посторінкового списку).
-
 
-Надсилання параметрів компоненту .[#toc-otpravka-parametrov-komponentu]
-=======================================================================
+Параметри відправки .[#toc-sending-parameters]
+==============================================
 
-Коли ми надсилаємо параметри компоненту через AJAX-запит, чи то сигнальні, чи постійні параметри, ми повинні надати їхнє глобальне ім'я, яке також містить ім'я компонента. Повне ім'я параметра повертає метод `getParameterId()`.
+Коли ми надсилаємо параметри компоненту за допомогою AJAX-запиту, будь то сигнальні параметри або постійні параметри, ми повинні вказати їх глобальне ім'я, яке також містить ім'я компонента. Повне ім'я параметра повертає метод `getParameterId()`.
 
 ```js
-$.getJSON(
-	{link changeCountBasket!},
-	{
-		{$control->getParameterId('id')}: id,
-		{$control->getParameterId('count')}: count
-	}
-});
+let url = new URL({link //foo!});
+url.searchParams.set({$control->getParameterId('bar')}, bar);
+
+fetch(url, {
+	headers: {'X-Requested-With': 'XMLHttpRequest'},
+})
 ```
 
-І обробити метод з відповідними параметрами в компоненті.
+Метод обробки з відповідними параметрами в компоненті:
 
 ```php
-public function handleChangeCountBasket(int $id, int $count): void
+public function handleFoo(int $bar): void
 {
-
 }
 ```
diff --git a/application/uk/bootstrap.texy b/application/uk/bootstrap.texy
index f71b35252b..aef63e390f 100644
--- a/application/uk/bootstrap.texy
+++ b/application/uk/bootstrap.texy
@@ -20,18 +20,44 @@ use Nette\Bootstrap\Configurator;
 
 class Bootstrap
 {
-	public static function boot(): Configurator
+	private Configurator $configurator;
+	private string $rootDir;
+
+	public function __construct()
+	{
+		$this->rootDir = dirname(__DIR__);
+		// Конфігуратор відповідає за налаштування середовища та служб програми.
+		$this->configurator = new Configurator;
+		// Встановіть каталог для тимчасових файлів, що генеруються Nette (наприклад, скомпільовані шаблони)
+		$this->configurator->setTempDirectory($this->rootDir . '/temp');
+	}
+
+	public function bootWebApplication(): Nette\DI\Container
 	{
-		$appDir = dirname(__DIR__);
-		$configurator = new Configurator;
-		//$configurator->setDebugMode('secret@23.75.345.200');
-		$configurator->enableTracy($appDir . '/log');
-		$configurator->setTempDirectory($appDir . '/temp');
-		$configurator->createRobotLoader()
+		$this->initializeEnvironment();
+		$this->setupContainer();
+		return $this->configurator->createContainer();
+	}
+
+	private function initializeEnvironment(): void
+	{
+		// Nette розумний, і режим розробки вмикається автоматично,
+		// або ви можете увімкнути його для певної IP-адреси, не коментуючи наступний рядок:
+		// $this->configurator->setDebugMode('secret@23.75.345.200');
+
+		// Вмикає Tracy: найкращий інструмент налагодження "швейцарський армійський ніж".
+		$this->configurator->enableTracy($this->rootDir . '/log');
+
+		// RobotLoader: автозавантаження всіх класів у вказаному каталозі
+		$this->configurator->createRobotLoader()
 			->addDirectory(__DIR__)
 			->register();
-		$configurator->addConfig($appDir . '/config/common.neon');
-		return $configurator;
+	}
+
+	private function setupContainer(): void
+	{
+		// Завантажити конфігураційні файли
+		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 	}
 }
 ```
@@ -40,16 +66,15 @@ class Bootstrap
 index.php .[#toc-index-php]
 ===========================
 
-У випадку веб-додатків початковим файлом є `index.php`, який знаходиться у загальнодоступному каталозі `www/`. Він дозволяє класу `Bootstrap` ініціалізувати середовище і повертає `$configurator`, який створює контейнер DI. Потім він отримує сервіс `Application`, який запускає веб-додаток:
+Початковим файлом для веб-додатків є `index.php`, розташований у загальнодоступному каталозі `www/`. Він використовує клас `Bootstrap` для ініціалізації середовища і створення DI-контейнера. Потім він отримує сервіс `Application` з контейнера, який запускає веб-додаток:
 
 ```php
-// ініціалізуємо середовище + отримуємо об'єкт Configurator
-$configurator = App\Bootstrap::boot();
-// створюємо DI-контейнер
-$container = $configurator->createContainer();
-// DI-контейнер створює об'єкт Nette\Application\Application
+$bootstrap = new App\Bootstrap;
+// Ініціалізація середовища + створення контейнера DI
+$container = $bootstrap->bootWebApplication();
+// Контейнер DI створює об'єкт Nette\Application\Application
 $application = $container->getByType(Nette\Application\Application::class);
-// запускаємо додаток Nette
+// Запустіть додаток Nette та обробіть вхідний запит
 $application->run();
 ```
 
@@ -66,19 +91,19 @@ Nette розрізняє два основні режими, в яких вик
 Якщо ви хочете ввімкнути режим розробки в інших випадках, наприклад, для програмістів, які отримують доступ з певної IP-адреси, ви можете використовувати `setDebugMode()`:
 
 ```php
-$configurator->setDebugMode('23.75.345.200'); // одна або більше IP-адрес
+$this->configurator->setDebugMode('23.75.345.200'); // одна або більше IP-адрес
 ```
 
 Ми безумовно рекомендуємо поєднувати IP-адресу з файлом cookie. Ми зберігатимемо секретний токен у cookie `nette-debug', например, `secret1234`, і режим розробки буде активовано для програмістів із такою комбінацією IP і cookie.
 
 ```php
-$configurator->setDebugMode('secret1234@23.75.345.200');
+$this->configurator->setDebugMode('secret1234@23.75.345.200');
 ```
 
 Можна повністю вимкнути режим розробника, навіть для localhost:
 
 ```php
-$configurator->setDebugMode(false);
+$this->configurator->setDebugMode(false);
 ```
 
 Зверніть увагу, що значення `true` жорстко вмикає режим розробника, чого ніколи не повинно відбуватися на робочому сервері.
@@ -90,7 +115,7 @@ $configurator->setDebugMode(false);
 Для полегшення налагодження ми увімкнемо чудовий інструмент [Tracy |tracy:]. У режимі розробника він візуалізує помилки, а в режимі виробництва - записує помилки в зазначений каталог:
 
 ```php
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->enableTracy($this->rootDir . '/log');
 ```
 
 
@@ -100,7 +125,7 @@ $configurator->enableTracy($appDir . '/log');
 Nette використовує кеш для DI-контейнера, RobotLoader, шаблонів тощо. Тому необхідно задати шлях до директорії, де зберігатиметься кеш:
 
 ```php
-$configurator->setTempDirectory($appDir . '/temp');
+$this->configurator->setTempDirectory($this->rootDir . '/temp');
 ```
 
 У Linux або macOS встановіть [права на запис |nette:troubleshooting#Setting-Directory-Permissions] для каталогів `log/` і `temp/`.
@@ -112,7 +137,7 @@ RobotLoader .[#toc-robotloader]
 Зазвичай ми хочемо автоматично завантажувати класи за допомогою [RobotLoader |robot-loader:], тому ми повинні запустити його і дозволити йому завантажити класи з каталогу, в якому знаходиться `Bootstrap.php` (тобто `__DIR__`) і всі його підкаталоги:
 
 ```php
-$configurator->createRobotLoader()
+$this->configurator->createRobotLoader()
 	->addDirectory(__DIR__)
 	->register();
 ```
@@ -126,7 +151,7 @@ $configurator->createRobotLoader()
 Configurator дає змогу вказати часовий пояс для вашого застосунку.
 
 ```php
-$configurator->setTimeZone('Europe/Prague');
+$this->configurator->setTimeZone('Europe/Prague');
 ```
 
 
@@ -143,16 +168,17 @@ $configurator->setTimeZone('Europe/Prague');
 Файли конфігурації завантажуються за допомогою `addConfig()`:
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
+$this->configurator->addConfig($this->rootDir . '/config/common.neon');
 ```
 
 Метод `addConfig()` може бути викликаний кілька разів для додавання декількох файлів.
 
 ```php
-$configurator->addConfig($appDir . '/config/common.neon');
-$configurator->addConfig($appDir . '/config/local.neon');
+$configDir = $this->rootDir . '/config';
+$this->configurator->addConfig($configDir . '/common.neon');
+$this->configurator->addConfig($configDir . '/services.neon');
 if (PHP_SAPI === 'cli') {
-	$configurator->addConfig($appDir . '/config/cli.php');
+	$this->configurator->addConfig($configDir . '/cli.php');
 }
 ```
 
@@ -169,7 +195,7 @@ if (PHP_SAPI === 'cli') {
 Параметри, що використовуються у файлах конфігурації, можуть бути визначені [в секції `parameters` |dependency-injection:configuration#parameters] і підхоплені (або перезаписані) методом `addStaticParameters()` (у нього є аліас `addParameters()`). Важливо, що різні значення параметрів викликають генерацію додаткових DI-контейнерів, тобто додаткових класів.
 
 ```php
-$configurator->addStaticParameters([
+$this->configurator->addStaticParameters([
 	'projectId' => 23,
 ]);
 ```
@@ -183,7 +209,7 @@ $configurator->addStaticParameters([
 Можна також додати динамічні параметри в контейнер. Їхні різні значення, на відміну від статичних параметрів, не призведуть до генерації нових DI-контейнерів.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'remoteIp' => $_SERVER['REMOTE_ADDR'],
 ]);
 ```
@@ -191,7 +217,7 @@ $configurator->addDynamicParameters([
 Змінні середовища можуть бути легко доступні з використанням динамічних параметрів. Ми можемо отримати доступ до них через `%env.variable%` у файлах конфігурації.
 
 ```php
-$configurator->addDynamicParameters([
+$this->configurator->addDynamicParameters([
 	'env' => getenv(),
 ]);
 ```
@@ -206,6 +232,7 @@ $configurator->addDynamicParameters([
 - `%wwwDir%` - абсолютний шлях до каталогу, в якому знаходиться файл запису `index.php`
 - `%tempDir%` - абсолютний шлях до каталогу для тимчасових файлів
 - `%vendorDir%` - абсолютний шлях до каталогу, куди Composer встановлює бібліотеки
+- `%rootDir%` - абсолютний шлях до кореневого каталогу проекту
 - `%debugMode%` вказує на те, чи перебуває програма у режимі налагодження
 - `%consoleMode%` вказує на те, що запит надійшов через командний рядок
 
@@ -225,7 +252,7 @@ services:
 Створюємо новий екземпляр і вставляємо його в Bootstrap:
 
 ```php
-$configurator->addServices([
+$this->configurator->addServices([
 	'myservice' => new App\Model\MyCustomService('foobar'),
 ]);
 ```
@@ -234,13 +261,21 @@ $configurator->addServices([
 Різні середовища .[#toc-different-environments]
 ===============================================
 
-Не соромтеся налаштувати клас `Bootstrap` відповідно до ваших потреб. Ви можете додавати параметри до методу `boot()` для розділення веб-проєктів, або додавати інші методи, як-от `bootForTests()`, які ініціалізують середовище для модульних тестів, `bootForCli()` для скриптів, що викликаються з командного рядка, і так далі.
+Не соромтеся налаштовувати клас `Bootstrap` відповідно до ваших потреб. Ви можете додати параметри до методу `bootWebApplication()`, щоб розрізняти веб-проекти. Крім того, ви можете додати інші методи, такі як `bootTestEnvironment()` для ініціалізації середовища для модульних тестів, `bootConsoleApplication()` для скриптів, що викликаються з командного рядка, і так далі.
 
 ```php
-public static function bootForTests(): Configurator
+public function bootTestEnvironment(): Nette\DI\Container
+{
+	Tester\Environment::setup(); // Ініціалізація Nette Tester
+	$this->setupContainer();
+	return $this->configurator->createContainer();
+}
+
+public function bootConsoleApplication(): Nette\DI\Container
 {
-	$configurator = self::boot();
-	Tester\Environment::setup(); // Инициализация Nette Tester
-	return $configurator;
+	$this->configurator->setDebugMode(false);
+	$this->initializeEnvironment();
+	$this->setupContainer();
+	return $this->configurator->createContainer();
 }
 ```
diff --git a/application/uk/components.texy b/application/uk/components.texy
index 834fb55a2f..b8b4c592e4 100644
--- a/application/uk/components.texy
+++ b/application/uk/components.texy
@@ -230,6 +230,28 @@ $this->redirect(/* ... */); // робимо редирект
 ```
 
 
+Перенаправлення за сигналом .[#toc-redirection-after-a-signal]
+==============================================================
+
+Після обробки сигналу компонента часто відбувається перенаправлення. Ця ситуація схожа на форми - після відправлення форми ми також виконуємо перенаправлення, щоб запобігти повторному відправленню даних при оновленні сторінки в браузері.
+
+```php
+$this->redirect('this') // redirects to the current presenter and action
+```
+
+Оскільки компонент є елементом багаторазового використання і зазвичай не повинен мати прямої залежності від конкретних доповідачів, методи `redirect()` і `link()` автоматично інтерпретують параметр як сигнал компонента:
+
+```php
+$this->redirect('click') // redirects to the 'click' signal of the same component
+```
+
+Якщо вам потрібно перенаправити на іншого доповідача або дію, ви можете зробити це через доповідача:
+
+```php
+$this->getPresenter()->redirect('Product:show'); // redirects to a different presenter/action
+```
+
+
 Постійні параметри .[#toc-persistent-parameters]
 ================================================
 
@@ -347,7 +369,7 @@ services:
 Нарешті, ми будемо використовувати цю фабрику в нашому презентері:
 
 ```php
-class PollPresenter extends Nette\UI\Application\Presenter
+class PollPresenter extends Nette\Application\UI\Presenter
 {
 	public function __construct(
 		private PollControlFactory $pollControlFactory,
@@ -380,7 +402,7 @@ interface PollControlFactory
 Компоненти в Nette Application - це багаторазово використовувані частини веб-додатка, які ми вбудовуємо в сторінки, про що і піде мова в цьому розділі. Які можливості такого компонента?
 
 1) він може бути відображений у шаблоні
-2) він знає, яку частину себе відображати під час [AJAX-запиту |ajax#invalidation] (сніпети)
+2) він знає, [яку частину себе |ajax#snippets] рендерити під час AJAX-запиту (фрагменти)
 3) має можливість зберігати свій стан в URL (постійні параметри)
 4) має можливість реагувати на дії користувача (сигнали)
 5) створює ієрархічну структуру (де коренем є ведучий)
diff --git a/application/uk/configuration.texy b/application/uk/configuration.texy
index 650875ec58..9e34868a04 100644
--- a/application/uk/configuration.texy
+++ b/application/uk/configuration.texy
@@ -13,11 +13,15 @@ application:
 	# відображає вкладку "Nette Application" на синьому екрані Tracy?
 	debugger: ...           # (bool) за замовчуванням true
 
-	# чи буде викликатися презентер помилок у разі помилки?
-	catchExceptions: ...    # (bool) за замовчуванням true на "бойовому" сервері
+	# чи буде викликано error-presenter при помилці?
+	# має ефект тільки в режимі розробника
+	catchExceptions: ...    # (bool) за замовчуванням дорівнює true
 
 	# ім'я презентера помилок
-	errorPresenter: Error   # (string) за замовчуванням 'Nette:Error'
+	errorPresenter: Error   # (string|array) за замовчуванням 'Nette:Error'
+
+	# визначає псевдоніми для доповідачів та подій
+	aliases: ...
 
 	# визначає правила для перетворення імені ведучого в клас
 	mapping: ...
@@ -27,10 +31,19 @@ application:
 	silentLinks: ...        # (bool) за замовчуванням false
 ```
 
-Оскільки в режимі розробки презентери помилок за замовчуванням не викликаються, а помилки відображаються Tracy, зміна значення `catchExceptions` на `true` допомагає перевірити коректність роботи презентерів помилок під час розробки.
+Починаючи з версії 3.2 `nette/application` можна визначити пару презентувальників помилок:
+
+```neon
+application:
+	errorPresenter:
+		4xx: Error4xx   # для виключення Nette\Application\BadRequestException
+		5xx: Error5xx   # для інших винятків
+```
 
 Опція `silentLinks` визначає, як Nette поводиться в режимі розробника, коли генерація посилань не вдається (наприклад, через відсутність презентера тощо). Значення за замовчуванням `false` означає, що Nette запускає `E_USER_WARNING`. Встановлення значення `true` пригнічує це повідомлення про помилку. У виробничому середовищі завжди викликається `E_USER_WARNING`. Ми також можемо вплинути на цю поведінку, встановивши змінну презентера [$invalidLinkMode |creating-links#Invalid-Links].
 
+[Псевдоніми спрощують посилання |creating-links#aliases] на часто використовуваних доповідачів.
+
 Карта [mapping визначає правила |modules#Mapping], за якими ім'я класу виводиться з імені ведучого.
 
 
@@ -82,6 +95,9 @@ latte:
 	# включає [перевірку згенерованого коду |latte:develop#Checking Generated Code]
 	phpLinter: ...       # (string) за замовчуванням null
 
+	# встановлює локаль
+	locale: cs_CZ        # (string) за замовчуванням null
+
 	# клас $this->template
 	templateClass: App\MyTemplateClass # за замовчуванням Nette\Bridges\ApplicationLatte\DefaultTemplate
 ```
@@ -91,7 +107,7 @@ latte:
 ```neon
 latte:
 	расширения:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 /--comment
diff --git a/application/uk/creating-links.texy b/application/uk/creating-links.texy
index 34ec0457fb..5a13a43c77 100644
--- a/application/uk/creating-links.texy
+++ b/application/uk/creating-links.texy
@@ -38,7 +38,7 @@
 <a n:href="Product:show $product->id, lang: en">подробнее</a>
 ```
 
-Якщо метод `ProductPresenter::renderShow()` не має `$lang` у своїй сигнатурі, він може прочитати значення параметра, використовуючи `$lang = $this->getParameter('lang')`.
+Якщо метод `ProductPresenter::renderShow()` не має `$lang` у своїй сигнатурі, він може отримати значення параметра за допомогою `$lang = $this->getParameter('lang')` або з [властивості |presenters#Request Parameters].
 
 Якщо параметри зберігаються в масиві, їх можна розширити за допомогою оператора `(expand)` (щось на зразок оператора `...` у PHP, але працює з асоціативними масивами):
 
@@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 <a n:href="this">обновить</a>
 ```
 
-При цьому передаються всі параметри, зазначені в сигнатурі методу `render<View>()` або `action<Action>()`. Таким чином, якщо ми перебуваємо на сторінках `Product:show` і `id:123`, посилання на `this` також передаватиме цей параметр.
+При цьому всі параметри, зазначені в підписі до файлу `action<Action>()` або `render<View>()` якщо метод `action<Action>()` не визначено, передаються. Отже, якщо ми знаходимося на сторінках `Product:show` і `id:123`, то посилання на `this` також передасть цей параметр.
 
 Звичайно, можна вказати параметри безпосередньо:
 
@@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
 Якщо ми хочемо зробити посилання на презентери в шаблоні компонента, ми використовуємо тег `{plink}`:
 
 ```latte
-<a href="{plink Home:default}">главная страница</a>
+<a href={plink Home:default}>главная страница</a>
 ```
 
 or in the code
@@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default')
 ```
 
 
+Псевдоніми .[#toc-aliases]{data-version:v3.2.2}
+===============================================
+
+Іноді корисно присвоїти парі доповідач:дія псевдонім, який легко запам'ятовується. Наприклад, ви можете назвати домашню сторінку `Front:Home:default` просто як `home` або `Admin:Dashboard:default` як `admin`.
+
+Псевдоніми визначаються у [конфігурації |configuration] за допомогою ключа `application › aliases`:
+
+```neon
+application:
+    aliases:
+        home: Front:Home:default
+        admin: Admin:Dashboard:default
+        sign: Front:Sign:in
+```
+
+У посиланнях вони пишуться за допомогою символу at, наприклад:
+
+```latte
+<a n:href="@admin">administration</a>
+```
+
+Вони підтримуються у всіх методах, які працюють з посиланнями, таких як `redirect()` та подібних.
+
+
 Недійсні посилання .[#toc-invalid-links]
 ========================================
 
diff --git a/application/uk/how-it-works.texy b/application/uk/how-it-works.texy
index 03cb3b413a..12f465f683 100644
--- a/application/uk/how-it-works.texy
+++ b/application/uk/how-it-works.texy
@@ -22,18 +22,18 @@
 /--pre
 <b>web-project/</b>
 ├── <b>app/</b>                      ← каталог с приложением
-│   ├── <b>Presenters/</b>           ← классы презентеров
-│   │   ├── <b>HomePresenter.php</b>  ← Класс презентера главной страницы
-│   │   └── <b>templates/</b>        ← директория шаблонов
-│   │       ├── <b>@layout.latte</b> ← шаблон общего макета
-│   │       └── <b>Home/</b>         ← шаблоны презентера главной страницы
-│   │           └── <b>default.latte</b>  ← шаблон действия `default`
-│   ├── <b>Router/</b>               ← конфигурация URL-адресов
+│   ├── <b>Core/</b>                 ← основні необхідні класи
+│   │   └── <b>RouterFactory.php</b> ← конфігурація URL-адрес
+│   ├── <b>UI/</b>                   ← презентатори, шаблони та інше
+│   │   ├── <b>@layout.latte</b>     ← шаблон спільного макета
+│   │   └── <b>Home/</b>             ← домашній каталог доповідачів
+│   │       ├── <b>HomePresenter.php</b> ← клас головного доповідача
+│   │       └── <b>default.latte</b> ← шаблон дії default
 │   └── <b>Bootstrap.php</b>         ← загрузочный класс Bootstrap
 ├── <b>bin/</b>                      ← скрипты командной строки
 ├── <b>config/</b>                   ← файлы конфигурации
 │   ├── <b>common.neon</b>
-│   └── <b>local.neon</b>
+│   └── <b>services.neon</b>
 ├── <b>log/</b>                      ← журналы ошибок
 ├── <b>temp/</b>                     ← временные файлы, кэш, …
 ├── <b>vendor/</b>                   ← библиотеки, установленные через Composer
@@ -91,7 +91,7 @@ Nette - це наставник, який спрямовує вас до нап
 
 Додаток починає роботу з того, що просить так званий маршрутизатор вирішити, якому з презентерів передати поточний запит на обробку. Маршрутизатор вирішує, чия це відповідальність. Він переглядає вхідний URL `https://example.com/product/123`, який хоче `показать` продукт із `id: 123` як дію. Доброю звичкою є написання пар презентер + дія, розділених двокрапкою: `Продукт:показать`.
 
-Тому маршрутизатор перетворив URL у пару `Presenter:action` + параметри, у нашому випадку `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Router/RouterFactory.php`, і ми детально опишемо його в розділі [Маршрутизація |routing].
+Тому маршрутизатор перетворив URL у пару `Presenter:action` + параметри, у нашому випадку `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Core/RouterFactory.php`, і ми детально опишемо його в розділі [Маршрутизація |routing].
 
 Давайте рухатися далі. Додаток уже знає ім'я презентера і може продовжити роботу. Шляхом створення об'єкта `ProductPresenter`, який є кодом презентера `Product`. Точніше, він просить контейнер DI створити презентера, тому що створення об'єктів - це його робота.
 
@@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Після цього презентер повертає відповідь. Це може бути HTML-сторінка, зображення, XML-документ, надсилання файлу з диска, JSON або перенаправлення на іншу сторінку. Важливо зазначити, що якщо ми явно не вказуємо, як реагувати (що має місце у випадку з `ProductPresenter`), відповіддю буде відображення шаблону з HTML-сторінкою. Чому? Ну, тому що в 99% випадків ми хочемо відобразити шаблон, тому презентер приймає таку поведінку за замовчуванням і хоче полегшити нашу роботу. Це точка зору Nette.
 
-Нам навіть не потрібно вказувати, який шаблон потрібно вивести, він сам виводить шлях до нього відповідно до простої логіки. У випадку з презентером `Product` і дією `show`, він намагається перевірити, чи існує один із цих файлів шаблонів відносно каталогу, в якому знаходиться клас `ProductPresenter`:
+Нам навіть не потрібно вказувати, який шаблон рендерити; фреймворк сам визначить шлях. У випадку дії `show` він просто намагається завантажити шаблон `show.latte` з каталогу з класом `ProductPresenter`. Він також намагається знайти макет у файлі `@layout.latte` (докладніше про [пошук шаблонів |templates#Template Lookup]).
 
-- `templates/Product/show.latte`
-- `templates/Product.show.latte`
-
-І потім він відображає шаблон. Тепер завдання презентера і всієї програми виконано. Якщо шаблону не існує, буде повернуто сторінку з помилкою 404. Детальніше про презентери ви можете прочитати на сторінці [Презентери |presenters].
+Згодом шаблони візуалізуються. На цьому завдання доповідача і всієї програми завершується, і робота завершується. Якщо шаблон не існує, буде повернута сторінка помилки 404. Ви можете прочитати більше про доповідачів на сторінці [Доповідачі |presenters].
 
 [* request-flow.svg *]
 
@@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 3) маршрутизатор декодує URL як пару `Home:default`
 4) створюється об'єкт `HomePresenter`
 5) викликається метод `renderDefault()` (якщо існує)
-6) шаблон `templates/Home/default.latte` з макетом `templates/@layout.latte` відмальований
+6) шаблон `default.latte` з макетом `@layout.latte` відмальований
 
 
 Можливо, зараз ви зіткнулися з безліччю нових понять, але ми вважаємо, що вони мають сенс. Створювати додатки в Nette - простіше простого.
diff --git a/application/uk/modules.texy b/application/uk/modules.texy
index 5503142028..a9b28a35c7 100644
--- a/application/uk/modules.texy
+++ b/application/uk/modules.texy
@@ -2,29 +2,31 @@
 ******
 
 .[perex]
-У Nette модулі являють собою логічні одиниці, з яких складається додаток. Вони включають ведучі, шаблони, можливо, компоненти та класи моделей.
+Модулі вносять ясність у додатки Nette, полегшуючи поділ на логічні блоки.
 
-Одного компонента для презентаторів і одного для шаблонів буде недостатньо для реальних проектів. Наявність десятків файлів в одній папці щонайменше неорганізована. Як вийти з цього становища? Ми просто розділяємо їх на підкаталоги на диску і на простори імен у коді. І це саме те, що роблять модулі Nette.
-
-Тому давайте забудемо про єдину папку для ведучих і шаблонів і натомість створимо модулі, наприклад, `Admin` і `Front`.
+Подібно до організації файлів у папки на жорсткому диску, в Nette ми можемо розділити презентатори, шаблони та інші допоміжні класи на модулі. Як це працює на практиці? Просто додаванням нових підкаталогів до структури. Ось приклад структури з двома модулями, Front і Admin:
 
 /--pre
-<b>app/</b>
-├── <del>Presenters/</del>
-├── <b>Modules/</b>              ← директория с модулями
-│   ├── <b>Admin/</b>            ← модуль Admin
-│   │   ├── <b>Presenters/</b>   ← его презентеры
-│   │   │   ├── <b>DashboardPresenter.php</b>
-│   │   │   └── <b>templates/</b>
-│   └── <b>Front/</b>            ← модуль Front
-│       └── <b>Presenters/</b>   ← его презентеры
-│           └── ...
+app/
+├── UI/
+│   ├── <b>Admin/</b>            ← Admin module
+│   │   ├── @layout.latte
+│   │   ├── Dashboard/
+│   │   │   ├── DashboardPresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
+│   ├── <b>Front/</b>            ← Front module
+│   │   ├── @layout.latte
+│   │   ├── Home/
+│   │   │   ├── HomePresenter.php
+│   │   │   └── default.latte
+│   │   └── ...
 \--
 
-Ця структура каталогів буде відображена в просторах імен класів, так, наприклад, `DashboardPresenter` буде знаходитися в просторі `App\Modules\Admin\Presenters`:
+Ця структура каталогів відображається в просторах імен класів, тому, наприклад, `DashboardPresenter` знаходиться в просторі імен `App\UI\Admin\Dashboard`:
 
 ```php
-namespace App\Modules\Admin\Presenters;
+namespace App\UI\Admin\Dashboard;
 
 class DashboardPresenter extends Nette\Application\UI\Presenter
 {
@@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Ведучий `Dashboard` усередині модуля `Admin` позначається в додатку за допомогою подвійної точкової нотації як `Admin:Dashboard`, а його дія `default` позначається як `Admin:Dashboard:default`.
-А звідки Nette знає, що `Admin:Dashboard` представляє клас `App\Modules\Admin\Presenters\DashboardPresenter`? Ми говоримо про це, використовуючи [відображення |#Mapping] в конфігурації.
-Таким чином, наведена структура не є фіксованою, і ви можете змінювати її на свій розсуд.
+У програмі ми звертаємось до доповідача `Dashboard` у модулі `Admin`, використовуючи двокрапку, як `Admin:Dashboard`. Для його дії `default` ми звертаємось до нього як `Admin:Dashboard:default`.
+
+Представлена структура не є жорсткою; ви можете [повністю налаштувати її відповідно до ваших потреб |#mapping] у конфігурації. .[tip]
 
-Модулі, звісно, можуть містити всі інші частини, крім презентаторів і шаблонів, такі як компоненти, класи моделей тощо.
+Модулі можуть включати всі інші файли, такі як компоненти і допоміжні класи, на додаток до презентаторів і шаблонів. Якщо ви обмірковуєте, де їх розмістити, розгляньте можливість використання папки `Accessory`:
+
+/--pre
+app/
+├── UI/
+│   ├── Admin/
+│   │   ├── <b>Accessory/</b>
+│   │   │   ├── FormFactory.php
+│   │   │   └── AdminLayout.php
+│   │   ├── Dashboard/
+│   │   └── ...
+\--
 
 
 Вкладені модулі .[#toc-nested-modules]
 --------------------------------------
 
-Модулі не обов'язково повинні формувати тільки плоску структуру, ви також можете створювати, наприклад, підмодулі:
+Модулі можуть мати кілька рівнів вкладеності, подібно до структури каталогів на диску:
 
 /--pre
-<b>app/</b>
-├── <b>Modules/</b>              ← директория с модулями
-│   ├── <b>Blog/</b>             ← модуль Blog
-│   │   ├── <b>Admin/</b>        ← подмодуль Admin
-│   │   │   ├── <b>Presenters/</b>
+app/
+├── UI/
+│   ├── <b>Blog/</b>             ← Blog module
+│   │   ├── <b>Admin/</b>        ← Admin submodule
+│   │   │   ├── Dashboard/
+│   │   │   └── ...
+│   │   ├── <b>Front/</b>        ← Front submodule
+│   │   │   ├── @layout.latte
+│   │   │   ├── Home/
 │   │   │   └── ...
-│   │   └── <b>Front/</b>        ← подмодуль Front
-│   │       ├── <b>Presenters/</b>
-│   │       └── ...
-│   ├── <b>Forum/</b>            ← модуль Forum
+│   ├── <b>Forum/</b>            ← Forum module
 │   │   └── ...
 \--
 
-Таким чином, модуль `Blog` розбивається на підмодулі `Admin` і `Front`. І знову ж таки це буде відображено в просторах імен, які будуть `App\Modules\Blog\Admin\Presenters` тощо. Ведучий `Dashboard` всередині підмодуля називається `Blog:Admin:Dashboard`.
+Модуль `Blog` поділяється на підмодулі `Admin` і `Front`. Це також відображається у просторах імен, які потім з'являються як `App\UI\Blog\Admin` і подібним чином. Щоб звернутися до доповідача `Dashboard` у підмодулі `Admin`, ми посилаємося на нього як `Blog:Admin:Dashboard`.
+
+Вкладеність може бути настільки глибокою, наскільки це необхідно, що дозволяє створювати підмодулі.
 
-Розгалуження може бути настільки глибоким, наскільки ви захочете, тому ви можете створювати підмодулі.
+Наприклад, якщо в адмініструванні ви маєте багато доповідачів, пов'язаних з управлінням замовленнями, таких як `OrderDetail`, `OrderEdit`, `OrderDispatch` і т.д., ви можете створити модуль `Order`, в якому будуть організовані доповідачі `Detail`, `Edit`, `Dispatch` та інші.
 
 
 Створення посилань .[#toc-creating-links]
@@ -99,50 +115,69 @@ class DashboardPresenter extends Nette\Application\UI\Presenter
 Див. [розділ про маршрутизацію |routing#modules].
 
 
-Складання карти .[#toc-mapping]
+Картографування .[#toc-mapping]
 -------------------------------
 
-Визначає правила, за якими ім'я класу виводиться з імені ведучого. Ми записуємо їх у [конфігурацію |configuration] під ключем `application › mapping`.
+Відображення визначає правила отримання імені класу з імені доповідача. Ці правила задаються у [конфігурації |configuration] під ключем `application › mapping`.
 
-Почнемо з прикладу, в якому не використовуються модулі. Ми просто хочемо, щоб класи ведучого мали простір імен `App\Presenters`. Тобто ми хочемо, щоб ведучий, наприклад, `Home` відображався на клас `App\Presenters\HomePresenter`. Цього можна досягти за допомогою такої конфігурації:
+Структури каталогів, згадані раніше на цій сторінці, базуються на наступному відображенні:
 
 ```neon
 application:
-	mapping:
-		*: App\Presenters\*Presenter
+	mapping: App\UI\*\**Presenter
 ```
 
-Ім'я презентера замінюється зірочкою, і в результаті виходить назва класу. Легко!
+Як працює мапування? Для кращого розуміння, давайте спочатку уявимо додаток без модулів. Ми хочемо, щоб класи доповідача потрапляли до простору імен `App\UI`, щоб доповідач `Home` відображався у клас `App\UI\HomePresenter`. Цього можна досягти за допомогою такої конфігурації:
 
-Якщо ми розділимо доповідачів на модулі, то для кожного модуля в нас може бути свій маппінг:
+```neon
+application:
+	mapping: App\UI\*Presenter
+```
+
+Це відображення працює шляхом заміни зірочки у масці `App\UI\*Presenter` на ім'я доповідача `Home`, в результаті чого ми отримаємо кінцеве ім'я класу `App\UI\HomePresenter`. Все просто!
+
+Однак, як ви можете бачити у прикладах у цій та інших главах, ми розміщуємо класи доповідачів у однойменних підкаталогах, наприклад, доповідач `Home` зіставляється з класом `App\UI\Home\HomePresenter`. Це досягається за допомогою подвоєння зірочки (потрібно Nette Application 3.2):
+
+```neon
+application:
+	mapping: App\UI\**Presenter
+```
+
+Тепер перейдемо до зіставлення доповідачів з модулями. Для кожного модуля ми можемо визначити специфічні відображення:
 
 ```neon
 application:
 	mapping:
-		Front: App\Modules\Front\Presenters\*Presenter
-		Admin: App\Modules\Admin\Presenters\*Presenter
+		Front: App\UI\Front\**Presenter
+		Admin: App\UI\Admin\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Тепер презентер `Front:Home` визначається класом `App\Modules\Front\HomePresenter`, а презентер `Admin:Dashboard` ` - `App\AdminModule\DashboardPresenter`.
+Згідно з цією конфігурацією, доповідач `Front:Home` зіставляється з класом `App\UI\Front\Home\HomePresenter`, а доповідач `Api:OAuth` зіставляється з класом `App\Api\OAuthPresenter`.
 
-Зручніше буде створити загальне правило (зірочка), яке замінить перші два правила і додасть додаткову зірочку тільки для модуля:
+Оскільки модулі `Front` і `Admin` мають подібний підхід до зіставлення і таких модулів, ймовірно, буде більше, можна створити загальне правило, яке замінить їх. До маски класу буде додано нову зірочку для модуля:
 
 ```neon
 application:
 	mapping:
-		*: App\Modules\*\Presenters\*Presenter
+		*: App\UI\*\**Presenter
 		Api: App\Api\*Presenter
 ```
 
-Але що якщо ми використовуємо кілька вкладених модулів і в нас є, наприклад, провідний `Admin:User:Edit`? У цьому випадку сегмент із зірочкою, що представляє модуль для кожного рівня, буде просто повторюватися, і результатом буде клас `App\Modules\Admin\User\Presenters\EditPresenter`.
+Для багаторівневих вкладених модулів, таких як доповідач `Admin:User:Edit`, сегмент зірочки повторюється для кожного рівня, в результаті чого утворюється клас `App\UI\Admin\User\Edit\EditPresenter`.
 
-Альтернативною нотацією є використання масиву, що складається з трьох сегментів, замість рядка. Ця нотація еквівалентна попередній:
+Альтернативним варіантом запису є використання масиву, що складається з трьох сегментів, замість рядка. Цей запис еквівалентний попередньому:
 
 ```neon
 application:
 	mapping:
-		*: [App\Modules, *, Presenters\*Presenter]
+		*: [App\UI, *, **Presenter]
+		Api: [App\Api, '', *Presenter]
 ```
 
-Значення за замовчуванням - `*: *Module\*Presenter`.
+Якщо в конфігурації є лише одне правило, загальне, ми можемо написати його коротко:
+
+```neon
+application:
+	mapping: App\UI\*\**Presenter
+```
diff --git a/application/uk/presenters.texy b/application/uk/presenters.texy
index 1f81ec0dbf..47e3d7b0c0 100644
--- a/application/uk/presenters.texy
+++ b/application/uk/presenters.texy
@@ -60,7 +60,7 @@ class ArticlePresenter extends Nette\Application\UI\Presenter
 
 Важливо, що `action<Action>()` викликається перед `render<View>()`, тому всередині нього ми можемо, можливо, змінити наступний хід життєвого циклу, тобто змінити шаблон, який буде відображатися, а також метод `render<View>()`, який буде викликатися, використовуючи `setView('otherView')`.
 
-У метод передаються параметри із запиту. Можна і рекомендується вказувати типи для параметрів, наприклад `actionShow(int $id, string $slug = null)` - якщо параметр `id` відсутній або якщо він не є цілим числом, презентер повертає [помилку 404 |#Error-404-etc] і завершує операцію.
+У метод передаються параметри із запиту. Можна і рекомендується вказувати типи для параметрів, наприклад `actionShow(int $id, ?string $slug = null)` - якщо параметр `id` відсутній або якщо він не є цілим числом, презентер повертає [помилку 404 |#Error-404-etc] і завершує операцію.
 
 
 `handle<Signal>(args...)` .{toc: handle<Signal>()}
@@ -205,7 +205,7 @@ $this->redirect(/* ... */);
 Помилка 404 тощо. .[#toc-error-404-etc]
 =======================================
 
-Коли ми не можемо виконати запит, тому що, наприклад, стаття, яку ми хочемо відобразити, не існує в базі даних, ми викинемо помилку 404, використовуючи метод `error(string $message = null, int $httpCode = 404)`, який представляє HTTP-помилку 404:
+Коли ми не можемо виконати запит, тому що, наприклад, стаття, яку ми хочемо відобразити, не існує в базі даних, ми викинемо помилку 404, використовуючи метод `error(?string $message = null, int $httpCode = 404)`, який представляє HTTP-помилку 404:
 
 ```php
 public function renderShow(int $id): void
@@ -236,6 +236,32 @@ public function actionData(): void
 ```
 
 
+Параметри запиту .[#toc-request-parameters]
+===========================================
+
+Доповідач, як і кожен компонент, отримує свої параметри з HTTP-запиту. Їх значення можна отримати за допомогою методу `getParameter($name)` або `getParameters()`. Значення є рядками або масивами рядків, по суті, необробленими даними, отриманими безпосередньо з URL-адреси.
+
+Для більшої зручності ми рекомендуємо зробити параметри доступними через властивості. Просто додайте до них анотацію з атрибутом `#[Parameter]` за допомогою атрибута
+
+```php
+use Nette\Application\Attributes\Parameter;  // ця лінія важлива
+
+class HomePresenter extends Nette\Application\UI\Presenter
+{
+	#[Parameter]
+	public string $theme; // має бути публічною
+}
+```
+
+Для властивостей ми рекомендуємо вказувати тип даних (наприклад, `string`). Тоді Nette автоматично перетворить значення на основі цього типу. Значення параметрів також можна [перевірити |#Validation of Parameters].
+
+При створенні посилання ви можете безпосередньо задати значення параметрів:
+
+```latte
+<a n:href="Home:default theme: dark">click</a>
+```
+
+
 Постійні параметри .[#toc-persistent-parameters]
 ================================================
 
@@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 
 Якщо `$this->lang` має значення `'en'`, то посилання, створені за допомогою `link()` або `n:href`, також будуть містити параметр `lang=en`. І коли посилання буде натиснуто, воно знову стане `$this->lang = 'en'`.
 
-Для властивостей рекомендується вказувати тип даних (наприклад, `string`), а також можна вказати значення за замовчуванням. Значення параметрів можна [перевіряти |#Validation of Persistent Parameters].
+Для властивостей рекомендується вказувати тип даних (наприклад, `string`), а також значення за замовчуванням. Значення параметрів можуть бути [перевірені |#Validation of Parameters].
 
 Постійні параметри за замовчуванням передаються між усіма діями даного доповідача. Щоб передати їх між кількома доповідачами, вам також потрібно їх визначити:
 
@@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Того, що ми показали досі в цьому розділі, ймовірно, буде достатньо. Наступні рядки призначені для тих, хто цікавиться презентерами досконально і хоче знати все.
 
 
-Вимоги та параметри .[#toc-requirement-and-parameters]
-------------------------------------------------------
+Перевірка параметрів .[#toc-validation-of-parameters]
+-----------------------------------------------------
 
-Запит, який обробляє доповідач, є об'єктом [api:Nette\Application\Request] і повертається методом доповідача `getRequest()`. Він містить масив параметрів, кожен з яких належить або якомусь з компонентів, або безпосередньо доповідачу (який, власне, теж є компонентом, хоча й особливим). Тож Nette перерозподіляє параметри та передачі між окремими компонентами (та доповідачем) за допомогою виклику методу `loadState(array $params)`. Параметри можна отримати за допомогою методу `getParameters(): array`, окремо за допомогою `getParameter($name)`. Значення параметрів - це рядки або масиви рядків, в основному це необроблені дані, отримані безпосередньо з URL-адреси.
+Значення [параметрів запиту |#request parameters] і [постійних параметрів |#persistent parameters], отриманих з URL-адрес, записуються у властивості методом `loadState()`. Також перевіряється, чи збігається тип даних, вказаний у властивості, інакше буде видано помилку 404 і сторінка не буде відображена.
 
-
-Перевірка постійних параметрів .[#toc-validation-of-persistent-parameters]
---------------------------------------------------------------------------
-
-Значення [постійних параметрів |#persistent parameters], отриманих з URL-адрес, записуються у властивості методом `loadState()`. Також перевіряється, чи збігається тип даних, вказаний у властивості, інакше буде видано помилку 404, і сторінка не буде відображена.
-
-Ніколи не довіряйте сліпо постійним параметрам, оскільки вони можуть бути легко перезаписані користувачем в URL. Наприклад, так ми перевіряємо, чи є `$this->lang` серед підтримуваних мов. Хороший спосіб зробити це - перевизначити метод `loadState()`, згаданий вище:
+Ніколи не довіряйте параметрам наосліп, оскільки вони можуть бути легко переписані користувачем в URL-адресі. Наприклад, так ми перевіряємо, чи є `$this->lang` серед підтримуваних мов. Хороший спосіб зробити це - перевизначити метод `loadState()`, згаданий вище:
 
 ```php
 class ProductPresenter extends Nette\Application\UI\Presenter
@@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Збереження та відновлення запиту .[#toc-save-and-restore-the-request]
 ---------------------------------------------------------------------
 
-Ви можете зберегти поточний запит у сесії або відновити його із сесії та дозволити презентеру виконати його знову. Це корисно, наприклад, коли користувач заповнює форму, а термін дії його логіна закінчується. Щоб не втратити дані, перед перенаправленням на сторінку реєстрації ми зберігаємо поточний запит у сесію за допомогою функції `$reqId = $this->storeRequest()`, яка повертає ідентифікатор у вигляді короткого рядка і передає його як параметр презенту для реєстрації.
+Запит, який обробляє доповідач, є об'єктом [api:Nette\Application\Request] і повертається методом доповідача `getRequest()`.
+
+Ви можете зберегти поточний запит в сеансі або відновити його з сеансу і дозволити ведучому виконати його знову. Це корисно, наприклад, коли користувач заповнив форму, а його логін закінчується. Щоб не втратити дані, перед перенаправленням на сторінку входу, ми зберігаємо поточний запит до сесії за допомогою `$reqId = $this->storeRequest()`, який повертає ідентифікатор у вигляді короткого рядка і передає його як параметр ведучому входу.
 
 Після входу в систему ми викликаємо метод `$this->restoreRequest($reqId)`, який забирає запит у сесії та пересилає його їй. Метод перевіряє, що запит був створений тим самим користувачем, який зараз увійшов у систему. Якщо інший користувач увійшов у систему або ключ недійсний, він нічого не робить, і програма продовжує роботу.
 
@@ -362,7 +384,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter
 Ви також можете викликати канонізацію вручну за допомогою методу `canonicalize()`, який, як і метод `link()`, отримує як аргументи презентера, дії та параметри. Він створює посилання і порівнює його з поточним URL. Якщо вони відрізняються, то відбувається перенаправлення на згенероване посилання.
 
 ```php
-public function actionShow(int $id, string $slug = null): void
+public function actionShow(int $id, ?string $slug = null): void
 {
 	$realSlug = $this->facade->getSlugForId($id);
 	// перенаправляє, якщо $slug відрізняється від $realSlug
@@ -425,6 +447,51 @@ $this->sendResponse(new Responses\CallbackResponse($callback));
 ```
 
 
+Обмеження доступу за допомогою `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2}
+----------------------------------------------------------------------------------------------------------
+
+Атрибут `#[Requires]` надає розширені можливості для обмеження доступу до доповідачів та їхніх методів. Його можна використовувати для визначення HTTP-методів, вимагати AJAX-запитів, обмежувати доступ до одного і того ж джерела та обмежувати доступ лише пересиланням. Атрибут можна застосовувати до класів презентера, а також до окремих методів, таких як `action<Action>()`, `render<View>()`, `handle<Signal>()`та `createComponent<Name>()`.
+
+Ви можете вказати такі обмеження:
+- на HTTP-методи: `#[Requires(methods: ['GET', 'POST'])]`
+- що вимагають AJAX-запиту: `#[Requires(ajax: true)]`
+- доступ тільки з одного джерела: `#[Requires(sameOrigin: true)]`
+- доступ тільки через переадресацію: `#[Requires(forward: true)]`
+- обмеження на певні дії: `#[Requires(actions: 'default')]`
+
+За деталями дивіться [Як використовувати атрибут Requires атрибут |best-practices:attribute-requires].
+
+
+Перевірка методу HTTP .[#toc-http-method-check]
+-----------------------------------------------
+
+У Nette доповідачі автоматично перевіряють HTTP-метод кожного вхідного запиту, головним чином з міркувань безпеки. За замовчуванням дозволені методи `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`.
+
+Якщо ви хочете увімкнути додаткові методи, такі як `OPTIONS`, ви можете використовувати атрибут `#[Requires]` (починаючи з версії Nette Application v3.2):
+
+```php
+#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+У версії 3.1 перевірка виконується в `checkHttpMethod()`, який перевіряє, чи входить вказаний в запиті метод в масив `$presenter->allowedMethods`. Додайте такий метод:
+
+```php
+class MyPresenter extends Nette\Application\UI\Presenter
+{
+    protected function checkHttpMethod(): void
+    {
+        $this->allowedMethods[] = 'OPTIONS';
+        parent::checkHttpMethod();
+    }
+}
+```
+
+Важливо підкреслити, що якщо ви дозволите метод `OPTIONS`, ви також повинні правильно обробляти його у вашому презентері. Цей метод часто використовується як так званий попередній запит, який браузери автоматично надсилають перед самим запитом, коли необхідно визначити, чи дозволений запит з точки зору політики CORS (Cross-Origin Resource Sharing). Якщо ви дозволите цей метод, але не реалізуєте відповідну реакцію, це може призвести до невідповідностей і потенційних проблем з безпекою.
+
+
 Читати далі .[#toc-further-reading]
 ===================================
 
diff --git a/application/uk/routing.texy b/application/uk/routing.texy
index c19046885b..6f1fc532a6 100644
--- a/application/uk/routing.texy
+++ b/application/uk/routing.texy
@@ -216,7 +216,7 @@ $router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */)
 Розширена нотація .[#toc-advanced-notation]
 -------------------------------------------
 
-Другий параметр маршруту, який ми часто пишемо у форматі `Presenter:action`, є абревіатурою, яку ми також можемо написати у вигляді поля, де ми безпосередньо вказуємо значення (за замовчуванням) окремих параметрів:
+Мета маршруту, зазвичай записана у вигляді `Presenter:action`, також може бути виражена за допомогою масиву, який визначає окремі параметри та їхні значення за замовчуванням:
 
 ```php
 $router->addRoute('<presenter>/<action>[/<id \d+>]', [
@@ -225,7 +225,7 @@ $router->addRoute('<presenter>/<action>[/<id \d+>]', [
 ]);
 ```
 
-Або ми можемо використовувати цю форму, зверніть увагу на переписування регулярного виразу перевірки:
+Для більш детальної специфікації можна використовувати ще більш розширену форму, де на додаток до значень за замовчуванням можна задати інші властивості параметрів, наприклад, регулярний вираз перевірки (див. параметр `id` ):
 
 ```php
 use Nette\Routing\Route;
@@ -243,7 +243,7 @@ $router->addRoute('<presenter>/<action>[/<id>]', [
 ]);
 ```
 
-Ці детальніші формати корисні для додавання додаткових метаданих.
+Важливо відзначити, що якщо параметри, визначені в масиві, не включені в маску шляху, їх значення не можуть бути змінені, навіть за допомогою параметрів запиту, зазначених після знака питання в URL-адресі.
 
 
 Фільтри та переклади .[#toc-filters-and-translations]
@@ -477,10 +477,10 @@ $router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
 Інтеграція .[#toc-integration]
 ==============================
 
-Щоб підключити наш маршрутизатор до застосунку, ми повинні повідомити про нього контейнер DI. Найпростіший спосіб - це підготувати фабрику, яка буде створювати об'єкт маршрутизатора, і повідомити конфігурацію контейнера, щоб вона його використовувала. Припустимо, ми напишемо для цього метод `App\Router\RouterFactory::createRouter()`:
+Щоб підключити наш маршрутизатор до застосунку, ми повинні повідомити про нього контейнер DI. Найпростіший спосіб - це підготувати фабрику, яка буде створювати об'єкт маршрутизатора, і повідомити конфігурацію контейнера, щоб вона його використовувала. Припустимо, ми напишемо для цього метод `App\Core\RouterFactory::createRouter()`:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Application\Routers\RouteList;
 
@@ -499,7 +499,7 @@ class RouterFactory
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 ```
 
 Будь-які залежності, такі як підключення до бази даних тощо, передаються методу фабрики як параметри за допомогою [autowiring |dependency-injection:autowiring]:
@@ -663,7 +663,7 @@ $router->addRoute(/* ... */);
 Отже, ми знову додамо метод, який буде створювати, наприклад, маршрутизатор:
 
 ```php
-namespace App\Router;
+namespace App\Core;
 
 use Nette\Routing\RouteList;
 
@@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class);
 Або ми будемо створювати об'єкти безпосередньо:
 
 ```php
-$router = App\Router\RouterFactory::createRouter();
+$router = App\Core\RouterFactory::createRouter();
 $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
 ```
 
diff --git a/application/uk/templates.texy b/application/uk/templates.texy
index 2dc5f8f053..c4ed7aee2b 100644
--- a/application/uk/templates.texy
+++ b/application/uk/templates.texy
@@ -34,35 +34,81 @@ Nette використовує систему шаблонів [Latte |latte:].
 Він визначає блок `content`, який вставляється замість `{include content}` у макеті, а також перевизначає блок `title`, який перезаписує `{block title}` у макеті. Спробуйте уявити собі результат.
 
 
-Пошук шаблонів .[#toc-search-for-templates]
--------------------------------------------
+Пошук шаблонів .[#toc-template-lookup]
+--------------------------------------
 
-Шлях до шаблонів визначається ведучим за допомогою простої логіки. Він спробує перевірити, чи є один із цих файлів, розташований відносно каталогу класу ведучого, де `<Presenter>` це ім'я поточного ведучого, а `<view>` це ім'я поточної події:
+У презентаторах вам не потрібно вказувати, який шаблон має бути відрендерений; фреймворк автоматично визначить шлях, полегшуючи вам кодування.
 
-- `templates/<Presenter>/<view>.latte`
-- `templates/<Presenter>.<view>.latte`
+Якщо ви використовуєте структуру каталогів, де кожен презентер має власний каталог, просто розмістіть шаблон у цьому каталозі під назвою дії (тобто подання). Наприклад, для дії `default` використовуйте шаблон `default.latte`:
 
-Якщо шаблон не буде знайдено, він спробує виконати пошук у каталозі `templates` на один рівень вище, тобто на тому ж рівні, що і каталог з класом presenter.
+/--pre
+app/
+└── UI/
+    └── Home/
+        ├── HomePresenter.php
+        └── <b>default.latte</b>
+\--
 
-Якщо шаблон не буде знайдено і там, у відповідь буде видано [помилку 404 |presenters#Error 404 etc.].
+Якщо ви використовуєте структуру, де доповідачі знаходяться разом в одному каталозі, а шаблони - в папці `templates`, збережіть її або у файлі `<Presenter>.<view>.latte` або `<Presenter>/<view>.latte`:
 
-Ви також можете змінити вигляд за допомогою `$this->setView('jineView')`. Або, замість прямого пошуку, вкажіть ім'я файлу шаблону за допомогою `$this->template->setFile('/path/to/template.latte')`.
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>Home.default.latte</b>  ← 1st variant
+        └── <b>Home/</b>
+            └── <b>default.latte</b>   ← 2nd variant
+\--
+
+Директорію `templates` також можна розмістити на один рівень вище, на тому ж рівні, що і директорію з класами ведучого.
+
+Якщо шаблон не знайдено, доповідач видає [помилку 404 - сторінка не знайдена |presenters#Error 404 etc].
+
+Ви можете змінити вигляд за допомогою `$this->setView('anotherView')`. Також можна безпосередньо вказати файл шаблону за допомогою `$this->template->setFile('/path/to/template.latte')`.
 
 .[note]
-Файли, в яких здійснюється пошук шаблонів, можна змінити, наклавши метод [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], який повертає масив можливих імен файлів.
+Файли, в яких шукаються шаблони, можна змінити, перевизначивши метод [formatTemplateFiles( |api:Nette\Application\UI\Presenter::formatTemplateFiles()]), який повертає масив можливих імен файлів.
+
+
+Пошук шаблонів макетів .[#toc-layout-template-lookup]
+-----------------------------------------------------
+
+Nette також автоматично шукає файл макета.
+
+Якщо ви використовуєте структуру каталогів, де кожен доповідач має власний каталог, розмістіть макет або в папці доповідача, якщо він стосується лише його, або на рівень вище, якщо він є спільним для кількох доповідачів:
+
+/--pre
+app/
+└── UI/
+    ├── <b>@layout.latte</b>           ← common layout
+    └── Home/
+        ├── <b>@layout.latte</b>       ← only for Home presenter
+        ├── HomePresenter.php
+        └── default.latte
+\--
+
+Якщо ви використовуєте структуру, в якій ведучі згруповані в одному каталозі, а шаблони знаходяться в папці `templates`, макет буде знаходитися в наступних місцях:
 
-У цих файлах очікується компонування:
+/--pre
+app/
+└── Presenters/
+    ├── HomePresenter.php
+    └── templates/
+        ├── <b>@layout.latte</b>       ← common layout
+        ├── <b>Home.@layout.latte</b>  ← only for Home, 1st variant
+        └── <b>Home/</b>
+            └── <b>@layout.latte</b>   ← only for Home, 2nd variant
+\--
 
-- `templates/<Presenter>/@<layout>.latte`
-- `templates/<Presenter>.@<layout>.latte`
-- `templates/@<layout>.latte` макет, спільний для кількох доповідачів
+Якщо доповідач знаходиться в [модулі |modules], він також буде шукати далі по дереву каталогів відповідно до вкладеності модуля.
 
-Де `<Presenter>` це ім'я поточного ведучого і `<layout>` це ім'я макета, яке за замовчуванням дорівнює `'layout'`. Ім'я може бути змінено за допомогою `$this->setLayout('jinyLayout')`, тому будуть випробувані файли `@jinyLayout.latte`.
+Назву шаблону можна змінити за допомогою `$this->setLayout('layoutAdmin')` і тоді вона буде очікуватися у файлі `@layoutAdmin.latte`. Ви також можете безпосередньо вказати файл шаблону розкладки за допомогою `$this->setLayout('/path/to/template.latte')`.
 
-Ви також можете безпосередньо вказати ім'я файлу шаблону макета за допомогою `$this->setLayout('/path/to/template.latte')`. Використання `$this->setLayout(false)` відключає відстеження макета.
+Використання `$this->setLayout(false)` або тегу `{layout none}` всередині шаблону вимикає пошук макетів.
 
 .[note]
-Файли, в яких здійснюється пошук шаблонів макета, можна змінити, наклавши метод [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], який повертає масив можливих імен файлів.
+Файли, в яких шукаються шаблони макетів, можна змінити, перевизначивши метод [formatLayoutTemplateFiles( |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()]), який повертає масив можливих імен файлів.
 
 
 Змінні в шаблоні .[#toc-variables-in-the-template]
@@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
 Ви також можете дозволити собі розкіш шепотіти в шаблонах, просто встановіть плагін Latte в PhpStorm і помістіть ім'я класу на початок шаблону, докладнішу інформацію дивіться в статті "Latte: як набирати систему":https://blog.nette.org/uk/latte-yak-koristuvatisya-sistemoyu-tipiv:
 
 ```latte
-{templateType App\Presenters\ArticleTemplate}
+{templateType App\UI\Article\ArticleTemplate}
 ...
 ```
 
@@ -176,7 +222,7 @@ public function beforeRender(): void
 Latte версії 3 пропонує більш просунутий спосіб створення [розширення |latte:creating-extension] для кожного веб-проекту. Ось короткий приклад такого класу:
 
 ```php
-namespace App\Templating;
+namespace App\UI\Accessory;
 
 final class LatteExtension extends Latte\Extension
 {
@@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension
 ```neon
 latte:
 	extensions:
-		- App\Templating\LatteExtension
+		- App\UI\Accessory\LatteExtension
 ```
 
 
@@ -239,7 +285,7 @@ protected function beforeRender(): void
 ```neon
 latte:
 	extensions:
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 Тоді перекладач можна використовувати, наприклад, як фільтр `|translate`, з додатковими параметрами, переданими методу `translate()` (див. `foo, bar`):
diff --git a/best-practices/bg/@home.texy b/best-practices/bg/@home.texy
index c3d00d8610..814ac362f9 100644
--- a/best-practices/bg/@home.texy
+++ b/best-practices/bg/@home.texy
@@ -17,6 +17,8 @@
 - [Как да се върнете към предишна страница |restore-request]
 - [Страница на резултатите от базата данни |Pagination]
 - [Динамични фрагменти |dynamic-snippets]
+- [Как да използвате атрибута #Requires |attribute-requires]
+- [Как да използвате правилно POST връзки |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@
 Обща
 ----
 - [Как да заредим конфигурационен файл |bootstrap:]
+- [Как да пишем микросайтове |microsites]
 - [Защо Nette използва константна нотация PascalCase? |https://blog.nette.org/bg/za-po-malko-kresene-v-koda]
 - [Защо Nette не използва суфикса Interface? |https://blog.nette.org/bg/prefiksite-i-sufiksite-ne-prinadlezat-na-imenata-na-interfejsite]
 - [Съвети за използване на Composer |composer]
 - [Съвети за редактори и инструменти |editors-and-tools]
+- [Въведение в обектно-ориентираното програмиране |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/bg/attribute-requires.texy b/best-practices/bg/attribute-requires.texy
new file mode 100644
index 0000000000..3918ac851d
--- /dev/null
+++ b/best-practices/bg/attribute-requires.texy
@@ -0,0 +1,179 @@
+Как да използвате `#[Requires]` Атрибут
+***************************************
+
+.[perex]
+Когато пишете уеб приложение, често се сблъсквате с необходимостта да ограничите достъпа до определени части на приложението. Може би искате някои заявки да могат да изпращат данни само чрез формуляр (като по този начин се използва методът POST) или да са достъпни само за AJAX повиквания. В Nette Framework 3.2 е въведен нов инструмент, който ви позволява да задавате такива ограничения по елегантен и ясен начин: инструментът `#[Requires]` атрибут.
+
+Атрибутът е специален маркер в PHP, който се добавя преди дефиницията на даден клас или метод. Тъй като по същество това е клас, трябва да включите клаузата use, за да работят следващите примери:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Можете да използвате `#[Requires]` атрибут в самия клас на презентатора и в тези методи:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Последните два метода също се отнасят за компоненти, така че можете да използвате атрибута и при тях.
+
+Ако условията, определени от атрибута, не са изпълнени, се задейства грешка HTTP 4xx.
+
+
+HTTP методи .[#toc-http-methods]
+--------------------------------
+
+Можете да зададете кои HTTP методи (като GET, POST и т.н.) са разрешени за достъп. Например, ако искате да разрешите достъп само чрез изпращане на формуляр, задайте:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Защо трябва да използвате POST вместо GET за действия за промяна на състоянието и как да го направите? [Прочетете ръководството |post-links].
+
+Можете да посочите метод или масив от методи. Специален случай е стойността `'*'`, за да се активират всички методи, което презентаторите не позволяват по подразбиране от [съображения за сигурност |application:presenters#http-method-check].
+
+
+Извиквания AJAX .[#toc-ajax-calls]
+----------------------------------
+
+Ако искате даден презентатор или метод да бъде достъпен само за AJAX заявки, използвайте:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Същият произход .[#toc-same-origin]
+-----------------------------------
+
+За да повишите сигурността, можете да изискате заявката да бъде направена от същия домейн. Това предотвратява [уязвимостта към CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+За `handle<Signal>()` методи, автоматично се изисква достъп от същия домейн. Затова, ако искате да разрешите достъп от всеки домейн, посочете:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Достъп чрез Forward .[#toc-access-via-forward]
+----------------------------------------------
+
+Понякога е полезно да се ограничи достъпът до даден презентатор, така че той да е достъпен само косвено, например чрез методите `forward()` или `switch()` от друг презентатор. По този начин се защитават презентаторите за грешки, за да се предотврати задействането им от URL адрес:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+В практиката често се налага да се маркират определени изгледи, до които може да се получи достъп само въз основа на логика в презентатора. Отново, за да не могат да бъдат отваряни директно:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Специфични действия .[#toc-specific-actions]
+--------------------------------------------
+
+Можете също така да ограничите достъпа до определен код, като например създаване на компонент, само за определени действия в презентатора:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+За едно действие не е необходимо да се пише масив: `#[Requires(actions: 'default')]`
+
+
+Потребителски атрибути .[#toc-custom-attributes]
+------------------------------------------------
+
+Ако искате да използвате `#[Requires]` атрибут с едни и същи настройки, можете да създадете свой собствен атрибут, който ще наследи `#[Requires]` и да го настроите според нуждите си.
+
+Например, `#[SingleAction]` позволява достъп само чрез действието `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Или `#[RestMethods]` ще позволи достъп чрез всички HTTP методи, използвани за REST API:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Заключение .[#toc-conclusion]
+-----------------------------
+
+На `#[Requires]` ви дава голяма гъвкавост и контрол върху начина, по който се осъществява достъпът до вашите уеб страници. С помощта на прости, но мощни правила можете да повишите сигурността и правилното функциониране на вашето приложение. Както виждате, използването на атрибути в Nette може не само да опрости работата ви, но и да я осигури.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/bg/composer.texy b/best-practices/bg/composer.texy
index b8a26ebb20..2852264f64 100644
--- a/best-practices/bg/composer.texy
+++ b/best-practices/bg/composer.texy
@@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update
 ```
 
 
+Пренебрегване на версията на PHP .[#toc-ignoring-php-version]
+=============================================================
+
+Пакетите обикновено посочват както най-ниската версия на PHP, с която са съвместими, така и най-високата версия, с която са тествани. Ако планирате да използвате още по-нова версия на PHP, може би за целите на тестването, Composer ще откаже да инсталира такъв пакет. Решението е да използвате опцията `--ignore-platform-req=php+`, която кара Composer да игнорира горните граници на изискваната версия на PHP.
+
+
 Фалшиви доклади .[#toc-false-reports]
 =====================================
 
@@ -183,7 +189,7 @@ Packagist.org - глобално хранилище .[#toc-packagist-org-global-
 
 Впоследствие трябва да стартирате командата `composer dumpautoload` при всяка промяна и да позволите на таблиците на автоматичния модул да се възстановят. Това е изключително неудобно и е много по-добре да оставите тази задача на [RobotLoader |robot-loader:], който върши същата работа автоматично във фонов режим и много по-бързо.
 
-Вторият вариант е да следвате [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Казано по-просто, това е система, в която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, т.е. `App\Router\RouterFactory` се намира в `/path/to/App/Router/RouterFactory.php`. Примерна конфигурация:
+Вторият вариант е да следвате [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Казано по-просто, това е система, в която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, т.е. `App\Core\RouterFactory` се намира в `/path/to/App/Core/RouterFactory.php`. Примерна конфигурация:
 
 ```js
 {
diff --git a/best-practices/bg/dynamic-snippets.texy b/best-practices/bg/dynamic-snippets.texy
index b927d707e4..7b2db16d21 100644
--- a/best-practices/bg/dynamic-snippets.texy
+++ b/best-practices/bg/dynamic-snippets.texy
@@ -35,7 +35,7 @@ public function handleUnlike(int $articleId): void
 Ajaxisation .[#toc-ajaxization]
 ===============================
 
-Сега нека въведем AJAX в това просто приложение. Промяната на класацията на дадена статия не е достатъчно важна, за да изисква HTTP заявка с пренасочване, така че в идеалния случай това трябва да се прави с AJAX във фонов режим. Ще използваме [скрипта на манипулатора от добавките |https://componette.org/vojtech-dobes/nette.ajax.js/] с обичайната конвенция, че връзките AJAX имат CSS клас `ajax`.
+Сега нека въведем AJAX в това просто приложение. Промяната на класацията на дадена статия не е достатъчно важна, за да изисква HTTP заявка с пренасочване, така че в идеалния случай това трябва да се прави с AJAX във фонов режим. Ще използваме [скрипта на манипулатора от добавките |application:ajax#toc-naja] с обичайната конвенция, че връзките AJAX имат CSS клас `ajax`.
 
 Как точно да го направим обаче? Nette предлага 2 начина: метода на динамичните фрагменти и метода на компонентите. И двете имат своите плюсове и минуси, затова ще ги покажем последователно.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ class LikeControl extends Nette\Application\UI\Control
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/bg/form-reuse.texy b/best-practices/bg/form-reuse.texy
index 9470a63875..6e65e1bc8a 100644
--- a/best-practices/bg/form-reuse.texy
+++ b/best-practices/bg/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Много е важно обвързването между класовете `FormFactory` и `EditFormFactory` да се реализира чрез композиция, а не чрез наследяване на обекти:
+Много е важно връзката между класовете `FormFactory` и `EditFormFactory` да се осъществява [чрез композиция |nette:introduction-to-object-oriented-programming#composition], а не [чрез |nette:introduction-to-object-oriented-programming#composition] [наследяване на обекти |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ НЕ! НАСЛЕДСТВОТО НЕ ПРИНАДЛЕЖИ ТУК
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Използването на наследяване в този случай би било напълно непродуктивно. Много бързо ще се сблъскате с проблеми. Например, ако искате да добавите параметри към метода `create()`; PHP ще отчете грешка, че сигнатурата му е различна от тази на родителя.
 Или при предаване на зависимост на класа `EditFormFactory` чрез конструктора. Това би довело до това, което наричаме " [ад на конструкторите" |dependency-injection:passing-dependencies#Constructor hell].
 
-Като цяло е по-добре да се предпочита композицията пред наследяването.
+Като цяло е по-добре да се предпочита [композицията пред наследяването |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Обработка на формуляри .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/bg/lets-create-contact-form.texy b/best-practices/bg/lets-create-contact-form.texy
index b0f3d7ccf6..80a29d0e4e 100644
--- a/best-practices/bg/lets-create-contact-form.texy
+++ b/best-practices/bg/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ class HomePresenter extends Presenter
 Но какво ще стане, ако потребителят не попълни някои полета? В такъв случай трябва да го уведомим, че това е задължително поле. Направихме това с метода `setRequired()`.
 Накрая добавихме и [събитие |nette:glossary#events] `onSuccess`, което се задейства, ако формулярът е изпратен успешно. В нашия случай то извиква метода `contactFormSucceeded`, който се грижи за обработката на изпратения формуляр. След малко ще добавим това към кода.
 
-Нека компонентът `contantForm` бъде визуализиран в шаблона `templates/Home/default.latte`:
+Нека компонентът `contantForm` бъде визуализиран в шаблона `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/bg/microsites.texy b/best-practices/bg/microsites.texy
new file mode 100644
index 0000000000..535babfa3f
--- /dev/null
+++ b/best-practices/bg/microsites.texy
@@ -0,0 +1,63 @@
+Как да пишем микросайтове
+*************************
+
+Представете си, че трябва бързо да създадете малък уебсайт за предстоящо събитие на вашата компания. Той трябва да бъде прост, бърз и без излишни усложнения. Може би си мислите, че такъв малък проект не изисква стабилна рамка. Но какво ще кажете, ако използването на рамката Nette може значително да опрости и ускори този процес?
+
+Дори когато създавате прости уебсайтове, не искате да се отказвате от комфорта. Не искате да изобретявате колелото наново. Чувствайте се свободни да бъдете мързеливи и да се поглезите. Рамката Nette може да се използва отлично и като микрорамка.
+
+Как може да изглежда един такъв микросайт? Например, целият код на уебсайта може да бъде поставен в един файл `index.php` в публичната папка:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// създаване на контейнер DI въз основа на конфигурацията в config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// настройка на маршрутизацията
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// маршрут за URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// разпознаване на езика на браузъра и пренасочване към URL /en или /de и т.н.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// маршрут за URL https://example.com/cs или https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// покажете съответния шаблон, например ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// стартирайте приложението!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Всичко останало ще бъде шаблони, съхранявани в родителската папка `/templates`.
+
+PHP кодът в `index.php` първо настройва [средата |bootstrap:], след това дефинира [маршрути |application:routing#dynamic-routing-with-callbacks] и накрая стартира приложението. Предимството е, че вторият параметър на функцията `addRoute()` може да бъде извикващо се име, което се изпълнява при отваряне на съответната страница.
+
+
+Защо да използвате Nette за микросайтове? .[#toc-why-use-nette-for-microsites]
+------------------------------------------------------------------------------
+
+- Разработчиците, които някога са опитвали [Трейси |tracy:], днес не могат да си представят кодирането без него.
+- Но преди всичко ще използвате системата за шаблониране [Latte |latte:], защото само от 2 страници ще искате да разделите [оформлението и съдържанието |latte:template-inheritance].
+- И със сигурност искате да разчитате на [автоматичното ескапиране, |latte:safety-first] за да предотвратите XSS уязвимости.
+- Nette също така гарантира, че в случай на грешка никога няма да бъдат показвани съобщения за грешка на PHP, а вместо това ще бъде показана удобна за потребителя страница.
+- Ако искате да получавате обратна връзка от потребителите, например под формата на форма за контакт, можете да добавите и [форми |forms:] и [база данни |database:].
+- Можете също така лесно да [изпратите |mail:] попълнените формуляри [по имейл |mail:].
+- Понякога може да ви е полезно [кеширането |caching:], например при изтегляне и показване на емисии.
+
+В днешната епоха, в която скоростта и ефективността са от ключово значение, е важно да разполагате с инструменти, които ви позволяват да постигате резултати без излишни забавяния. Рамката Nette предлага точно това - бърза разработка, сигурност и широк набор от инструменти като Tracy и Latte, които опростяват процеса. Достатъчно е да инсталирате няколко пакета на Nette и изграждането на такъв микросайт се превръща в лесна задача. И знаете, че няма скрити недостатъци в сигурността.
diff --git a/best-practices/bg/pagination.texy b/best-practices/bg/pagination.texy
index be7883dffc..9d04ddc1b1 100644
--- a/best-practices/bg/pagination.texy
+++ b/best-practices/bg/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 След това въвеждаме класа на модела в презентатора и в метода `render` правим справка за публикуваните статии, които предаваме на шаблона:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-В шаблона се грижим за извеждането на списъка със статии:
+След това шаблонът `default.latte` ще се погрижи за изброяването на статиите:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ class ArticleRepository
 Също така разширяваме метода `render`, за да получим инстанцията Paginator, да я конфигурираме и да изберем желаните статии, които да се показват в шаблона. HomePresenter ще изглежда по следния начин:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Не е необходимо да създаваме Paginator в презентатора, вместо това ще използваме метода на обекта `Selection`, върнат от хранилището:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/bg/post-links.texy b/best-practices/bg/post-links.texy
new file mode 100644
index 0000000000..f9299c9cbe
--- /dev/null
+++ b/best-practices/bg/post-links.texy
@@ -0,0 +1,59 @@
+Как правилно да използвате POST връзки
+**************************************
+
+В уеб приложенията, особено в административните интерфейси, трябва да е основно правило, че действия, променящи състоянието на сървъра, не трябва да се извършват чрез метода HTTP GET. Както подсказва името на метода, GET трябва да се използва само за извличане на данни, а не за тяхната промяна.
+За действия като изтриване на записи е по-подходящо да се използва методът POST. Въпреки че идеалният вариант би бил да се използва методът DELETE, той не може да бъде извикан без JavaScript, поради което исторически се използва POST.
+
+Как да го направим на практика? Използвайте този прост трик. В началото на вашия шаблон създайте помощна форма с идентификатор `postForm`, която след това ще използвате за бутоните за изтриване:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+С тази форма можете да използвате `<button>` вместо класическия `<a>` връзка, която може да бъде визуално променена, за да изглежда като обикновена връзка. Например, CSS рамката Bootstrap предлага класовете `btn btn-link`, които позволяват на бутона да бъде визуално неразличим от другите връзки. Използвайки атрибута `form="postForm"`, ние го свързваме с предварително подготвената форма:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Когато щракнете върху връзката, сега се извиква действието `delete`. За да се гарантира, че заявките се приемат само чрез метода POST и от същия домейн (което е ефективна защита срещу CSRF атаки), използвайте атрибута `#[Requires]` атрибут:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Атрибутът е наличен от версия 3.2 на Nette Application и можете да научите повече за възможностите му на страницата [Как да използваме атрибута #Requires |attribute-requires].
+
+Ако сте използвали сигнала `handleDelete()` вместо действието `actionDelete()`, не е необходимо да посочвате `sameOrigin: true`, тъй като сигналите имат имплицитно зададена тази защита:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Този подход не само подобрява сигурността на вашето приложение, но и допринася за спазването на правилните уеб стандарти и практики. Чрез използването на POST методи за действия, променящи състоянието, постигате по-стабилно и сигурно приложение.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/bg/presenter-traits.texy b/best-practices/bg/presenter-traits.texy
index 0c4c5e8fed..54d39734cc 100644
--- a/best-practices/bg/presenter-traits.texy
+++ b/best-practices/bg/presenter-traits.texy
@@ -2,7 +2,7 @@
 ****************************
 
 .[perex]
-Ако трябва да приложим един и същ код в няколко презентатора (например проверка дали потребителят е влязъл в системата), изкушаващо е да поставим този код в общ предшественик. Вторият вариант е да се създадат едноцелеви признаци.
+Ако трябва да приложим един и същ код в няколко презентатора (например проверка дали потребителят е влязъл в системата), изкушаващо е да поставим кода в общ предшественик. Втората възможност е да се създадат едноцелеви [черти |nette:introduction-to-object-oriented-programming#traits].
 
 Предимството на това решение е, че всеки презентатор може да използва само чертите, от които действително се нуждае, докато в PHP не е възможно многократно наследяване.
 
diff --git a/best-practices/cs/@home.texy b/best-practices/cs/@home.texy
index 5466d6d7fc..84d96c8a34 100644
--- a/best-practices/cs/@home.texy
+++ b/best-practices/cs/@home.texy
@@ -17,6 +17,8 @@ Nette Aplikace
 - [Jak se vrátit k dřívější stránce |restore-request]
 - [Stránkování výsledků databáze |pagination]
 - [Dynamické snippety |dynamic-snippets]
+- [Jak používat atribut #Requires |attribute-requires]
+- [Jak správně používat POST odkazy |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formuláře
 Obecné
 ------
 - [Jak načíst konfigurační soubor |bootstrap:]
+- [Jak psát mikro-weby |microsites]
 - [Proč Nette používá PascalCase notaci konstant? |https://blog.nette.org/cs/za-mene-kriku-v-kodu]
 - [Proč Nette nepoužívá příponu Interface? |https://blog.nette.org/cs/predpony-a-pripony-do-nazvu-rozhrani-nepatri]
 - [Composer: tipy pro použití |composer]
 - [Tipy na editory & nástroje |editors-and-tools]
+- [Úvod do objektově orientovaného programování |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/cs/attribute-requires.texy b/best-practices/cs/attribute-requires.texy
new file mode 100644
index 0000000000..fdde683a91
--- /dev/null
+++ b/best-practices/cs/attribute-requires.texy
@@ -0,0 +1,179 @@
+Jak používat atribut `#[Requires]`
+**********************************
+
+.[perex]
+Když píšete webovou aplikaci, často se setkáte s potřebou omezit přístup k určitým částem vaší aplikace. Možná chcete, aby některé požadavky mohly odesílat data pouze pomocí formuláře (tedy metodou POST), nebo aby byly přístupné pouze pro AJAXové volání. V Nette Frameworku 3.2 se objevil nový nástroj, který vám umožní taková omezení nastavit velmi elegantně a přehledně: atribut `#[Requires]`.
+
+Atribut je speciální značka v PHP, kterou přidáte před definici třídy nebo metody. Protože jde vlastně o třídu, aby vám následující příklady fungovaly, je nutné uvést klauzuli use:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Atribut `#[Requires]` můžete použít u samotné třídy presenteru a také na těchto metodách:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Poslední dvě metody se týkají i komponent, tedy atribut můžete používat i u nich.
+
+Pokud nejsou splněny podmínky, které atribut uvádí, dojde k vyvolání HTTP chyby 4xx.
+
+
+Metody HTTP
+-----------
+
+Můžete specifikovat, které HTTP metody (jako GET, POST atd.) jsou pro přístup povolené. Například, pokud chcete povolit přístup pouze odesíláním formuláře, nastavíte:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Proč byste měli používat POST místo GET pro akce měnící stav a jak na to? [Přečtěte si návod |post-links].
+
+Můžete uvést metodu nebo pole metod. Speciálním případem je hodnota `'*'`, která povolí všechny metody, což standardně presentery z [bezpečnostních důvodů nedovolují |application:presenters#toc-kontrola-http-metody].
+
+
+AJAXové volání
+--------------
+
+Pokud chcete, aby byl presenter nebo metoda dostupná pouze pro AJAXové požadavky, použijte:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Stejný původ
+------------
+
+Pro zvýšení bezpečnosti můžete vyžadovat, aby byl požadavek učiněn ze stejné domény. Tím zabráníte [zranitelnosti CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+U metod `handle<Signal>()` je přístup ze stejné domény vyžadován automaticky. Takže pokud naopak chcete povolit přístup z jakékoliv domény, uveďte:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Přístup přes forward
+--------------------
+
+Někdy je užitečné omezit přístup k presenteru tak, aby byl dostupný pouze nepřímo, například použitím metody `forward()` nebo `switch()` z jiného presenteru. Takto se třeba chrání error-presentery, aby je nebylo možné vyvolat z URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+V praxi bývá často potřeba označit určité views, ke kterým se lze dostat až na základě logiky v presenteru. Tedy opět, aby je nebylo možné otevřít přímo:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = $this->facade->getProduct($id);
+		if (!$product) {
+			$this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Konkrétní akce
+--------------
+
+Můžete také omezit, že určitý kód, třeba vytvoření komponenty, bude dostupné pouze pro specifické akce v presenteru:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+V případě jedné akce není potřeba zapisovat pole: `#[Requires(actions: 'default')]`
+
+
+Vlastní atributy
+----------------
+
+Pokud chcete použít atribut `#[Requires]` opakovaně s týmž nastavením, můžete si vytvořit vlastní atribut, který bude dědit `#[Requires]` a nastaví ho podle potřeb.
+
+Například `#[SingleAction]` umožní přístup pouze přes akci `default`:
+
+```php
+#[\Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Nebo `#[RestMethods]` umožní přístup přes všechny HTTP metody používané pro REST API:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Závěr
+-----
+
+Atribut `#[Requires]` vám dává velkou flexibilitu a kontrolu nad tím, jak jsou vaše webové stránky přístupné. Pomocí jednoduchých, ale mocných pravidel můžete zvýšit bezpečnost a správné fungování vaší aplikace. Jak vidíte, použití atributů v Nette může vaši práci nejen usnadnit, ale i zabezpečit.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/cs/composer.texy b/best-practices/cs/composer.texy
index 2f0c503870..137b09c745 100644
--- a/best-practices/cs/composer.texy
+++ b/best-practices/cs/composer.texy
@@ -58,7 +58,7 @@ composer update
 
 Composer stáhne Nette Database do složky `vendor/`. Dále vytvoří soubor `composer.lock`, který obsahuje informace o tom, které verze knihoven přesně nainstaloval.
 
-Composer vygeneruje soubor `vendor/autoload.php`, který můžeme jednoduše zainkludovat a začít používat knihovny bez jakékoli další práce:
+Composer vygeneruje soubor `vendor/autoload.php`, který můžeme jednoduše inkludovat a začít používat knihovny bez jakékoli další práce:
 
 ```php
 require __DIR__ . '/vendor/autoload.php';
@@ -142,6 +142,12 @@ Nebo přímo v souboru `composer.json`:
 ```
 
 
+Ignorování verze PHP
+====================
+
+Balíčky zpravidla mívají uvedenou jak nejnižší verzi PHP, se kterou jsou kompatibilní, tak i nejvyšší, se kterou jsou testované. Pokud se chystáte používat verzi PHP ještě novější, třeba z důvodu testování, Composer odmítne takový balíček nainstalovat. Řešením je volba `--ignore-platform-req=php+`, která způsobí, že Composer bude ignorovat horní limity požadované verze PHP.
+
+
 Planá hlášení
 =============
 
@@ -183,7 +189,7 @@ Nicméně je možné používat Composer i pro načítání dalších tříd i m
 
 Následně je potřeba při každé změně spustit příkaz `composer dumpautoload` a nechat autoloadovací tabulky přegenerovat. To je nesmírně nepohodlné a daleko lepší je tento úkol svěřit [RobotLoaderu|robot-loader:], který stejnou činnost provádí automaticky na pozadí a mnohem rychleji.
 
-Druhou možností je dodržovat [PSR-4|https://www.php-fig.org/psr/psr-4/]. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a názvům souborů, tedy např. `App\Router\RouterFactory` bude v souboru `/path/to/App/Router/RouterFactory.php`. Příklad konfigurace:
+Druhou možností je dodržovat [PSR-4|https://www.php-fig.org/psr/psr-4/]. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a názvům souborů, tedy např. `App\Core\RouterFactory` bude v souboru `/path/to/App/Core/RouterFactory.php`. Příklad konfigurace:
 
 ```js
 {
diff --git a/best-practices/cs/dynamic-snippets.texy b/best-practices/cs/dynamic-snippets.texy
index 600dc4b9bd..daf3b00928 100644
--- a/best-practices/cs/dynamic-snippets.texy
+++ b/best-practices/cs/dynamic-snippets.texy
@@ -35,7 +35,7 @@ public function handleUnlike(int $articleId): void
 Ajaxizace
 =========
 
-Pojďme nyní tuto jednoduchou aplikaci vybavit AJAXem. Změna hodnocení článku není natolik důležitá, aby muselo dojít k přesměrování, a proto by ideálně měla probíhat AJAXem na pozadí. Využijeme [obslužného skriptu z doplňků |https://componette.org/vojtech-dobes/nette.ajax.js/] s obvyklou konvencí, že AJAXové odkazy mají CSS třídu `ajax`.
+Pojďme nyní tuto jednoduchou aplikaci vybavit AJAXem. Změna hodnocení článku není natolik důležitá, aby muselo dojít k přesměrování, a proto by ideálně měla probíhat AJAXem na pozadí. Využijeme [obslužného skriptu z doplňků |application:ajax#toc-naja] s obvyklou konvencí, že AJAXové odkazy mají CSS třídu `ajax`.
 
 Nicméně jak na to konkrétně? Nette nabízí 2 cesty: cestu tzv. dynamických snippetů a cestu komponent. Obě dvě mají svá pro a proti, a proto si je ukážeme jednu po druhé.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Samozřejmě se nám změní šablona view a do presenteru budeme muset doplnit
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/cs/form-reuse.texy b/best-practices/cs/form-reuse.texy
index c659b8bcb4..2a6db194db 100644
--- a/best-practices/cs/form-reuse.texy
+++ b/best-practices/cs/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Velmi důležité je, aby vazba mezi třídami `FormFactory` a `EditFormFactory` byla realizována kompozicí, nikoliv objektovou dědičností:
+Velmi důležité je, aby vazba mezi třídami `FormFactory` a `EditFormFactory` byla realizována [kompozicí|nette:introduction-to-object-oriented-programming#kompozice], nikoliv [objektovou dědičností|https://doc.nette.org/cs/introduction-to-object-oriented-programming#dedicnost]:
 
 ```php
 // ⛔ TAKHLE NE! SEM DĚDIČNOST NEPATŘÍ
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Použití dedičnosti by bylo v tomto případě zcela kontraproduktivní. Na problémy byste narazili velmi rychle. Třeba ve chvíli, kdybyste chtěli přidat metodě `create()` parametry; PHP by zahlásilo chybu, že se její signatura liší od rodičovské.
 Nebo při předávání závislosti do třídy `EditFormFactory` přes konstruktor. Nastala by situace, které říkáme [constructor hell |dependency-injection:passing-dependencies#Constructor hell].
 
-Obecně je lepší dávat přednost kompozici před dědičností.
+Obecně je lepší dávat přednost [kompozici před dědičností|dependency-injection:faq#Proč se upřednostňuje kompozice před dědičností].
 
 
 Obsluha formuláře
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/cs/inject-method-attribute.texy b/best-practices/cs/inject-method-attribute.texy
index 9bd667a09f..b3e80f1266 100644
--- a/best-practices/cs/inject-method-attribute.texy
+++ b/best-practices/cs/inject-method-attribute.texy
@@ -61,7 +61,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 
 Výhodou tohoto způsobu předávání závislostí byla velice úsporná podoba zápisu. Nicméně s příchodem [constructor property promotion |https://blog.nette.org/cs/php-8-0-kompletni-prehled-novinek#toc-constructor-property-promotion] se jeví snazší použít konstruktor.
 
-Naopak tento způsob trpí stejnými nedostatky, jako předávání závislosti do properites obecně: nemáme kontrolu nad změnami v proměnné a zároveň se proměnná stává součástí veřejného rozhraní třídy, což je nežádnoucí.
+Naopak tento způsob trpí stejnými nedostatky, jako předávání závislosti do properties obecně: nemáme kontrolu nad změnami v proměnné a zároveň se proměnná stává součástí veřejného rozhraní třídy, což je nežádnoucí.
 
 
 {{sitename: Best Practices}}
diff --git a/best-practices/cs/lets-create-contact-form.texy b/best-practices/cs/lets-create-contact-form.texy
index 78f2f92886..aa24fb819f 100644
--- a/best-practices/cs/lets-create-contact-form.texy
+++ b/best-practices/cs/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Jak vidíte, vytvořili jsme dvě metody. První metoda `createComponentContactF
 Ale co když uživatel nevyplní nějaké pole? V takovém případě bychom mu měli dát vědět, že je to povinné pole. Toho jsme docílili metodou `setRequired()`.
 Nakonec jsme přidali také [událost |nette:glossary#Události] `onSuccess`, která se spustí, pokud je formulář úspěšně odeslán. V našem případě zavolá metodu `contactFormSucceeded`, která se postará o zpracování odeslaného formuláře. To do kódu doplníme za okamžik.
 
-Komponentu `contantForm` necháme vykreslit v šabloně `templates/Home/default.latte`:
+Komponentu `contantForm` necháme vykreslit v šabloně `Home/default.latte`:
 
 ```latte
 {block content}
@@ -131,7 +131,7 @@ Zatím se odesílá prostý textový email obsahující pouze zprávu odeslanou
 </html>
 ```
 
-Zbývá upravit `ContactFacade`, aby tuto šablonu používal. V konstruktoru si vyžádáme třídu `LatteFactory`, která umí vyrobit objekt `Latte\Engine`, tedy [vykreslovač Latte šablon |latte:develop#jak-vykreslit-sablonu]. Pomocí metody `renderToString()` šablonu vykreslíme do souboru, prvním parametrem je cesta k šabloně a druhým jsou proměnné.
+Zbývá upravit `ContactFacade`, aby tuto šablonu používal. V konstruktoru si vyžádáme třídu `LatteFactory`, která umí vyrobit objekt `Latte\Engine`, tedy [vykreslovač Latte šablon |latte:develop#vykresleni-sablony]. Pomocí metody `renderToString()` šablonu vykreslíme do souboru, prvním parametrem je cesta k šabloně a druhým jsou proměnné.
 
 ```php
 namespace App\Model;
diff --git a/best-practices/cs/microsites.texy b/best-practices/cs/microsites.texy
new file mode 100644
index 0000000000..17a9fa7e41
--- /dev/null
+++ b/best-practices/cs/microsites.texy
@@ -0,0 +1,63 @@
+Jak psát mikro-weby
+*******************
+
+Představte si, že potřebujete rychle vytvořit malý web pro nadcházející akci vaší firmy. Má to být jednoduché, rychlé a bez zbytečných komplikací. Možná si myslíte, že pro tak malý projekt nepotřebujete robustní framework. Ale co když použití Nette frameworku může tento proces zásadně zjednodušit a zrychlit?
+
+Přece i při tvorbě jednoduchých webů se nechcete vzdát pohodlí. Nechcete vymýšlet to, co už bylo jednou vyřešené. Buďte klidně líný a nechte se rozmazlovat. Nette Framework lze skvěle využít i jako micro framework.
+
+Jak takový microsite může vypadat? Například tak, že celý kód webu umístíme do jediného souboru `index.php` ve veřejné složce:
+
+```php
+<?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// vytvoř DI kontejner na základě konfigurace v config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// nastavíme routing
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// routa pro URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// detekujeme jazyk prohlížeče a přesměrujeme na URL /en nebo /de atd.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// routa pro URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// zobrazíme příslušnou šablonu, například ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// spusť aplikaci!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Vše ostatní budou šablony uložené v nadřazené složce `/templates`.
+
+PHP kód v `index.php` nejprve [připraví prostředí |bootstrap:], poté definuje [routy|application:routing#dynamicke-routovani-s-callbacky] a nakonec spustí aplikaci. Výhodou je, že druhý parametr funkce `addRoute()` může být callable, který se po otevření odpovídající stránky vykoná.
+
+
+Proč používat Nette pro microsite?
+----------------------------------
+
+- Programátoři, kteří někdy vyzkoušeli [Tracy|tracy:], si dnes neumí představit, že by něco programovali bez ní.
+- Především ale využijete šablonovací systém [Latte|latte:], protože už od 2 stránek budete chtít mít oddělený [layout a obsah|latte:template-inheritance].
+- A rozhodně se chcete spolehout na [automatické escapování |latte:safety-first], aby nevznikla zranitelnost XSS
+- Nette taky zajistí, že se při chybě nikdy neobrazí programátorské chybové hlášky PHP, ale uživateli srozumitelná stránka.
+- Pokud chcete získávat zpětnou vazbu od uživatelů, například v podobě kontaktního formuláře, tak ještě přidáte [formuláře|forms:] a [databázi|database:].
+- Vyplněné formuláře si taktéž můžete nechat snadno [odesílat emailem|mail:].
+- Někdy se vám může hodit [kešování|caching:], například pokud stahujete a zobrazujete feedy.
+
+V dnešní době, kdy je rychlost a efektivita klíčová, je důležité mít nástroje, které vám umožní dosáhnout výsledků bez zbytečného zdržování. Nette framework vám nabízí právě to - rychlý vývoj, bezpečnost a širokou škálu nástrojů, jako je Tracy a Latte, které zjednodušují proces. Stačí nainstalovat pár Nette balíčků a vybudovat takovou microsite je najednou úplná hračka. A víte, že se nikde neskrývá žádná bezpečnostní díra.
diff --git a/best-practices/cs/pagination.texy b/best-practices/cs/pagination.texy
index 46a00cd256..8a558bb0b7 100644
--- a/best-practices/cs/pagination.texy
+++ b/best-practices/cs/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 V presenteru si pak injectujeme modelovou třídu a v render metodě si vyžádáme publikované články, které předáme do šablony:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-V šabloně se pak postaráme o výpis článků:
+V šabloně `default.latte` se pak postaráme o výpis článků:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Následně se pustíme do úprav presenteru. Do render metody budeme předávat
 Dále také render metodu rozšíříme o získání instance Paginatoru, jeho nastavení a výběru správných článků pro zobrazení v šabloně. HomePresenter bude po úpravách vypadat takto:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 V presenteru nemusíme vytvářet Paginator, použijeme místo něj metodu třídy `Selection`, kterou nám vrací repositář:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/cs/post-links.texy b/best-practices/cs/post-links.texy
new file mode 100644
index 0000000000..e82bb4798d
--- /dev/null
+++ b/best-practices/cs/post-links.texy
@@ -0,0 +1,59 @@
+Jak správně používat POST odkazy
+********************************
+
+Ve webových aplikacích, zejména v administrativních rozhraních, by mělo být základním pravidlem, že akce měnící stav serveru by neměly být prováděny prostřednictvím HTTP metody GET. Jak název metody napovídá, GET by měl sloužit pouze k získání dat, nikoli k jejich změně.
+Pro akce jako třeba mazání záznamů je vhodnější použít metodu POST. I když ideální by byla metoda DELETE, ale tu nelze bez JavaScriptu vyvolat, proto se historicky používá POST.
+
+Jak na to v praxi? Využijte tento jednoduchý trik. Na začátku šablony si vytvoříte pomocný formulář s identifikátorem `postForm`, který následně použijete pro mazací tlačítka:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Díky tomuto formuláři můžete místo klasického odkazu `<a>` použít tlačítko `<button>`, které lze vizuálně upravit tak, aby vypadalo jako běžný odkaz. Například CSS framework Bootstrap nabízí třídy `btn btn-link` se kterými dosáhnete toho, že tlačítko nebude vizuálně odlišné od ostatních odkazů. Pomocí atributu `form="postForm"` ho provážeme s předpřipraveným formulářem:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Při kliknutí na odkaz se nyní vyvolá akce `delete`. Pro zajištění, že požadavky budou přijímány pouze prostřednictvím metody POST a z téže domény (což je účinná obrana proti CSRF útokům), použijte atribut `#[Requires]`:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypotetický kód mazající záznam
+		$this->redirect('default');
+	}
+}
+```
+
+Atribut existuje od Nette Application 3.2 a více o jeho možnostech se dozvíte na stránce [Jak používat atribut #Requires |attribute-requires].
+
+Pokud byste místo akce `actionDelete()` používali signál `handleDelete()`, není nutné uvádět `sameOrigin: true`, protože signály mají tuto ochranu nastavenou implicitně:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Tento přístup nejenže zlepšuje bezpečnost vaší aplikace, ale také přispívá k dodržování správných webových standardů a praxe. Využitím metod POST pro akce měnící stav dosáhnete robustnější a bezpečnější aplikace.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/cs/presenter-traits.texy b/best-practices/cs/presenter-traits.texy
index 56c6ba8dfd..06ff9b3063 100644
--- a/best-practices/cs/presenter-traits.texy
+++ b/best-practices/cs/presenter-traits.texy
@@ -2,7 +2,7 @@ Skládání presenterů z trait
 ***************************
 
 .[perex]
-Pokud potřebujeme ve více presenterech implementovat stejný kód (např. ověření, že je uživatel přihlášen), nabízí se umístit kód do společného předka. Druhou možností je vytvoření jednoúčelových trait.
+Pokud potřebujeme ve více presenterech implementovat stejný kód (např. ověření, že je uživatel přihlášen), nabízí se umístit kód do společného předka. Druhou možností je vytvoření jednoúčelových [trait|nette:introduction-to-object-oriented-programming#traity].
 
 Výhoda tohoto řešení je, že každý z presenterů může použít právě ty traity, které skutečně potřebuje, zatímco vícenásobná dědičnost není v PHP možná.
 
diff --git a/best-practices/de/@home.texy b/best-practices/de/@home.texy
index 9a057ba919..4309bbdf91 100644
--- a/best-practices/de/@home.texy
+++ b/best-practices/de/@home.texy
@@ -17,6 +17,8 @@ Nette Bewerbung
 - [Wie man zu einer früheren Seite zurückkehrt |restore-request]
 - [Paginieren von Datenbankergebnissen |Pagination]
 - [Dynamische Schnipsel |dynamic-snippets]
+- [Wie man das Attribut #Requires verwendet |attribute-requires]
+- [Wie man POST-Links richtig verwendet |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formulare
 Allgemein
 ---------
 - [Wie man eine Konfigurationsdatei lädt |bootstrap:]
+- [Wie man Microsites schreibt |microsites]
 - [Warum verwendet Nette die Konstantenschreibweise PascalCase? |https://blog.nette.org/de/fuer-weniger-geschrei-im-code]
 - [Warum verwendet Nette nicht das Suffix Interface? |https://blog.nette.org/de/praefixe-und-suffixe-gehoeren-nicht-in-schnittstellennamen]
 - [Tipps zur Verwendung des Composers |composer]
 - [Tipps zu Editoren und Tools |editors-and-tools]
+- [Einführung in die objektorientierte Programmierung |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/de/attribute-requires.texy b/best-practices/de/attribute-requires.texy
new file mode 100644
index 0000000000..853a90b4f5
--- /dev/null
+++ b/best-practices/de/attribute-requires.texy
@@ -0,0 +1,179 @@
+Wie man das `#[Requires]` Attribut
+**********************************
+
+.[perex]
+Wenn Sie eine Webanwendung schreiben, stoßen Sie häufig auf die Notwendigkeit, den Zugriff auf bestimmte Teile Ihrer Anwendung zu beschränken. Vielleicht möchten Sie, dass einige Anfragen nur Daten über ein Formular senden können (also die POST-Methode verwenden) oder nur für AJAX-Aufrufe zugänglich sind. In Nette Framework 3.2 wurde ein neues Werkzeug eingeführt, mit dem Sie solche Einschränkungen elegant und klar festlegen können: das `#[Requires]` Attribut.
+
+Das Attribut ist eine spezielle Markierung in PHP, die Sie vor der Definition einer Klasse oder Methode hinzufügen. Da es sich im Wesentlichen um eine Klasse handelt, müssen Sie die Use-Klausel einfügen, damit die folgenden Beispiele funktionieren:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Sie können das `#[Requires]` Attribut mit der Presenter-Klasse selbst und mit diesen Methoden verwenden:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Die letzten beiden Methoden betreffen auch Komponenten, so dass Sie das Attribut auch für diese verwenden können.
+
+Wenn die durch das Attribut festgelegten Bedingungen nicht erfüllt sind, wird ein HTTP 4xx-Fehler ausgelöst.
+
+
+HTTP-Methoden .[#toc-http-methods]
+----------------------------------
+
+Sie können angeben, welche HTTP-Methoden (wie GET, POST usw.) für den Zugriff zugelassen sind. Wenn Sie beispielsweise den Zugriff nur durch das Absenden eines Formulars erlauben wollen, legen Sie fest:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Warum sollten Sie POST anstelle von GET für zustandsändernde Aktionen verwenden, und wie geht das? [Lesen Sie den Leitfaden |post-links].
+
+Sie können eine Methode oder eine Reihe von Methoden angeben. Ein Sonderfall ist der Wert `'*'`, um alle Methoden zu aktivieren, was Presenter aus [Sicherheitsgründen |application:presenters#http-method-check] standardmäßig nicht zulassen.
+
+
+AJAX-Aufrufe .[#toc-ajax-calls]
+-------------------------------
+
+Wenn Sie möchten, dass ein Presenter oder eine Methode nur für AJAX-Anfragen zugänglich ist, verwenden Sie:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Gleiche Herkunft .[#toc-same-origin]
+------------------------------------
+
+Um die Sicherheit zu erhöhen, können Sie verlangen, dass die Anfrage von der gleichen Domäne aus gestellt wird. Dies verhindert eine [Anfälligkeit für CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Für `handle<Signal>()` Methoden ist der Zugriff aus derselben Domäne automatisch erforderlich. Wenn Sie also den Zugriff aus einer beliebigen Domäne zulassen wollen, geben Sie dies an:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Zugang über Forward .[#toc-access-via-forward]
+----------------------------------------------
+
+Manchmal ist es sinnvoll, den Zugriff auf einen Präsentator so einzuschränken, dass er nur indirekt verfügbar ist, z. B. über die Methoden `forward()` oder `switch()` eines anderen Präsentators. Auf diese Weise werden Fehlerpräsenter geschützt, um zu verhindern, dass sie von einer URL ausgelöst werden:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+In der Praxis ist es oft notwendig, bestimmte Ansichten zu markieren, auf die nur aufgrund der Logik im Präsentator zugegriffen werden kann. Auch hier gilt, dass sie nicht direkt geöffnet werden können:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Spezifische Aktionen .[#toc-specific-actions]
+---------------------------------------------
+
+Sie können auch einschränken, dass bestimmter Code, wie das Erstellen einer Komponente, nur für bestimmte Aktionen im Präsentator zugänglich ist:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Für eine einzelne Aktion muss kein Array geschrieben werden: `#[Requires(actions: 'default')]`
+
+
+Benutzerdefinierte Attribute .[#toc-custom-attributes]
+------------------------------------------------------
+
+Wenn Sie das Attribut `#[Requires]` Attribut wiederholt mit denselben Einstellungen verwenden möchten, können Sie ein eigenes Attribut erstellen, das die `#[Requires]` erbt, und es nach Ihren Bedürfnissen einstellen.
+
+Zum Beispiel, `#[SingleAction]` erlaubt den Zugriff nur über die Aktion `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Oder `#[RestMethods]` ermöglicht den Zugriff über alle für die REST-API verwendeten HTTP-Methoden:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Schlussfolgerung .[#toc-conclusion]
+-----------------------------------
+
+Das `#[Requires]` Attribut gibt Ihnen große Flexibilität und Kontrolle darüber, wie auf Ihre Webseiten zugegriffen wird. Mit einfachen, aber leistungsfähigen Regeln können Sie die Sicherheit und das ordnungsgemäße Funktionieren Ihrer Anwendung verbessern. Wie Sie sehen, kann die Verwendung von Attributen in Nette Ihre Arbeit nicht nur vereinfachen, sondern auch sichern.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/de/composer.texy b/best-practices/de/composer.texy
index eaaa86a842..10aed8c202 100644
--- a/best-practices/de/composer.texy
+++ b/best-practices/de/composer.texy
@@ -142,6 +142,12 @@ Oder direkt in der Datei "Composer.json":
 ```
 
 
+PHP-Version ignorieren .[#toc-ignoring-php-version]
+===================================================
+
+Pakete geben normalerweise sowohl die niedrigste Version von PHP an, mit der sie kompatibel sind, als auch die höchste Version, mit der sie getestet wurden. Wenn Sie vorhaben, eine noch neuere Version von PHP zu verwenden, etwa zu Testzwecken, wird Composer die Installation eines solchen Pakets verweigern. Die Lösung besteht darin, die Option `--ignore-platform-req=php+` zu verwenden, die Composer veranlasst, die Obergrenzen der erforderlichen PHP-Version zu ignorieren.
+
+
 False Berichte .[#toc-false-reports]
 ====================================
 
@@ -183,7 +189,7 @@ Es ist jedoch auch möglich, Composer zu verwenden, um andere Klassen außerhalb
 
 Anschließend müssen Sie bei jeder Änderung den Befehl `composer dumpautoload` ausführen und die Autoloader-Tabellen neu generieren lassen. Dies ist äußerst lästig, und es ist weitaus besser, diese Aufgabe [RobotLoader |robot-loader:] anzuvertrauen, der dieselbe Tätigkeit automatisch im Hintergrund und viel schneller durchführt.
 
-Die zweite Möglichkeit ist, [PSR-4 |https://www.php-fig.org/psr/psr-4/] zu folgen. Einfach gesagt handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, d. h. `App\Router\RouterFactory` befindet sich in der Datei `/path/to/App/Router/RouterFactory.php`. Beispiel für eine Konfiguration:
+Die zweite Möglichkeit ist, [PSR-4 |https://www.php-fig.org/psr/psr-4/] zu folgen. Einfach gesagt handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, d. h. `App\Core\RouterFactory` befindet sich in der Datei `/path/to/App/Core/RouterFactory.php`. Beispiel für eine Konfiguration:
 
 ```js
 {
diff --git a/best-practices/de/dynamic-snippets.texy b/best-practices/de/dynamic-snippets.texy
index c75affd1e4..e4ac99a50a 100644
--- a/best-practices/de/dynamic-snippets.texy
+++ b/best-practices/de/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Vorlage:
 Ajaxisierung .[#toc-ajaxization]
 ================================
 
-Bringen wir nun AJAX in diese einfache Anwendung. Das Ändern der Bewertung eines Artikels ist nicht wichtig genug, um eine HTTP-Anfrage mit Redirect zu erfordern, also sollte es idealerweise mit AJAX im Hintergrund geschehen. Wir werden das [Handler-Skript aus add-ons |https://componette.org/vojtech-dobes/nette.ajax.js/] verwenden, mit der üblichen Konvention, dass AJAX-Links die CSS-Klasse `ajax` haben.
+Bringen wir nun AJAX in diese einfache Anwendung. Das Ändern der Bewertung eines Artikels ist nicht wichtig genug, um eine HTTP-Anfrage mit Redirect zu erfordern, also sollte es idealerweise mit AJAX im Hintergrund geschehen. Wir werden das [Handler-Skript aus add-ons |application:ajax#toc-naja] verwenden, mit der üblichen Konvention, dass AJAX-Links die CSS-Klasse `ajax` haben.
 
 Aber wie macht man das konkret? Nette bietet 2 Wege an: den dynamischen Snippet-Weg und den Komponenten-Weg. Beide haben ihre Vor- und Nachteile, daher werden wir sie nacheinander vorstellen.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Natürlich werden wir die Ansichtsvorlage ändern und dem Präsentator eine Fabr
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/de/form-reuse.texy b/best-practices/de/form-reuse.texy
index 08cc17d64f..a68bf02309 100644
--- a/best-practices/de/form-reuse.texy
+++ b/best-practices/de/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Es ist sehr wichtig, dass die Bindung zwischen den Klassen `FormFactory` und `EditFormFactory` durch Komposition und nicht durch Objektvererbung implementiert wird:
+Es ist sehr wichtig, dass die Bindung zwischen den Klassen `FormFactory` und `EditFormFactory` [durch Komposition |nette:introduction-to-object-oriented-programming#composition] und nicht [durch |nette:introduction-to-object-oriented-programming#composition] [Objektvererbung |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance] implementiert wird:
 
 ```php
 // ⛔ NEIN! VERERBUNG GEHÖRT HIER NICHT HIN
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Die Verwendung von Vererbung wäre in diesem Fall völlig kontraproduktiv. Sie würden sehr schnell auf Probleme stoßen. Wenn Sie z.B. der Methode `create()` Parameter hinzufügen wollten, würde PHP einen Fehler melden, dass sich die Signatur der Methode von der des Elternteils unterscheidet.
 Oder bei der Übergabe einer Abhängigkeit an die Klasse `EditFormFactory` über den Konstruktor. Dies würde zu dem führen, was wir [Konstruktorhölle |dependency-injection:passing-dependencies#Constructor hell] nennen.
 
-Im Allgemeinen ist es besser, Komposition der Vererbung vorzuziehen.
+Im Allgemeinen ist es besser, die [Komposition der Vererbung |dependency-injection:faq#Why composition is preferred over inheritance] vorzuziehen.
 
 
 Handhabung von Formularen .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/de/lets-create-contact-form.texy b/best-practices/de/lets-create-contact-form.texy
index 67b26710b2..886b452767 100644
--- a/best-practices/de/lets-create-contact-form.texy
+++ b/best-practices/de/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Wie Sie sehen können, haben wir zwei Methoden erstellt. Die erste Methode `crea
 Was aber, wenn der Benutzer einige Felder nicht ausfüllt? In diesem Fall sollten wir ihn darauf hinweisen, dass es sich um ein Pflichtfeld handelt. Wir haben dies mit der Methode `setRequired()` getan.
 Schließlich haben wir auch ein [Ereignis |nette:glossary#events] `onSuccess` hinzugefügt, das ausgelöst wird, wenn das Formular erfolgreich abgeschickt wurde. In unserem Fall ruft es die Methode `contactFormSucceeded` auf, die sich um die Verarbeitung des übermittelten Formulars kümmert. Das fügen wir dem Code gleich hinzu.
 
-Die Komponente `contantForm` soll in der Vorlage `templates/Home/default.latte` gerendert werden:
+Die Komponente `contantForm` soll in der Vorlage `Home/default.latte` gerendert werden:
 
 ```latte
 {block content}
diff --git a/best-practices/de/microsites.texy b/best-practices/de/microsites.texy
new file mode 100644
index 0000000000..f28c89828c
--- /dev/null
+++ b/best-practices/de/microsites.texy
@@ -0,0 +1,63 @@
+Wie man Microsites schreibt
+***************************
+
+Stellen Sie sich vor, Sie müssen schnell eine kleine Website für eine bevorstehende Veranstaltung Ihres Unternehmens erstellen. Sie soll einfach, schnell und ohne unnötige Komplikationen sein. Sie denken vielleicht, dass ein solch kleines Projekt kein robustes Framework benötigt. Aber was wäre, wenn die Verwendung des Nette-Frameworks diesen Prozess erheblich vereinfachen und beschleunigen könnte?
+
+Auch bei der Erstellung einfacher Websites wollen Sie nicht auf Komfort verzichten. Sie wollen das Rad nicht neu erfinden. Seien Sie ruhig faul und gönnen Sie sich etwas. Das Nette Framework lässt sich auch hervorragend als Micro-Framework einsetzen.
+
+Wie könnte eine solche Microsite aussehen? Zum Beispiel kann der gesamte Code der Website in einer einzigen `index.php` Datei im öffentlichen Ordner untergebracht werden:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// einen DI-Container auf der Grundlage der Konfiguration in config.neon erstellen
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// Routing einrichten
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// Route für URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// Erkennung der Browsersprache und Umleitung auf URL /en oder /de usw.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// Route für URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// Anzeige der entsprechenden Vorlage, zum Beispiel ../templates/de.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// Starten Sie die Anwendung!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Alles andere sind Vorlagen, die im übergeordneten Ordner `/templates` gespeichert werden.
+
+Der PHP-Code in `index.php` richtet zunächst [die Umgebung |bootstrap:] ein, definiert dann die [Routen |application:routing#dynamic-routing-with-callbacks] und führt schließlich die Anwendung aus. Der Vorteil ist, dass der zweite Parameter der Funktion `addRoute()` eine Callable sein kann, die ausgeführt wird, wenn die entsprechende Seite geöffnet wird.
+
+
+Warum Nette für Microsites verwenden? .[#toc-why-use-nette-for-microsites]
+--------------------------------------------------------------------------
+
+- Entwickler, die [Tracy |tracy:] einmal ausprobiert haben, können sich heute nicht mehr vorstellen, ohne es zu programmieren.
+- Aber vor allem werden Sie das Templating-System [Latte |latte:] nutzen, denn schon ab 2 Seiten werden Sie [Layout und Inhalt |latte:template-inheritance] trennen wollen.
+- Und Sie wollen sich auf jeden Fall auf das [automatische Escaping |latte:safety-first] verlassen, um XSS-Schwachstellen zu vermeiden.
+- Nette sorgt auch dafür, dass im Falle eines Fehlers niemals PHP-Fehlermeldungen angezeigt werden, sondern eine benutzerfreundliche Seite.
+- Wenn Sie Feedback von den Nutzern erhalten möchten, zum Beispiel in Form eines Kontaktformulars, können Sie auch [Formulare |forms:] und eine [Datenbank |database:] hinzufügen.
+- Sie können ausgefüllte Formulare auch einfach [per E-Mail versch |mail:]icken lassen.
+- In manchen Fällen ist die [Zwischenspeicherung |caching:] nützlich, z. B. beim Herunterladen und Anzeigen von Feeds.
+
+In der heutigen Zeit, in der Geschwindigkeit und Effizienz entscheidend sind, ist es wichtig, über Werkzeuge zu verfügen, die es Ihnen ermöglichen, Ergebnisse ohne unnötige Verzögerungen zu erzielen. Das Nette-Framework bietet genau das - schnelle Entwicklung, Sicherheit und eine breite Palette von Tools wie Tracy und Latte, die den Prozess vereinfachen. Installieren Sie einfach ein paar Nette-Pakete, und die Erstellung einer solchen Microsite wird zum Kinderspiel. Und Sie wissen, dass es keine versteckten Sicherheitslücken gibt.
diff --git a/best-practices/de/pagination.texy b/best-practices/de/pagination.texy
index 5775e52df1..245680368c 100644
--- a/best-practices/de/pagination.texy
+++ b/best-practices/de/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 In den Presenter injizieren wir dann die Modellklasse, und in der Rendering-Methode fragen wir nach den veröffentlichten Artikeln, die wir an die Vorlage übergeben:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-In der Vorlage kümmern wir uns um das Rendern einer Artikelliste:
+Die Vorlage `default.latte` kümmert sich dann um die Auflistung der Artikel:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Der nächste Schritt besteht darin, den Präsentator zu bearbeiten. Wir werden d
 Wir erweitern die Render-Methode auch, um die Paginator-Instanz zu erhalten, sie einzurichten und die richtigen Artikel für die Anzeige in der Vorlage auszuwählen. Der HomePresenter wird wie folgt aussehen:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Wir müssen keinen Paginator im Presenter erstellen, sondern verwenden die Methode des `Selection` -Objekts, das vom Repository zurückgegeben wird:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/de/post-links.texy b/best-practices/de/post-links.texy
new file mode 100644
index 0000000000..13c38839bb
--- /dev/null
+++ b/best-practices/de/post-links.texy
@@ -0,0 +1,59 @@
+Wie man POST-Links richtig verwendet
+************************************
+
+In Webanwendungen, insbesondere in Verwaltungsschnittstellen, sollte es eine Grundregel sein, dass Aktionen, die den Zustand des Servers verändern, nicht über die HTTP-GET-Methode durchgeführt werden sollten. Wie der Name der Methode schon sagt, sollte GET nur zum Abrufen von Daten verwendet werden, nicht zum Ändern.
+Für Aktionen wie das Löschen von Datensätzen ist es angemessener, die POST-Methode zu verwenden. Ideal wäre die Verwendung der DELETE-Methode, die jedoch ohne JavaScript nicht aufgerufen werden kann, weshalb in der Regel POST verwendet wird.
+
+Wie macht man das in der Praxis? Verwenden Sie diesen einfachen Trick. Erstellen Sie am Anfang Ihrer Vorlage ein Hilfsformular mit dem Bezeichner `postForm`, das Sie dann für die Schaltflächen zum Löschen verwenden werden:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Mit diesem Formular können Sie ein `<button>` anstelle des klassischen `<a>` Link verwenden, der visuell so verändert werden kann, dass er wie ein normaler Link aussieht. Das Bootstrap-CSS-Framework bietet zum Beispiel die Klassen `btn btn-link` an, mit denen die Schaltfläche optisch nicht von anderen Links zu unterscheiden ist. Mit dem Attribut `form="postForm"` verknüpfen wir sie mit dem vorbereiteten Formular:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Beim Anklicken des Links wird nun die Aktion `delete` aufgerufen. Um sicherzustellen, dass Anfragen nur über die POST-Methode und von der gleichen Domäne akzeptiert werden (was ein wirksamer Schutz gegen CSRF-Angriffe ist), verwenden Sie das `#[Requires]` Attribut:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Das Attribut ist seit Nette Application 3.2 verfügbar, und Sie können mehr über seine Möglichkeiten auf der Seite [How to use the #Requires attribute |attribute-requires] erfahren.
+
+Wenn Sie das Signal `handleDelete()` anstelle der Aktion `actionDelete()` verwenden, ist es nicht notwendig, `sameOrigin: true` anzugeben, da Signale diesen Schutz implizit gesetzt haben:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Dieser Ansatz verbessert nicht nur die Sicherheit Ihrer Anwendung, sondern trägt auch zur Einhaltung der richtigen Webstandards und -praktiken bei. Durch die Verwendung von POST-Methoden für zustandsändernde Aktionen erreichen Sie eine robustere und sicherere Anwendung.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/de/presenter-traits.texy b/best-practices/de/presenter-traits.texy
index 41b4d98037..807e21e31f 100644
--- a/best-practices/de/presenter-traits.texy
+++ b/best-practices/de/presenter-traits.texy
@@ -2,7 +2,7 @@ Zusammenstellung von Moderatoren aus Merkmalen
 **********************************************
 
 .[perex]
-Wenn wir denselben Code in mehreren Presentern implementieren müssen (z. B. die Überprüfung, ob der Benutzer angemeldet ist), ist es verlockend, den Code in einem gemeinsamen Vorgänger zu platzieren. Die zweite Möglichkeit ist die Erstellung von Single-Purpose-Traits.
+Wenn wir denselben Code in mehreren Presentern implementieren müssen (z. B. die Überprüfung, ob der Benutzer angemeldet ist), ist es verlockend, den Code in einem gemeinsamen Vorgänger zu platzieren. Die zweite Möglichkeit besteht darin, [Einzweck-Traits |nette:introduction-to-object-oriented-programming#traits] zu erstellen.
 
 Der Vorteil dieser Lösung ist, dass jeder Präsentator nur die Traits verwenden kann, die er tatsächlich benötigt, während Mehrfachvererbung in PHP nicht möglich ist.
 
diff --git a/best-practices/el/@home.texy b/best-practices/el/@home.texy
index ba364faa14..48662b32a3 100644
--- a/best-practices/el/@home.texy
+++ b/best-practices/el/@home.texy
@@ -17,6 +17,8 @@
 - [Πώς να επιστρέψετε σε μια προηγούμενη σελίδα|restore-request]
 - [Σελιδοποίηση των αποτελεσμάτων της βάσης δεδομένων |Pagination]
 - [Δυναμικά αποσπάσματα |dynamic-snippets]
+- [Πώς να χρησιμοποιήσετε το χαρακτηριστικό #Requires |attribute-requires]
+- [Πώς να χρησιμοποιείτε σωστά τους συνδέσμους POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@
 Κοινό
 -----
 - [Πώς να φορτώσετε το αρχείο ρυθμίσεων |bootstrap:]
+- [Πώς να γράφετε microsites |microsites]
 - [Γιατί η Nette χρησιμοποιεί τη σημειογραφία σταθερών PascalCase; |https://blog.nette.org/el/gia-ligoteres-krauges-ston-kodika]
 - [Γιατί η Nette δεν χρησιμοποιεί την κατάληξη Interface; |https://blog.nette.org/el/ta-prothemata-kai-ta-epithemata-den-anekoun-sta-onomata-diasyndeses]
 - [Συμβουλές χρήσης του Composer |composer]
 - [Συμβουλές για επεξεργαστές & εργαλεία |editors-and-tools]
+- [Εισαγωγή στον αντικειμενοστραφή προγραμματισμό |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/el/attribute-requires.texy b/best-practices/el/attribute-requires.texy
new file mode 100644
index 0000000000..95d1417ac9
--- /dev/null
+++ b/best-practices/el/attribute-requires.texy
@@ -0,0 +1,179 @@
+Πώς να χρησιμοποιήσετε το `#[Requires]` Attribute
+*************************************************
+
+.[perex]
+Κατά τη συγγραφή μιας εφαρμογής ιστού, συναντάτε συχνά την ανάγκη να περιορίσετε την πρόσβαση σε ορισμένα τμήματα της εφαρμογής σας. Ίσως θέλετε κάποια αιτήματα να μπορούν να στέλνουν δεδομένα μόνο μέσω μιας φόρμας (χρησιμοποιώντας έτσι τη μέθοδο POST) ή να είναι προσβάσιμα μόνο σε κλήσεις AJAX. Στο Nette Framework 3.2, έχει εισαχθεί ένα νέο εργαλείο που σας επιτρέπει να ορίσετε τέτοιους περιορισμούς με κομψότητα και σαφήνεια: το `#[Requires]` χαρακτηριστικό.
+
+Το χαρακτηριστικό είναι ένας ειδικός δείκτης στην PHP, τον οποίο προσθέτετε πριν από τον ορισμό μιας κλάσης ή μεθόδου. Εφόσον πρόκειται ουσιαστικά για μια κλάση, πρέπει να συμπεριλάβετε τη ρήτρα use για να λειτουργήσουν τα παρακάτω παραδείγματα:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Μπορείτε να χρησιμοποιήσετε το `#[Requires]` με την ίδια την κλάση presenter και σε αυτές τις μεθόδους:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Οι δύο τελευταίες μέθοδοι αφορούν επίσης συστατικά, οπότε μπορείτε να χρησιμοποιήσετε το χαρακτηριστικό και με αυτά.
+
+Εάν δεν πληρούνται οι συνθήκες που καθορίζονται από το χαρακτηριστικό, ενεργοποιείται ένα σφάλμα HTTP 4xx.
+
+
+Μέθοδοι HTTP .[#toc-http-methods]
+---------------------------------
+
+Μπορείτε να καθορίσετε ποιες μέθοδοι HTTP (όπως GET, POST κ.λπ.) επιτρέπονται για πρόσβαση. Για παράδειγμα, αν θέλετε να επιτρέψετε την πρόσβαση μόνο με την υποβολή μιας φόρμας, ορίστε:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Γιατί πρέπει να χρησιμοποιείτε POST αντί για GET για ενέργειες αλλαγής κατάστασης και πώς να το κάνετε; [Διαβάστε τον οδηγό |post-links].
+
+Μπορείτε να καθορίσετε μια μέθοδο ή έναν πίνακα μεθόδων. Μια ειδική περίπτωση είναι η τιμή `'*'` για την ενεργοποίηση όλων των μεθόδων, την οποία οι παρουσιαστές δεν επιτρέπουν από προεπιλογή για [λόγους ασφαλείας |application:presenters#http-method-check].
+
+
+Κλήσεις AJAX .[#toc-ajax-calls]
+-------------------------------
+
+Αν θέλετε ένας παρουσιαστής ή μια μέθοδος να είναι προσβάσιμη μόνο για αιτήσεις AJAX, χρησιμοποιήστε:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Ίδια προέλευση .[#toc-same-origin]
+----------------------------------
+
+Για να ενισχύσετε την ασφάλεια, μπορείτε να απαιτήσετε η αίτηση να γίνεται από τον ίδιο τομέα. Αυτό αποτρέπει την [ευπάθεια σε CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Για το `handle<Signal>()` μεθόδους, απαιτείται αυτόματα πρόσβαση από τον ίδιο τομέα. Έτσι, αν θέλετε να επιτρέψετε την πρόσβαση από οποιονδήποτε τομέα, καθορίστε:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Πρόσβαση μέσω Forward .[#toc-access-via-forward]
+------------------------------------------------
+
+Μερικές φορές είναι χρήσιμο να περιορίσετε την πρόσβαση σε έναν παρουσιαστή, ώστε να είναι διαθέσιμος μόνο έμμεσα, για παράδειγμα, χρησιμοποιώντας τις μεθόδους `forward()` ή `switch()` από έναν άλλο παρουσιαστή. Με αυτόν τον τρόπο προστατεύονται οι παρουσιαστές σφαλμάτων, ώστε να μην μπορούν να ενεργοποιηθούν από μια διεύθυνση URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Στην πράξη, είναι συχνά απαραίτητο να επισημαίνονται ορισμένες προβολές στις οποίες μπορεί να γίνει πρόσβαση μόνο με βάση τη λογική του παρουσιαστή. Και πάλι, έτσι ώστε να μην μπορούν να ανοιχτούν απευθείας:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Ειδικές δράσεις .[#toc-specific-actions]
+----------------------------------------
+
+Μπορείτε επίσης να περιορίσετε ότι ορισμένος κώδικας, όπως η δημιουργία ενός στοιχείου, θα είναι προσβάσιμος μόνο για συγκεκριμένες ενέργειες στον παρουσιαστή:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Για μια μεμονωμένη ενέργεια, δεν χρειάζεται να γράψετε έναν πίνακα: `#[Requires(actions: 'default')]`
+
+
+Προσαρμοσμένα χαρακτηριστικά .[#toc-custom-attributes]
+------------------------------------------------------
+
+Αν θέλετε να χρησιμοποιήσετε το `#[Requires]` χαρακτηριστικό επανειλημμένα με τις ίδιες ρυθμίσεις, μπορείτε να δημιουργήσετε το δικό σας χαρακτηριστικό που θα κληρονομεί `#[Requires]` και να το ορίσετε σύμφωνα με τις ανάγκες σας.
+
+Για παράδειγμα, `#[SingleAction]` επιτρέπει την πρόσβαση μόνο μέσω της ενέργειας `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Ή `#[RestMethods]` θα επιτρέψει την πρόσβαση μέσω όλων των μεθόδων HTTP που χρησιμοποιούνται για το REST API:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Συμπέρασμα .[#toc-conclusion]
+-----------------------------
+
+Το `#[Requires]` σας δίνει μεγάλη ευελιξία και έλεγχο στον τρόπο πρόσβασης στις ιστοσελίδες σας. Χρησιμοποιώντας απλούς, αλλά ισχυρούς κανόνες, μπορείτε να ενισχύσετε την ασφάλεια και την ορθή λειτουργία της εφαρμογής σας. Όπως μπορείτε να δείτε, η χρήση χαρακτηριστικών στη Nette μπορεί όχι μόνο να απλοποιήσει την εργασία σας αλλά και να την ασφαλίσει.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/el/composer.texy b/best-practices/el/composer.texy
index 0971df08e3..75f9e3f0bc 100644
--- a/best-practices/el/composer.texy
+++ b/best-practices/el/composer.texy
@@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update
 ```
 
 
+Αγνοώντας την έκδοση PHP .[#toc-ignoring-php-version]
+=====================================================
+
+Τα πακέτα συνήθως καθορίζουν τόσο τη χαμηλότερη έκδοση της PHP με την οποία είναι συμβατά όσο και την υψηλότερη έκδοση με την οποία έχουν δοκιμαστεί. Αν σκοπεύετε να χρησιμοποιήσετε μια ακόμη νεότερη έκδοση της PHP, ίσως για σκοπούς δοκιμής, το Composer θα αρνηθεί να εγκαταστήσει ένα τέτοιο πακέτο. Η λύση είναι να χρησιμοποιήσετε την επιλογή `--ignore-platform-req=php+`, η οποία αναγκάζει το Composer να αγνοήσει τα ανώτερα όρια της απαιτούμενης έκδοσης PHP.
+
+
 Ψευδείς αναφορές .[#toc-false-reports]
 ======================================
 
@@ -183,7 +189,7 @@ Packagist.org - Παγκόσμιο αποθετήριο .[#toc-packagist-org-glo
 
 Στη συνέχεια, είναι απαραίτητο να εκτελείτε την εντολή `composer dumpautoload` με κάθε αλλαγή και να αφήνετε τους πίνακες αυτόματης φόρτωσης να αναγεννώνται. Αυτό είναι εξαιρετικά άβολο και είναι πολύ καλύτερο να αναθέσετε αυτή την εργασία στο [RobotLoader |robot-loader:], το οποίο εκτελεί την ίδια δραστηριότητα αυτόματα στο παρασκήνιο και πολύ πιο γρήγορα.
 
-Η δεύτερη επιλογή είναι να ακολουθήσετε το [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και των ονομάτων των αρχείων, δηλαδή το `App\Router\RouterFactory` βρίσκεται στο αρχείο `/path/to/App/Router/RouterFactory.php`. Παράδειγμα διαμόρφωσης:
+Η δεύτερη επιλογή είναι να ακολουθήσετε το [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και των ονομάτων των αρχείων, δηλαδή το `App\Core\RouterFactory` βρίσκεται στο αρχείο `/path/to/App/Core/RouterFactory.php`. Παράδειγμα διαμόρφωσης:
 
 ```js
 {
diff --git a/best-practices/el/dynamic-snippets.texy b/best-practices/el/dynamic-snippets.texy
index 59031461f0..c75bfa12dd 100644
--- a/best-practices/el/dynamic-snippets.texy
+++ b/best-practices/el/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template:
 Ajaxization .[#toc-ajaxization]
 ===============================
 
-Ας φέρουμε τώρα το AJAX σε αυτή την απλή εφαρμογή. Η αλλαγή της βαθμολογίας ενός άρθρου δεν είναι αρκετά σημαντική ώστε να απαιτεί ένα αίτημα HTTP με ανακατεύθυνση, οπότε ιδανικά θα πρέπει να γίνεται με AJAX στο παρασκήνιο. Θα χρησιμοποιήσουμε το [σενάριο χειρισμού από τα πρόσθετα |https://componette.org/vojtech-dobes/nette.ajax.js/] με τη συνήθη σύμβαση ότι οι σύνδεσμοι AJAX έχουν την κλάση CSS `ajax`.
+Ας φέρουμε τώρα το AJAX σε αυτή την απλή εφαρμογή. Η αλλαγή της βαθμολογίας ενός άρθρου δεν είναι αρκετά σημαντική ώστε να απαιτεί ένα αίτημα HTTP με ανακατεύθυνση, οπότε ιδανικά θα πρέπει να γίνεται με AJAX στο παρασκήνιο. Θα χρησιμοποιήσουμε το [σενάριο χειρισμού από τα πρόσθετα |application:ajax#toc-naja] με τη συνήθη σύμβαση ότι οι σύνδεσμοι AJAX έχουν την κλάση CSS `ajax`.
 
 Ωστόσο, πώς να το κάνουμε συγκεκριμένα; Η Nette προσφέρει 2 τρόπους: τον τρόπο με τα δυναμικά αποσπάσματα και τον τρόπο με τα συστατικά. Και οι δύο έχουν τα πλεονεκτήματα και τα μειονεκτήματά τους, γι' αυτό θα τους παρουσιάσουμε έναν προς έναν.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ class LikeControl extends Nette\Application\UI\Control
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/el/form-reuse.texy b/best-practices/el/form-reuse.texy
index ec91ec79e1..3dc860e4cc 100644
--- a/best-practices/el/form-reuse.texy
+++ b/best-practices/el/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Είναι πολύ σημαντικό ότι η σύνδεση μεταξύ των κλάσεων `FormFactory` και `EditFormFactory` υλοποιείται με σύνθεση και όχι με κληρονομικότητα αντικειμένων:
+Είναι πολύ σημαντικό ότι η σύνδεση μεταξύ των κλάσεων `FormFactory` και `EditFormFactory` υλοποιείται [με σύνθεση |nette:introduction-to-object-oriented-programming#composition] και όχι με [κληρονομικότητα αντικειμένων |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ ΟΧΙ! Η ΚΛΗΡΟΝΟΜΙΆ ΔΕΝ ΑΝΉΚΕΙ ΕΔΏ
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Η χρήση κληρονομικότητας σε αυτή την περίπτωση θα ήταν εντελώς αντιπαραγωγική. Θα αντιμετωπίζατε προβλήματα πολύ γρήγορα. Για παράδειγμα, αν θέλατε να προσθέσετε παραμέτρους στη μέθοδο `create()`, η PHP θα ανέφερε ένα σφάλμα ότι η υπογραφή της ήταν διαφορετική από την υπογραφή του γονέα.
 Ή όταν περνούσατε μια εξάρτηση στην κλάση `EditFormFactory` μέσω του κατασκευαστή. Αυτό θα προκαλούσε αυτό που ονομάζουμε [κόλαση του κατασκευαστή |dependency-injection:passing-dependencies#Constructor hell].
 
-Γενικά, είναι προτιμότερο να προτιμάτε τη σύνθεση από την κληρονομικότητα.
+Είναι γενικά προτιμότερο να προτιμάτε τη [σύνθεση από την κληρονομικότητα |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Χειρισμός φόρμας .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/el/lets-create-contact-form.texy b/best-practices/el/lets-create-contact-form.texy
index aeded4979a..8cf6ab9a9f 100644
--- a/best-practices/el/lets-create-contact-form.texy
+++ b/best-practices/el/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ class HomePresenter extends Presenter
 Τι γίνεται όμως αν ο χρήστης δεν συμπληρώσει κάποια πεδία; Σε αυτή την περίπτωση, θα πρέπει να τον ενημερώσουμε ότι πρόκειται για υποχρεωτικό πεδίο. Αυτό το κάναμε με τη μέθοδο `setRequired()`.
 Τέλος, προσθέσαμε και ένα [συμβάν |nette:glossary#events] `onSuccess`, το οποίο ενεργοποιείται αν η φόρμα υποβληθεί με επιτυχία. Στην περίπτωσή μας, καλεί τη μέθοδο `contactFormSucceeded`, η οποία αναλαμβάνει την επεξεργασία της υποβληθείσας φόρμας. Θα το προσθέσουμε αυτό στον κώδικα σε λίγο.
 
-Αφήστε το στοιχείο `contantForm` να αποδοθεί στο πρότυπο `templates/Home/default.latte`:
+Αφήστε το στοιχείο `contantForm` να αποδοθεί στο πρότυπο `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/el/microsites.texy b/best-practices/el/microsites.texy
new file mode 100644
index 0000000000..b33d0b10fa
--- /dev/null
+++ b/best-practices/el/microsites.texy
@@ -0,0 +1,63 @@
+Πώς να γράψετε Microsites
+*************************
+
+Φανταστείτε ότι πρέπει να δημιουργήσετε γρήγορα έναν μικρό ιστότοπο για μια επερχόμενη εκδήλωση της εταιρείας σας. Θα πρέπει να είναι απλή, γρήγορη και χωρίς περιττές επιπλοκές. Μπορεί να νομίζετε ότι ένα τόσο μικρό έργο δεν απαιτεί ένα ισχυρό πλαίσιο. Τι γίνεται όμως αν η χρήση του πλαισίου Nette μπορεί να απλοποιήσει και να επιταχύνει σημαντικά αυτή τη διαδικασία;
+
+Ακόμα και όταν δημιουργείτε απλές ιστοσελίδες, δεν θέλετε να παραιτηθείτε από την άνεση. Δεν θέλετε να ανακαλύψετε ξανά τον τροχό. Νιώστε ελεύθεροι να είστε τεμπέληδες και να περιποιηθείτε τον εαυτό σας. Το πλαίσιο Nette μπορεί επίσης να χρησιμοποιηθεί άριστα ως μικροπλαίσιο.
+
+Πώς θα μπορούσε να μοιάζει μια τέτοια μικροσελίδα; Για παράδειγμα, ολόκληρος ο κώδικας της ιστοσελίδας μπορεί να τοποθετηθεί σε ένα μόνο αρχείο `index.php` στον δημόσιο φάκελο:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// δημιουργία ενός DI container με βάση τη διαμόρφωση στο config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// να ρυθμίσετε τη δρομολόγηση
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// διαδρομή για τη διεύθυνση URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// ανιχνεύει τη γλώσσα του προγράμματος περιήγησης και ανακατευθύνει στη διεύθυνση URL /en ή /de κ.λπ.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// διαδρομή για τη διεύθυνση URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// εμφάνιση του κατάλληλου προτύπου, για παράδειγμα ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// εκτελέστε την εφαρμογή!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Όλα τα υπόλοιπα θα είναι πρότυπα που θα αποθηκεύονται στον γονικό φάκελο `/templates`.
+
+Ο κώδικας PHP στο `index.php` [ρυθμίζει |bootstrap:] πρώτα [το περιβάλλον |bootstrap:], στη συνέχεια ορίζει τις [διαδρομές |application:routing#dynamic-routing-with-callbacks] και τέλος εκτελεί την εφαρμογή. Το πλεονέκτημα είναι ότι η δεύτερη παράμετρος της συνάρτησης `addRoute()` μπορεί να είναι ένα callable που εκτελείται όταν ανοίγει η αντίστοιχη σελίδα.
+
+
+Γιατί να χρησιμοποιήσετε τη Nette για μικροσελίδες; .[#toc-why-use-nette-for-microsites]
+----------------------------------------------------------------------------------------
+
+- Οι προγραμματιστές που δοκίμασαν ποτέ [το Tracy |tracy:] δεν μπορούν να φανταστούν σήμερα την κωδικοποίηση χωρίς αυτό.
+- Αλλά πάνω απ' όλα, θα αξιοποιήσετε το σύστημα templating [Latte |latte:], επειδή από μόλις 2 σελίδες, θα θέλετε να διαχωρίσετε τη [διάταξη και το περιεχόμενο |latte:template-inheritance].
+- Και σίγουρα θέλετε να βασιστείτε στην [αυτόματη διαφυγή |latte:safety-first] για να αποφύγετε τα τρωτά σημεία XSS.
+- Η Nette διασφαλίζει επίσης ότι σε περίπτωση σφάλματος, δεν θα εμφανίζονται ποτέ μηνύματα σφάλματος PHP, αλλά, αντίθετα, μια φιλική προς τον χρήστη σελίδα.
+- Αν θέλετε να λαμβάνετε σχόλια από τους χρήστες, για παράδειγμα με τη μορφή φόρμας επικοινωνίας, μπορείτε επίσης να προσθέσετε [φόρμες |forms:] και [βάση δεδομένων |database:].
+- Μπορείτε επίσης εύκολα να έχετε συμπληρωμένες φόρμες που [αποστέλλονται μέσω ηλεκτρονικού ταχυδρομείου |mail:].
+- Ορισμένες φορές μπορεί να βρείτε την [προσωρινή αποθήκευση δεδομένων |caching:] χρήσιμη, για παράδειγμα, κατά τη λήψη και την εμφάνιση τροφοδοσιών.
+
+Στη σημερινή εποχή, όπου η ταχύτητα και η αποδοτικότητα είναι το κλειδί, είναι σημαντικό να έχετε εργαλεία που σας επιτρέπουν να επιτυγχάνετε αποτελέσματα χωρίς περιττές καθυστερήσεις. Το πλαίσιο Nette προσφέρει ακριβώς αυτό - γρήγορη ανάπτυξη, ασφάλεια και ένα ευρύ φάσμα εργαλείων όπως το Tracy και το Latte που απλοποιούν τη διαδικασία. Απλά εγκαταστήστε μερικά πακέτα Nette και η κατασκευή ενός τέτοιου microsite γίνεται παιχνιδάκι. Και ξέρετε ότι δεν υπάρχουν κρυφά κενά ασφαλείας.
diff --git a/best-practices/el/pagination.texy b/best-practices/el/pagination.texy
index 3003b38a84..599f3ff25a 100644
--- a/best-practices/el/pagination.texy
+++ b/best-practices/el/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Στον Presenter στη συνέχεια εισάγουμε την κλάση model και στη μέθοδο render θα ζητήσουμε τα δημοσιευμένα άρθρα που θα περάσουμε στο template:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Στο πρότυπο, θα φροντίσουμε για την απόδοση μιας λίστας άρθρων:
+Το πρότυπο `default.latte` θα αναλάβει στη συνέχεια την καταχώριση των άρθρων:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ class ArticleRepository
 Επεκτείνουμε επίσης τη μέθοδο render για να λάβουμε την περίπτωση Paginator, να τη ρυθμίσουμε και να επιλέξουμε τα σωστά άρθρα που θα εμφανίζονται στο πρότυπο. Το HomePresenter θα μοιάζει με αυτό:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Δεν χρειάζεται να δημιουργήσουμε Paginator στο Presenter, αντίθετα θα χρησιμοποιήσουμε τη μέθοδο του αντικειμένου `Selection` που επιστρέφεται από το αποθετήριο:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/el/post-links.texy b/best-practices/el/post-links.texy
new file mode 100644
index 0000000000..634091cf38
--- /dev/null
+++ b/best-practices/el/post-links.texy
@@ -0,0 +1,59 @@
+Πώς να χρησιμοποιείτε σωστά τους συνδέσμους POST
+************************************************
+
+Στις εφαρμογές ιστού, ειδικά στις διαχειριστικές διεπαφές, θα πρέπει να αποτελεί βασικό κανόνα ότι οι ενέργειες που αλλάζουν την κατάσταση του διακομιστή δεν θα πρέπει να εκτελούνται μέσω της μεθόδου HTTP GET. Όπως υποδηλώνει το όνομα της μεθόδου, η GET θα πρέπει να χρησιμοποιείται μόνο για την ανάκτηση δεδομένων και όχι για την αλλαγή τους.
+Για ενέργειες όπως η διαγραφή εγγραφών, είναι καταλληλότερο να χρησιμοποιείται η μέθοδος POST. Αν και το ιδανικό θα ήταν να χρησιμοποιείται η μέθοδος DELETE, αυτή δεν μπορεί να κληθεί χωρίς JavaScript, γι' αυτό και χρησιμοποιείται ιστορικά η μέθοδος POST.
+
+Πώς να το κάνετε στην πράξη; Χρησιμοποιήστε αυτό το απλό τέχνασμα. Στην αρχή του προτύπου σας, δημιουργήστε μια βοηθητική φόρμα με το αναγνωριστικό `postForm`, την οποία στη συνέχεια θα χρησιμοποιήσετε για τα κουμπιά διαγραφής:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Με αυτή τη φόρμα, μπορείτε να χρησιμοποιήσετε ένα `<button>` αντί της κλασικής `<a>` συνδέσμου, ο οποίος μπορεί να τροποποιηθεί οπτικά ώστε να μοιάζει με κανονικό σύνδεσμο. Για παράδειγμα, το πλαίσιο Bootstrap CSS προσφέρει τις κλάσεις `btn btn-link` οι οποίες επιτρέπουν στο κουμπί να είναι οπτικά δυσδιάκριτο από άλλους συνδέσμους. Χρησιμοποιώντας το χαρακτηριστικό `form="postForm"`, το συνδέουμε με την προ-προετοιμασμένη φόρμα:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Όταν κάνετε κλικ στο σύνδεσμο, τώρα καλείται η ενέργεια `delete`. Για να διασφαλίσετε ότι οι αιτήσεις γίνονται δεκτές μόνο μέσω της μεθόδου POST και από τον ίδιο τομέα (κάτι που αποτελεί αποτελεσματική άμυνα κατά των επιθέσεων CSRF), χρησιμοποιήστε το `#[Requires]` attribute:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Το χαρακτηριστικό είναι διαθέσιμο από την έκδοση Nette Application 3.2 και μπορείτε να μάθετε περισσότερα για τις δυνατότητές του στη σελίδα [Πώς να χρησιμοποιήσετε το χαρακτηριστικό #Requires |attribute-requires].
+
+Εάν χρησιμοποιούσατε το σήμα `handleDelete()` αντί της ενέργειας `actionDelete()`, δεν είναι απαραίτητο να καθορίσετε το `sameOrigin: true`, επειδή τα σήματα έχουν θέσει αυτή την προστασία σιωπηρά:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Αυτή η προσέγγιση όχι μόνο βελτιώνει την ασφάλεια της εφαρμογής σας, αλλά συμβάλλει και στην τήρηση των κατάλληλων προτύπων και πρακτικών του διαδικτύου. Χρησιμοποιώντας μεθόδους POST για ενέργειες που αλλάζουν κατάσταση, επιτυγχάνετε μια πιο ισχυρή και ασφαλή εφαρμογή.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/el/presenter-traits.texy b/best-practices/el/presenter-traits.texy
index dcfda68d36..fad19dba1f 100644
--- a/best-practices/el/presenter-traits.texy
+++ b/best-practices/el/presenter-traits.texy
@@ -2,7 +2,7 @@
 ***********************************
 
 .[perex]
-Αν πρέπει να υλοποιήσουμε τον ίδιο κώδικα σε πολλούς παρουσιαστές (π.χ. επαλήθευση ότι ο χρήστης είναι συνδεδεμένος), είναι δελεαστικό να τοποθετήσουμε τον κώδικα σε έναν κοινό πρόγονο. Η δεύτερη επιλογή είναι να δημιουργήσουμε γνωρίσματα ενός σκοπού.
+Εάν πρέπει να υλοποιήσουμε τον ίδιο κώδικα σε πολλούς παρουσιαστές (π.χ. επαλήθευση ότι ο χρήστης είναι συνδεδεμένος), είναι δελεαστικό να τοποθετήσουμε τον κώδικα σε έναν κοινό πρόγονο. Η δεύτερη επιλογή είναι η δημιουργία [χαρακτηριστικών |nette:introduction-to-object-oriented-programming#traits] ενός μόνο σκοπού.
 
 Το πλεονέκτημα αυτής της λύσης είναι ότι κάθε παρουσιαστής μπορεί να χρησιμοποιήσει μόνο τα γνωρίσματα που πραγματικά χρειάζεται, ενώ η πολλαπλή κληρονομικότητα δεν είναι δυνατή στην PHP.
 
diff --git a/best-practices/en/@home.texy b/best-practices/en/@home.texy
index 43f088951b..e2630adeee 100644
--- a/best-practices/en/@home.texy
+++ b/best-practices/en/@home.texy
@@ -17,6 +17,8 @@ Nette Application
 - [How to return to an earlier page |restore-request]
 - [Paginating database results |Pagination]
 - [Dynamic snippets |dynamic-snippets]
+- [How to use #Requires attribute |attribute-requires]
+- [How to properly use POST links |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Forms
 Common
 ------
 - [How to load configuration file |bootstrap:]
+- [How to write microsites |microsites]
 - [Why Nette uses PascalCase constant notation? |https://blog.nette.org/en/for-less-screaming-in-the-code]
 - [Why Nette doesn't use the Interface suffix? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names]
 - [Composer usage tips |composer]
 - [Tips on editors & tools |editors-and-tools]
+- [Introduction to object-oriented programming |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/en/attribute-requires.texy b/best-practices/en/attribute-requires.texy
new file mode 100644
index 0000000000..514355ad79
--- /dev/null
+++ b/best-practices/en/attribute-requires.texy
@@ -0,0 +1,179 @@
+How to Use the `#[Requires]` Attribute
+**************************************
+
+.[perex]
+When writing a web application, you often encounter the need to restrict access to certain parts of your application. Perhaps you want some requests to only be able to send data via a form (thus using the POST method) or to be accessible only to AJAX calls. In Nette Framework 3.2, a new tool has been introduced that allows you to set such restrictions elegantly and clearly: the `#[Requires]` attribute.
+
+The attribute is a special marker in PHP, which you add before the definition of a class or method. Since it is essentially a class, you need to include the use clause to make the following examples work:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+You can use the `#[Requires]` attribute with the presenter class itself and on these methods:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+The last two methods also concern components, so you can use the attribute with them as well.
+
+If the conditions specified by the attribute are not met, an HTTP 4xx error is triggered.
+
+
+HTTP Methods
+------------
+
+You can specify which HTTP methods (such as GET, POST, etc.) are allowed for access. For example, if you want to allow access only by submitting a form, set:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Why should you use POST instead of GET for state changing actions and how to do it? [Read the guide |post-links].
+
+You can specify a method or an array of methods. A special case is the value `'*'` to enable all methods, which presenters do not allow by default for [security reasons |application:presenters#http-method-check].
+
+
+AJAX Calls
+----------
+
+If you want a presenter or method to be accessible only for AJAX requests, use:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Same Origin
+-----------
+
+To enhance security, you can require that the request be made from the same domain. This prevents [vulnerability to CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+For `handle<Signal>()` methods, access from the same domain is automatically required. So, if you want to allow access from any domain, specify:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Access via Forward
+------------------
+
+Sometimes it is useful to restrict access to a presenter so that it is only available indirectly, for example, using the `forward()` or `switch()` methods from another presenter. This is how error-presenters are protected to prevent them from being triggered from a URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+In practice, it is often necessary to mark certain views that can only be accessed based on logic in the presenter. Again, so that they cannot be opened directly:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Specific Actions
+----------------
+
+You can also restrict that certain code, like creating a component, will be accessible only for specific actions in the presenter:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+For a single action, there's no need to write an array: `#[Requires(actions: 'default')]`
+
+
+Custom Attributes
+-----------------
+
+If you want to use the `#[Requires]` attribute repeatedly with the same settings, you can create your own attribute that will inherit `#[Requires]` and set it according to your needs.
+
+For example, `#[SingleAction]` allows access only through the `default` action:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Or `#[RestMethods]` will allow access via all HTTP methods used for the REST API:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Conclusion
+----------
+
+The `#[Requires]` attribute gives you great flexibility and control over how your web pages are accessed. Using simple, yet powerful rules, you can enhance the security and proper functioning of your application. As you can see, using attributes in Nette can not only simplify your work but also secure it.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/en/composer.texy b/best-practices/en/composer.texy
index e87a29b0f7..d8753b98bd 100644
--- a/best-practices/en/composer.texy
+++ b/best-practices/en/composer.texy
@@ -142,6 +142,12 @@ Or directly in the `composer.json` file:
 ```
 
 
+Ignoring PHP Version
+====================
+
+Packages typically specify both the lowest version of PHP with which they are compatible and the highest version with which they have been tested. If you plan to use an even newer version of PHP, perhaps for testing purposes, Composer will refuse to install such a package. The solution is to use the `--ignore-platform-req=php+` option, which causes Composer to ignore the upper limits of the required PHP version.
+
+
 False Reports
 =============
 
@@ -183,7 +189,7 @@ However, it is also possible to use Composer to load other classes outside the f
 
 Subsequently, it is necessary to run the command `composer dumpautoload` with each change and let the autoloading tables regenerate. This is extremely inconvenient, and it is far better to entrust this task to [RobotLoader|robot-loader:], which performs the same activity automatically in the background and much faster.
 
-The second option is to follow [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simply saying, it is a system where the namespaces and class names correspond to the directory structure and file names, ie `App\Router\RouterFactory` is located in the file `/path/to/App/Router/RouterFactory.php`. Configuration example:
+The second option is to follow [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simply saying, it is a system where the namespaces and class names correspond to the directory structure and file names, ie `App\Core\RouterFactory` is located in the file `/path/to/App/Core/RouterFactory.php`. Configuration example:
 
 ```js
 {
diff --git a/best-practices/en/dynamic-snippets.texy b/best-practices/en/dynamic-snippets.texy
index a0e8e09cae..9ec54ca401 100644
--- a/best-practices/en/dynamic-snippets.texy
+++ b/best-practices/en/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template:
 Ajaxization
 ===========
 
-Let's now bring AJAX to this simple application. Changing the rating of an article is not important enough to require a HTTP request with redirect, so ideally it should be done with AJAX in the background. We'll use the [handler script from add-ons |https://componette.org/vojtech-dobes/nette.ajax.js/] with the usual convention that AJAX links have the CSS class `ajax`.
+Let's now bring AJAX to this simple application. Changing the rating of an article is not important enough to require a HTTP request with redirect, so ideally it should be done with AJAX in the background. We'll use the [handler script from add-ons |application:ajax#toc-naja] with the usual convention that AJAX links have the CSS class `ajax`.
 
 However, how to do it specifically? Nette offers 2 ways: the dynamic snippet way and the component way. Both of them have their pros and cons, so we will show them one by one.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Of course we will change the view template and we will have to add a factory to
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/en/form-reuse.texy b/best-practices/en/form-reuse.texy
index 176a6cb783..be53a9d13b 100644
--- a/best-practices/en/form-reuse.texy
+++ b/best-practices/en/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-It is very important that the binding between the `FormFactory` and `EditFormFactory` classes is implemented by composition, not object inheritance:
+It is very important that the binding between the `FormFactory` and `EditFormFactory` classes is implemented [by composition |nette:introduction-to-object-oriented-programming#composition], not [object inheritance |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ NO! INHERITANCE DOESN'T BELONG HERE
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Using inheritance in this case would be completely counterproductive. You would run into problems very quickly. For example, if you wanted to add parameters to the `create()` method; PHP would report an error that its signature was different from the parent.
 Or when passing a dependency to the `EditFormFactory` class via the constructor. This would cause what we call [constructor hell |dependency-injection:passing-dependencies#Constructor hell].
 
-In general, it is better to prefer composition over inheritance.
+It is generally better to prefer [composition over inheritance |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Form Handling
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/en/lets-create-contact-form.texy b/best-practices/en/lets-create-contact-form.texy
index ad2472ed15..f00cad1b75 100644
--- a/best-practices/en/lets-create-contact-form.texy
+++ b/best-practices/en/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ As you can see, we have created two methods. The first method `createComponentCo
 But what if the user doesn't fill in some fields? In that case, we should let him know that it is a required field. We did this with the `setRequired()` method.
 Finally, we also added an [event |nette:glossary#events] `onSuccess`, which is triggered if the form is submitted successfully. In our case, it calls the `contactFormSucceeded` method , which takes care of processing the submitted form. We'll add that to the code in a moment.
 
-Let the `contantForm` component be rendered in the `templates/Home/default.latte` template:
+Let the `contantForm` component be rendered in the `Home/default.latte` template:
 
 ```latte
 {block content}
diff --git a/best-practices/en/microsites.texy b/best-practices/en/microsites.texy
new file mode 100644
index 0000000000..846ddbe96d
--- /dev/null
+++ b/best-practices/en/microsites.texy
@@ -0,0 +1,63 @@
+How to Write Microsites
+***********************
+
+Imagine that you need to quickly create a small website for an upcoming event of your company. It should be simple, fast, and without unnecessary complications. You might think that such a small project doesn't require a robust framework. But what if using the Nette framework can significantly simplify and speed up this process?
+
+Even when creating simple websites, you don't want to give up comfort. You don't want to reinvent the wheel. Feel free to be lazy and pamper yourself. The Nette Framework can also be excellently used as a micro framework.
+
+What might such a microsite look like? For example, the entire code of the website can be placed in a single `index.php` file in the public folder:
+
+```php
+<?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// create a DI container based on the configuration in config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// set up routing
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// route for URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// detect browser language and redirect to URL /en or /de etc.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// route for URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// display the appropriate template, for example ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// run the application!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Everything else will be templates stored in the parent `/templates` folder.
+
+The PHP code in `index.php` first [sets up the environment |bootstrap:], then defines [routes|application:routing#dynamic-routing-with-callbacks], and finally runs the application. The advantage is that the second parameter of the `addRoute()` function can be a callable that is executed when the corresponding page is opened.
+
+
+Why use Nette for Microsites?
+-----------------------------
+
+- Developers who have ever tried [Tracy|tracy:] can't imagine coding without it today.
+- But above all, you will utilize the templating system [Latte|latte:], because from just 2 pages, you will want to separate [layout and content|latte:template-inheritance].
+- And you definitely want to rely on [automatic escaping |latte:safety-first] to prevent XSS vulnerabilities.
+- Nette also ensures that in case of an error, PHP error messages will never be displayed, but instead, a user-friendly page will.
+- If you want to get feedback from users, for example in the form of a contact form, you can also add [forms|forms:] and [database|database:].
+- You can also easily have filled-out forms [sent by email|mail:].
+- Sometimes you might find [caching|caching:] useful, for instance, when downloading and displaying feeds.
+
+In today's age, where speed and efficiency are key, it's important to have tools that allow you to achieve results without unnecessary delays. The Nette framework offers just that - fast development, security, and a wide range of tools like Tracy and Latte that simplify the process. Just install a few Nette packages, and building such a microsite becomes a breeze. And you know there are no hidden security flaws.
diff --git a/best-practices/en/pagination.texy b/best-practices/en/pagination.texy
index c0c0007e9b..8fa2b98ace 100644
--- a/best-practices/en/pagination.texy
+++ b/best-practices/en/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 In the Presenter we then inject the model class and in the render method we will ask for the published articles that we pass to the template:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-In the template, we will take care of rendering an articles list:
+The `default.latte` template will then take care of listing the articles:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ The next step is to edit the presenter. We will forward the number of the curren
 We also expand the render method to get the Paginator instance, setting it up, and selecting the correct articles to display in the template. HomePresenter will look like this:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 We do not have to create Paginator in the Presenter, instead we will use the method of `Selection` object returned by the repository:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/en/post-links.texy b/best-practices/en/post-links.texy
new file mode 100644
index 0000000000..45af7ea028
--- /dev/null
+++ b/best-practices/en/post-links.texy
@@ -0,0 +1,59 @@
+How to Properly Use POST Links
+******************************
+
+In web applications, especially in administrative interfaces, it should be a basic rule that actions changing the state of the server should not be performed via the HTTP GET method. As the method name suggests, GET should be used only to retrieve data, not to change it.
+For actions such as deleting records, it is more appropriate to use the POST method. Although the ideal would be to use the DELETE method, this cannot be invoked without JavaScript, hence POST is historically used.
+
+How to do it in practice? Use this simple trick. At the beginning of your template, create a helper form with the identifier `postForm`, which you will then use for the delete buttons:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+With this form, you can use a `<button>` instead of the classic `<a>` link, which can be visually modified to look like a regular link. For example, the Bootstrap CSS framework offers the classes `btn btn-link` which allow the button to be visually indistinguishable from other links. Using the `form="postForm"` attribute, we link it to the pre-prepared form:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+When clicking the link, the `delete` action is now invoked. To ensure that requests are accepted only through the POST method and from the same domain (which is an effective defense against CSRF attacks), use the `#[Requires]` attribute:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+The attribute has been available since Nette Application 3.2, and you can learn more about its capabilities on the page [How to use the #Requires attribute |attribute-requires].
+
+If you were using the signal `handleDelete()` instead of the action `actionDelete()`, it is not necessary to specify `sameOrigin: true`, because signals have this protection set implicitly:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+This approach not only improves the security of your application but also contributes to adhering to proper web standards and practices. By using POST methods for state-changing actions, you achieve a more robust and secure application.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/en/presenter-traits.texy b/best-practices/en/presenter-traits.texy
index 15edbdb7bd..051c3c0a7e 100644
--- a/best-practices/en/presenter-traits.texy
+++ b/best-practices/en/presenter-traits.texy
@@ -2,7 +2,7 @@ Composing Presenters from Traits
 ********************************
 
 .[perex]
-If we need to implement the same code in multiple presenters (e.g. verification that the user is logged in), it is tempting to place the code in a common ancestor. The second option is to create single-purpose traits.
+If we need to implement the same code in multiple presenters (e.g. verification that the user is logged in), it is tempting to place the code in a common ancestor. The second option is to create single-purpose [traits |nette:introduction-to-object-oriented-programming#traits].
 
 The advantage of this solution is that each presenter can use just the traits it actually needs, while multiple inheritance is not possible in PHP.
 
diff --git a/best-practices/es/@home.texy b/best-practices/es/@home.texy
index 2bbf67aa4b..155a7ca1c3 100644
--- a/best-practices/es/@home.texy
+++ b/best-practices/es/@home.texy
@@ -17,6 +17,8 @@ Aplicación Nette
 - [Cómo volver a una página anterior |restore-request]
 - [Paginación de los resultados de la base de datos |Pagination]
 - [Fragmentos dinámicos |dynamic-snippets]
+- [Cómo utilizar el atributo #Requires |attribute-requires]
+- [Cómo utilizar correctamente los enlaces POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formularios
 Común
 -----
 - [Cómo cargar el fichero de configuración |bootstrap:]
+- [Cómo escribir micrositios |microsites]
 - [¿Por qué Nette utiliza la notación constante PascalCase? |https://blog.nette.org/es/para-menos-gritos-en-el-codigo]
 - [¿Por qué Nette no utiliza el sufijo Interface? |https://blog.nette.org/es/los-prefijos-y-sufijos-no-pertenecen-a-los-nombres-de-interfaz]
 - [Consejos de uso de Composer |composer]
 - [Consejos sobre editores y herramientas |editors-and-tools]
+- [Introducción a la programación orientada a objetos |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/es/attribute-requires.texy b/best-practices/es/attribute-requires.texy
new file mode 100644
index 0000000000..0c51ef716b
--- /dev/null
+++ b/best-practices/es/attribute-requires.texy
@@ -0,0 +1,179 @@
+Cómo utilizar el atributo `#[Requires]` Atributo
+************************************************
+
+.[perex]
+Cuando escribes una aplicación web, a menudo te encuentras con la necesidad de restringir el acceso a ciertas partes de tu aplicación. Tal vez desee que algunas peticiones sólo puedan enviar datos a través de un formulario (utilizando así el método POST) o que sólo sean accesibles para llamadas AJAX. En Nette Framework 3.2, se ha introducido una nueva herramienta que permite establecer estas restricciones de forma elegante y clara: el atributo `#[Requires]` atributo.
+
+El atributo es un marcador especial en PHP, que se añade antes de la definición de una clase o método. Dado que se trata esencialmente de una clase, es necesario incluir la cláusula use para que los siguientes ejemplos funcionen:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Puede utilizar el atributo `#[Requires]` con la propia clase presentadora y en estos métodos:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Los dos últimos métodos también afectan a los componentes, por lo que también puede utilizar el atributo con ellos.
+
+Si no se cumplen las condiciones especificadas por el atributo, se produce un error HTTP 4xx.
+
+
+Métodos HTTP .[#toc-http-methods]
+---------------------------------
+
+Puede especificar qué métodos HTTP (como GET, POST, etc.) están permitidos para el acceso. Por ejemplo, si desea permitir el acceso sólo mediante el envío de un formulario, establezca:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+¿Por qué debería utilizar POST en lugar de GET para las acciones de cambio de estado y cómo hacerlo? [Lea la guía |post-links].
+
+Puede especificar un método o un conjunto de métodos. Un caso especial es el valor `'*'` para habilitar todos los métodos, que los presentadores no permiten por defecto por [motivos de seguridad |application:presenters#http-method-check].
+
+
+Llamadas AJAX .[#toc-ajax-calls]
+--------------------------------
+
+Si desea que un presentador o método sea accesible sólo para peticiones AJAX, utilice:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Mismo origen .[#toc-same-origin]
+--------------------------------
+
+Para mejorar la seguridad, puede exigir que la solicitud se realice desde el mismo dominio. Esto evita la [vulnerabilidad a CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Para los métodos `handle<Signal>()` se requiere automáticamente el acceso desde el mismo dominio. Por lo tanto, si desea permitir el acceso desde cualquier dominio, especifique:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Acceso a través de Forward .[#toc-access-via-forward]
+-----------------------------------------------------
+
+A veces es útil restringir el acceso a un presentador para que sólo esté disponible indirectamente, por ejemplo, utilizando los métodos `forward()` o `switch()` desde otro presentador. Así es como se protegen los presentadores de errores para evitar que se activen desde una URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+En la práctica, a menudo es necesario marcar determinadas vistas a las que sólo se puede acceder basándose en la lógica del presentador. De nuevo, para que no puedan abrirse directamente:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Acciones específicas .[#toc-specific-actions]
+---------------------------------------------
+
+También puede restringir que cierto código, como la creación de un componente, sea accesible sólo para acciones específicas en el presentador:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Para una sola acción, no es necesario escribir una matriz: `#[Requires(actions: 'default')]`
+
+
+Atributos personalizados .[#toc-custom-attributes]
+--------------------------------------------------
+
+Si desea utilizar el atributo `#[Requires]` atributo repetidamente con la misma configuración, puede crear su propio atributo que heredará `#[Requires]` y configurarlo según tus necesidades.
+
+Por ejemplo `#[SingleAction]` sólo permite el acceso a través de la acción `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+O `#[RestMethods]` permitirá el acceso a través de todos los métodos HTTP utilizados para la API REST:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Conclusión .[#toc-conclusion]
+-----------------------------
+
+El atributo `#[Requires]` te ofrece una gran flexibilidad y control sobre cómo se accede a tus páginas web. Usando reglas simples, pero potentes, puedes mejorar la seguridad y el buen funcionamiento de tu aplicación. Como puede ver, el uso de atributos en Nette no sólo puede simplificar su trabajo, sino también asegurarlo.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/es/composer.texy b/best-practices/es/composer.texy
index c550b6a92f..86cf99808a 100644
--- a/best-practices/es/composer.texy
+++ b/best-practices/es/composer.texy
@@ -142,6 +142,12 @@ O directamente en el archivo `composer.json`:
 ```
 
 
+Ignorando la versión de PHP .[#toc-ignoring-php-version]
+========================================================
+
+Los paquetes suelen especificar tanto la versión más baja de PHP con la que son compatibles como la versión más alta con la que han sido probados. Si planea usar una versión aún más nueva de PHP, quizás para propósitos de prueba, Composer se rehusará a instalar dicho paquete. La solución es utilizar la opción `--ignore-platform-req=php+`, que hace que Composer ignore los límites superiores de la versión PHP requerida.
+
+
 Informes falsos .[#toc-false-reports]
 =====================================
 
@@ -183,7 +189,7 @@ Sin embargo, también es posible utilizar Composer para cargar otras clases fuer
 
 Posteriormente, es necesario ejecutar el comando `composer dumpautoload` con cada cambio y dejar que se regeneren las tablas de autocarga. Esto es extremadamente incómodo, y es mucho mejor confiar esta tarea a [RobotLoader |robot-loader:], que realiza la misma actividad automáticamente en segundo plano y mucho más rápido.
 
-La segunda opción es seguir [PSR-4 |https://www.php-fig.org/psr/psr-4/]. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos, es decir, `App\Router\RouterFactory` se encuentra en el archivo `/path/to/App/Router/RouterFactory.php`. Ejemplo de configuración:
+La segunda opción es seguir [PSR-4 |https://www.php-fig.org/psr/psr-4/]. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos, es decir, `App\Core\RouterFactory` se encuentra en el archivo `/path/to/App/Core/RouterFactory.php`. Ejemplo de configuración:
 
 ```js
 {
diff --git a/best-practices/es/dynamic-snippets.texy b/best-practices/es/dynamic-snippets.texy
index 2133b4a573..d59e1eaefe 100644
--- a/best-practices/es/dynamic-snippets.texy
+++ b/best-practices/es/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Plantilla:
 Ajaxización .[#toc-ajaxization]
 ===============================
 
-Llevemos ahora AJAX a esta sencilla aplicación. Cambiar la calificación de un artículo no es lo suficientemente importante como para requerir una petición HTTP con redirección, así que lo ideal sería hacerlo con AJAX en segundo plano. Usaremos el [script handler de add-ons |https://componette.org/vojtech-dobes/nette.ajax.js/] con la convención habitual de que los enlaces AJAX tienen la clase CSS `ajax`.
+Llevemos ahora AJAX a esta sencilla aplicación. Cambiar la calificación de un artículo no es lo suficientemente importante como para requerir una petición HTTP con redirección, así que lo ideal sería hacerlo con AJAX en segundo plano. Usaremos el [script handler de add-ons |application:ajax#toc-naja] con la convención habitual de que los enlaces AJAX tienen la clase CSS `ajax`.
 
 Sin embargo, ¿cómo hacerlo específicamente? Nette ofrece 2 maneras: la del fragmento dinámico y la del componente. Ambas tienen sus pros y sus contras, así que las mostraremos una a una.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Por supuesto cambiaremos la plantilla de la vista y tendremos que añadir una f
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/es/form-reuse.texy b/best-practices/es/form-reuse.texy
index 12e62fa802..7f48acaea8 100644
--- a/best-practices/es/form-reuse.texy
+++ b/best-practices/es/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Es muy importante que la unión entre las clases `FormFactory` y `EditFormFactory` se implemente por composición, no por herencia de objetos:
+Es muy importante que la unión entre las clases `FormFactory` y `EditFormFactory` se implemente [por composición |nette:introduction-to-object-oriented-programming#composition], no por [herencia de objetos |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ ¡NO! LA HERENCIA NO PERTENECE AQUÍ
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Utilizar la herencia en este caso sería totalmente contraproducente. Se encontraría con problemas muy rápidamente. Por ejemplo, si quisiera agregar parámetros al método `create()`; PHP reportaría un error de que su firma es diferente a la del padre.
 O al pasar una dependencia a la clase `EditFormFactory` a través del constructor. Esto causaría lo que llamamos el infierno del [constructor |dependency-injection:passing-dependencies#Constructor hell].
 
-En general, es mejor preferir la composición a la herencia.
+En general, es mejor preferir la [composición a la herencia |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Manejo de Formularios .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/es/lets-create-contact-form.texy b/best-practices/es/lets-create-contact-form.texy
index 2c7e155167..142740037a 100644
--- a/best-practices/es/lets-create-contact-form.texy
+++ b/best-practices/es/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Como puedes ver, hemos creado dos métodos. El primer método `createComponentCo
 Pero, ¿qué pasa si el usuario no rellena algunos campos? En ese caso, debemos hacerle saber que se trata de un campo obligatorio. Hicimos esto con el método `setRequired()`.
 Por último, también añadimos un [evento |nette:glossary#events] `onSuccess`, que se activa si el formulario se envía correctamente. En nuestro caso, llama al método `contactFormSucceeded`, que se encarga de procesar el formulario enviado. Lo añadiremos al código en un momento.
 
-Dejemos que el componente `contantForm` sea renderizado en la plantilla `templates/Home/default.latte`:
+Dejemos que el componente `contantForm` sea renderizado en la plantilla `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/es/microsites.texy b/best-practices/es/microsites.texy
new file mode 100644
index 0000000000..6899e693df
--- /dev/null
+++ b/best-practices/es/microsites.texy
@@ -0,0 +1,63 @@
+Cómo escribir micrositios
+*************************
+
+Imagine que necesita crear rápidamente un pequeño sitio web para un próximo evento de su empresa. Debe ser simple, rápido y sin complicaciones innecesarias. Podrías pensar que un proyecto tan pequeño no requiere un framework robusto. Pero, ¿y si el uso del framework Nette puede simplificar y acelerar significativamente este proceso?
+
+Incluso cuando se crean sitios web sencillos, no se quiere renunciar a la comodidad. No quieres reinventar la rueda. Siéntase libre de ser perezoso y mimarse. Nette Framework también puede utilizarse de forma excelente como micro framework.
+
+¿Qué aspecto podría tener un micrositio de este tipo? Por ejemplo, todo el código del sitio web puede colocarse en un único archivo `index.php` en la carpeta pública:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// crear un contenedor DI basado en la configuración en config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// configurar el enrutamiento
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// ruta para la URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// detectar el idioma del navegador y redirigir a la URL /en o /de etc.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// ruta para URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// mostrar la plantilla adecuada, por ejemplo ../templates/es.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// ejecutar la aplicación
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Todo lo demás serán plantillas almacenadas en la carpeta padre `/templates`.
+
+El código PHP en `index.php` primero [configura el entorno |bootstrap:], luego define las [rutas |application:routing#dynamic-routing-with-callbacks] y finalmente ejecuta la aplicación. La ventaja es que el segundo parámetro de la función `addRoute()` puede ser un callable que se ejecuta cuando se abre la página correspondiente.
+
+
+¿Por qué utilizar Nette para los micrositios? .[#toc-why-use-nette-for-microsites]
+----------------------------------------------------------------------------------
+
+- Los desarrolladores que hayan probado alguna vez [Tracy |tracy:] no se imaginan hoy en día codificar sin él.
+- Pero sobre todo, utilizarán el sistema de plantillas [Latte |latte:], porque a partir de sólo 2 páginas, querrán separar [maquetación y contenido |latte:template-inheritance].
+- Y sin duda querrá confiar en el [escape automático |latte:safety-first] para evitar vulnerabilidades XSS.
+- Nette también garantiza que, en caso de error, nunca se mostrarán mensajes de error de PHP, sino una página fácil de usar.
+- Si desea obtener comentarios de los usuarios, por ejemplo en forma de formulario de contacto, también puede añadir [formularios |forms:] y [base de datos |database:].
+- También puedes hacer que los formularios rellenados se envíen fácilmente [por correo electrónico |mail:].
+- A veces puede resultarte útil [el almacenamiento en caché |caching:], por ejemplo, al descargar y mostrar feeds.
+
+En la era actual, en la que la velocidad y la eficacia son fundamentales, es importante contar con herramientas que permitan obtener resultados sin retrasos innecesarios. El framework Nette ofrece precisamente eso: desarrollo rápido, seguridad y una amplia gama de herramientas como Tracy y Latte que simplifican el proceso. Basta con instalar algunos paquetes de Nette, y construir un micrositio de este tipo se convierte en un juego de niños. Y sabes que no hay fallos de seguridad ocultos.
diff --git a/best-practices/es/pagination.texy b/best-practices/es/pagination.texy
index 4638f53da7..287b5d17a3 100644
--- a/best-practices/es/pagination.texy
+++ b/best-practices/es/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 En el Presentador inyectamos entonces la clase modelo y en el método render pediremos los artículos publicados que pasamos al modelo:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-En la plantilla nos encargaremos de renderizar una lista de artículos:
+La plantilla `default.latte` se encargará de listar los artículos:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ El siguiente paso es editar el presentador. Enviaremos el número de la página
 También expandimos el método render para obtener la instancia Paginator, configurándola, y seleccionando los artículos correctos para mostrar en la plantilla. HomePresenter tendrá este aspecto:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 No tenemos que crear Paginator en el Presentador, en su lugar utilizaremos el método del objeto `Selection` devuelto por el repositorio:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/es/post-links.texy b/best-practices/es/post-links.texy
new file mode 100644
index 0000000000..4b13b68b11
--- /dev/null
+++ b/best-practices/es/post-links.texy
@@ -0,0 +1,59 @@
+Cómo utilizar correctamente los enlaces POST
+********************************************
+
+En aplicaciones web, especialmente en interfaces administrativas, debería ser una regla básica que las acciones que cambian el estado del servidor no deberían realizarse a través del método HTTP GET. Como el nombre del método sugiere, GET debería usarse sólo para recuperar datos, no para cambiarlos.
+Para acciones como borrar registros, es más apropiado utilizar el método POST. Aunque lo ideal sería utilizar el método DELETE, éste no puede invocarse sin JavaScript, de ahí que históricamente se utilice POST.
+
+¿Cómo hacerlo en la práctica? Utilice este sencillo truco. Al principio de su plantilla, cree un formulario de ayuda con el identificador `postForm`, que luego utilizará para los botones de eliminación:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Con este formulario, puedes utilizar un `<button>` en lugar del clásico enlace `<a>` que puede modificarse visualmente para que parezca un enlace normal. Por ejemplo, el framework CSS de Bootstrap ofrece las clases `btn btn-link` que permiten que el botón sea visualmente indistinguible de otros enlaces. Usando el atributo `form="postForm"`, lo enlazamos al formulario ya preparado:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Al hacer clic en el enlace, ahora se invoca la acción `delete`. Para garantizar que las peticiones sólo se aceptan a través del método POST y desde el mismo dominio (lo que constituye una defensa eficaz contra los ataques CSRF), utilice el atributo `#[Requires]` atributo:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+El atributo ha estado disponible desde Nette Application 3.2, y puede aprender más sobre sus capacidades en la página [Cómo usar el atributo #Requires |attribute-requires].
+
+Si estuviera utilizando la señal `handleDelete()` en lugar de la acción `actionDelete()`, no es necesario especificar `sameOrigin: true`, porque las señales tienen esta protección establecida implícitamente:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Este enfoque no sólo mejora la seguridad de su aplicación, sino que también contribuye a adherirse a los estándares y prácticas web adecuados. Al utilizar métodos POST para acciones que cambian de estado, se consigue una aplicación más robusta y segura.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/es/presenter-traits.texy b/best-practices/es/presenter-traits.texy
index a50e8ec4e1..edcde6568c 100644
--- a/best-practices/es/presenter-traits.texy
+++ b/best-practices/es/presenter-traits.texy
@@ -2,7 +2,7 @@ Composición de presentadores a partir de rasgos
 ***********************************************
 
 .[perex]
-Si necesitamos implementar el mismo código en varios presentadores (por ejemplo, verificar que el usuario ha iniciado sesión), resulta tentador colocar el código en un ancestro común. La segunda opción es crear rasgos de propósito único.
+Si necesitamos implementar el mismo código en varios presentadores (por ejemplo, la verificación de que el usuario ha iniciado sesión), resulta tentador colocar el código en un ancestro común. La segunda opción es crear [rasgos |nette:introduction-to-object-oriented-programming#traits] de propósito único.
 
 La ventaja de esta solución es que cada presentador puede utilizar sólo los rasgos que realmente necesita, mientras que la herencia múltiple no es posible en PHP.
 
diff --git a/best-practices/fr/@home.texy b/best-practices/fr/@home.texy
index 0b3d8c26f6..93172f9ba9 100644
--- a/best-practices/fr/@home.texy
+++ b/best-practices/fr/@home.texy
@@ -17,6 +17,8 @@ Application Nette
 - [Comment revenir à une page précédente |restore-request]
 - [Pagination des résultats de la base de données |Pagination]
 - [Extraits dynamiques |dynamic-snippets]
+- [Comment utiliser l'attribut #Requires |attribute-requires]
+- [Comment utiliser correctement les liens POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formulaires
 Commun
 ------
 - [Comment charger le fichier de configuration |bootstrap:]
+- [Comment rédiger des microsites |microsites]
 - [Pourquoi Nette utilise la notation constante PascalCase ? |https://blog.nette.org/fr/pour-moins-crier-dans-le-code]
 - [Pourquoi Nette n'utilise pas le suffixe Interface ? |https://blog.nette.org/fr/les-prefixes-et-les-suffixes-n-ont-pas-leur-place-dans-les-noms-d-interface]
 - [Conseils d'utilisation de Composer |composer]
 - [Conseils sur les éditeurs et les outils |editors-and-tools]
+- [Introduction à la programmation orientée objet |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/fr/attribute-requires.texy b/best-practices/fr/attribute-requires.texy
new file mode 100644
index 0000000000..03e5be9f2e
--- /dev/null
+++ b/best-practices/fr/attribute-requires.texy
@@ -0,0 +1,179 @@
+Comment utiliser l'attribut `#[Requires]` Attribut
+**************************************************
+
+.[perex]
+Lorsque vous écrivez une application web, vous rencontrez souvent le besoin de restreindre l'accès à certaines parties de votre application. Vous souhaitez peut-être que certaines requêtes ne puissent envoyer des données que par l'intermédiaire d'un formulaire (en utilisant donc la méthode POST) ou qu'elles ne soient accessibles qu'aux appels AJAX. Dans le Nette Framework 3.2, un nouvel outil a été introduit qui vous permet de définir de telles restrictions de manière élégante et claire : l'attribut `#[Requires]` attribut.
+
+L'attribut est un marqueur spécial en PHP, que vous ajoutez avant la définition d'une classe ou d'une méthode. Comme il s'agit essentiellement d'une classe, vous devez inclure la clause use pour que les exemples suivants fonctionnent :
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Vous pouvez utiliser l'attribut `#[Requires]` avec la classe du présentateur elle-même et avec ces méthodes :
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Les deux dernières méthodes concernent également les composants, de sorte que vous pouvez également utiliser l'attribut avec eux.
+
+Si les conditions spécifiées par l'attribut ne sont pas remplies, une erreur HTTP 4xx est déclenchée.
+
+
+Méthodes HTTP .[#toc-http-methods]
+----------------------------------
+
+Vous pouvez spécifier les méthodes HTTP (telles que GET, POST, etc.) autorisées pour l'accès. Par exemple, si vous souhaitez n'autoriser l'accès qu'en soumettant un formulaire, définissez :
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Pourquoi utiliser POST au lieu de GET pour les actions de changement d'état et comment le faire ? [Lire le guide |post-links].
+
+Vous pouvez spécifier une méthode ou un tableau de méthodes. Un cas particulier est la valeur `'*'` qui permet d'activer toutes les méthodes, ce que les présentateurs n'autorisent pas par défaut pour des [raisons de sécurité |application:presenters#http-method-check].
+
+
+Appels AJAX .[#toc-ajax-calls]
+------------------------------
+
+Si vous souhaitez qu'un présentateur ou une méthode ne soit accessible que pour les requêtes AJAX, utilisez :
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Même origine .[#toc-same-origin]
+--------------------------------
+
+Pour renforcer la sécurité, vous pouvez exiger que la demande soit faite à partir du même domaine. Cela permet d'éviter la [vulnérabilité au CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Pour les méthodes `handle<Signal>()` l'accès à partir du même domaine est automatiquement requis. Par conséquent, si vous souhaitez autoriser l'accès à partir de n'importe quel domaine, indiquez :
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Accès via Forward .[#toc-access-via-forward]
+--------------------------------------------
+
+Il est parfois utile de restreindre l'accès à un présentateur pour qu'il ne soit accessible qu'indirectement, par exemple en utilisant les méthodes `forward()` ou `switch()` d'un autre présentateur. C'est ainsi que les présentateurs d'erreurs sont protégés pour éviter qu'ils ne soient déclenchés à partir d'une URL :
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Dans la pratique, il est souvent nécessaire de marquer certaines vues auxquelles on ne peut accéder qu'en fonction de la logique du présentateur. Là encore, elles ne peuvent pas être ouvertes directement :
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Actions spécifiques .[#toc-specific-actions]
+--------------------------------------------
+
+Vous pouvez également limiter l'accès à certains codes, comme la création d'un composant, à des actions spécifiques dans le présentateur :
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Pour une action unique, il n'est pas nécessaire d'écrire un tableau : `#[Requires(actions: 'default')]`
+
+
+Attributs personnalisés .[#toc-custom-attributes]
+-------------------------------------------------
+
+Si vous souhaitez utiliser l'attribut `#[Requires]` à plusieurs reprises avec les mêmes paramètres, vous pouvez créer votre propre attribut qui héritera de l'attribut `#[Requires]` et le paramétrer en fonction de vos besoins.
+
+Par exemple, l'attribut `#[SingleAction]` n'autorise l'accès que par l'action `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+ou `#[RestMethods]` permet l'accès via toutes les méthodes HTTP utilisées pour l'API REST :
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Conclusion .[#toc-conclusion]
+-----------------------------
+
+L'attribut `#[Requires]` vous offre une grande flexibilité et un contrôle sur la manière dont vos pages web sont accessibles. En utilisant des règles simples mais puissantes, vous pouvez améliorer la sécurité et le bon fonctionnement de votre application. Comme vous pouvez le constater, l'utilisation des attributs dans Nette peut non seulement simplifier votre travail, mais aussi le sécuriser.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/fr/composer.texy b/best-practices/fr/composer.texy
index 485cd78e67..bb6de406f9 100644
--- a/best-practices/fr/composer.texy
+++ b/best-practices/fr/composer.texy
@@ -142,6 +142,12 @@ Ou directement dans le fichier `composer.json` :
 ```
 
 
+Ignorer la version de PHP .[#toc-ignoring-php-version]
+======================================================
+
+Les paquets spécifient généralement la version la plus basse de PHP avec laquelle ils sont compatibles et la version la plus haute avec laquelle ils ont été testés. Si vous prévoyez d'utiliser une version plus récente de PHP, peut-être à des fins de test, Composer refusera d'installer un tel paquet. La solution est d'utiliser l'option `--ignore-platform-req=php+`, qui permet à Composer d'ignorer les limites supérieures de la version de PHP requise.
+
+
 Faux rapports .[#toc-false-reports]
 ===================================
 
@@ -183,7 +189,7 @@ Toutefois, il est également possible d'utiliser Composer pour charger d'autres
 
 Par la suite, il est nécessaire d'exécuter la commande `composer dumpautoload` à chaque modification et de laisser les tables d'autoloadage se régénérer. Ceci est extrêmement gênant, et il est de loin préférable de confier cette tâche à [RobotLoader |robot-loader:], qui effectue la même activité automatiquement en arrière-plan et beaucoup plus rapidement.
 
-La deuxième option consiste à suivre le [système PSR-4 |https://www.php-fig.org/psr/psr-4/]. Pour faire simple, il s'agit d'un système où les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, c'est-à-dire que `App\Router\RouterFactory` est situé dans le fichier `/path/to/App/Router/RouterFactory.php`. Exemple de configuration :
+La deuxième option consiste à suivre le [système PSR-4 |https://www.php-fig.org/psr/psr-4/]. Pour faire simple, il s'agit d'un système où les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, c'est-à-dire que `App\Core\RouterFactory` est situé dans le fichier `/path/to/App/Core/RouterFactory.php`. Exemple de configuration :
 
 ```js
 {
diff --git a/best-practices/fr/dynamic-snippets.texy b/best-practices/fr/dynamic-snippets.texy
index 5bc4743f67..053c6e6607 100644
--- a/best-practices/fr/dynamic-snippets.texy
+++ b/best-practices/fr/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template :
 Ajaxisation .[#toc-ajaxization]
 ===============================
 
-Introduisons maintenant AJAX dans cette application simple. La modification de l'évaluation d'un article n'est pas assez importante pour nécessiter une requête HTTP avec redirection, donc l'idéal serait de le faire avec AJAX en arrière-plan. Nous utiliserons le [script de gestion des modules complémentaires |https://componette.org/vojtech-dobes/nette.ajax.js/] avec la convention habituelle selon laquelle les liens AJAX ont la classe CSS `ajax`.
+Introduisons maintenant AJAX dans cette application simple. La modification de l'évaluation d'un article n'est pas assez importante pour nécessiter une requête HTTP avec redirection, donc l'idéal serait de le faire avec AJAX en arrière-plan. Nous utiliserons le [script de gestion des modules complémentaires |application:ajax#toc-naja] avec la convention habituelle selon laquelle les liens AJAX ont la classe CSS `ajax`.
 
 Cependant, comment le faire spécifiquement ? Nette propose deux méthodes : le snippet dynamique et le composant. Ces deux méthodes ont leurs avantages et leurs inconvénients, nous allons donc les présenter une par une.
 
@@ -151,7 +151,7 @@ Bien sûr, nous allons modifier le modèle de vue et nous devrons ajouter une fa
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/fr/form-reuse.texy b/best-practices/fr/form-reuse.texy
index a5a2829f81..97260a1ef4 100644
--- a/best-practices/fr/form-reuse.texy
+++ b/best-practices/fr/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Il est très important que la liaison entre les classes `FormFactory` et `EditFormFactory` soit mise en œuvre par composition et non par héritage d'objets :
+Il est très important que la liaison entre les classes `FormFactory` et `EditFormFactory` soit mise en œuvre [par composition |nette:introduction-to-object-oriented-programming#composition] et non par [héritage d'objets |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ NO ! L'HÉRITAGE N'A PAS SA PLACE ICI
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 L'utilisation de l'héritage dans ce cas serait totalement contre-productive. Vous rencontreriez des problèmes très rapidement. Par exemple, si vous vouliez ajouter des paramètres à la méthode `create()`, PHP signalerait une erreur parce que sa signature est différente de celle du parent.
 Ou lorsque vous passez une dépendance à la classe `EditFormFactory` via le constructeur. Cela provoquerait ce que nous appelons l'[enfer du constructeur |dependency-injection:passing-dependencies#Constructor hell].
 
-En général, il est préférable de préférer la composition à l'héritage.
+Il est généralement préférable de préférer la [composition à l'héritage |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Traitement des formulaires .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/fr/lets-create-contact-form.texy b/best-practices/fr/lets-create-contact-form.texy
index 50afc50327..0b3b5b4409 100644
--- a/best-practices/fr/lets-create-contact-form.texy
+++ b/best-practices/fr/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Comme vous pouvez le voir, nous avons créé deux méthodes. La première métho
 Mais que se passe-t-il si l'utilisateur ne remplit pas certains champs ? Dans ce cas, nous devons l'informer qu'il s'agit d'un champ obligatoire. C'est ce que nous avons fait avec la méthode `setRequired()`.
 Enfin, nous avons également ajouté un [événement |nette:glossary#events] `onSuccess`, qui est déclenché si le formulaire est soumis avec succès. Dans notre cas, il appelle la méthode `contactFormSucceeded`, qui se charge de traiter le formulaire soumis. Nous l'ajouterons au code dans un instant.
 
-Laissez le composant `contantForm` être rendu dans le modèle `templates/Home/default.latte`:
+Laissez le composant `contantForm` être rendu dans le modèle `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/fr/microsites.texy b/best-practices/fr/microsites.texy
new file mode 100644
index 0000000000..cdc28d162b
--- /dev/null
+++ b/best-practices/fr/microsites.texy
@@ -0,0 +1,63 @@
+Comment rédiger des microsites
+******************************
+
+Imaginez que vous ayez besoin de créer rapidement un petit site web pour un événement à venir de votre entreprise. Il doit être simple, rapide et sans complications inutiles. Vous pourriez penser qu'un si petit projet ne nécessite pas un framework robuste. Et si l'utilisation du framework Nette pouvait considérablement simplifier et accélérer ce processus ?
+
+Même lors de la création de sites web simples, vous ne voulez pas renoncer au confort. Vous ne voulez pas réinventer la roue. N'hésitez pas à être paresseux et à vous faire plaisir. Le cadre Nette peut également être utilisé de manière optimale en tant que micro-cadre.
+
+À quoi pourrait ressembler un tel microsite ? Par exemple, l'ensemble du code du site web peut être placé dans un seul fichier `index.php` dans le dossier public :
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// créer un conteneur DI basé sur la configuration dans config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// mettre en place le routage
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// route pour l'URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// détecter la langue du navigateur et rediriger vers l'URL /en ou /de etc.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// route pour l'URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// affiche le modèle approprié, par exemple ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// Exécutez l'application !
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Tout le reste sera des modèles stockés dans le dossier parent `/templates`.
+
+Le code PHP dans `index.php` configure d'abord l'[environnement |bootstrap:], puis définit les [itinéraires |application:routing#dynamic-routing-with-callbacks] et enfin exécute l'application. L'avantage est que le deuxième paramètre de la fonction `addRoute()` peut être un appel qui est exécuté lorsque la page correspondante est ouverte.
+
+
+Pourquoi utiliser Nette pour les microsites ? .[#toc-why-use-nette-for-microsites]
+----------------------------------------------------------------------------------
+
+- Les développeurs qui ont déjà essayé [Tracy |tracy:] ne peuvent imaginer coder sans lui aujourd'hui.
+- Mais surtout, vous utiliserez le système de templates [Latte |latte:], parce qu'à partir de 2 pages seulement, vous voudrez séparer la [mise en page et le contenu |latte:template-inheritance].
+- Et vous voudrez certainement compter sur l'[échappement automatique |latte:safety-first] pour éviter les vulnérabilités XSS.
+- Nette garantit également qu'en cas d'erreur, les messages d'erreur PHP ne seront jamais affichés, mais qu'une page conviviale le sera.
+- Si vous souhaitez obtenir un retour d'information de la part des utilisateurs, par exemple sous la forme d'un formulaire de contact, vous pouvez également ajouter des [formulaires |forms:] et une [base de données |database:].
+- Vous pouvez également faire en sorte que les formulaires remplis soient [envoyés par courrier électronique |mail:].
+- La [mise en cache |caching:] peut parfois s'avérer utile, par exemple lors du téléchargement et de l'affichage de flux.
+
+À notre époque, où la rapidité et l'efficacité sont essentielles, il est important de disposer d'outils qui vous permettent d'obtenir des résultats sans retards inutiles. C'est précisément ce qu'offre le cadre Nette : un développement rapide, la sécurité et une large gamme d'outils tels que Tracy et Latte qui simplifient le processus. Il suffit d'installer quelques paquets Nette pour que la création d'un microsite devienne un jeu d'enfant. Et vous savez qu'il n'y a pas de failles de sécurité cachées.
diff --git a/best-practices/fr/pagination.texy b/best-practices/fr/pagination.texy
index 9cb7e34af0..cafbff84cc 100644
--- a/best-practices/fr/pagination.texy
+++ b/best-practices/fr/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Dans le Presenter nous injectons ensuite la classe model et dans la méthode render nous allons demander les articles publiés que nous passons au template :
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Dans le modèle, nous allons nous occuper de rendre une liste d'articles :
+Le modèle `default.latte` se chargera ensuite de répertorier les articles :
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ L'étape suivante consiste à modifier le présentateur. Nous allons transmettre
 Nous étendons également la méthode de rendu pour obtenir l'instance de Paginator, la configurer et sélectionner les bons articles à afficher dans le modèle. Le HomePresenter ressemblera à ceci :
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Nous n'avons pas besoin de créer le Paginator dans le Presenter, à la place nous utiliserons la méthode de l'objet `Selection` retourné par le référentiel :
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/fr/post-links.texy b/best-practices/fr/post-links.texy
new file mode 100644
index 0000000000..70211882bc
--- /dev/null
+++ b/best-practices/fr/post-links.texy
@@ -0,0 +1,59 @@
+Comment utiliser correctement les liens POST
+********************************************
+
+Dans les applications web, en particulier dans les interfaces administratives, la règle de base devrait être que les actions modifiant l'état du serveur ne doivent pas être effectuées via la méthode HTTP GET. Comme le nom de la méthode le suggère, GET ne doit être utilisé que pour récupérer des données, et non pour les modifier.
+Pour des actions telles que la suppression d'enregistrements, il est plus approprié d'utiliser la méthode POST. L'idéal serait d'utiliser la méthode DELETE, mais celle-ci ne peut être invoquée sans JavaScript, d'où l'utilisation historique de POST.
+
+Comment faire en pratique ? Utilisez cette astuce simple. Au début de votre modèle, créez un formulaire d'aide avec l'identifiant `postForm`, que vous utiliserez ensuite pour les boutons de suppression :
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Avec ce formulaire, vous pouvez utiliser un `<button>` au lieu du lien classique `<a>` qui peut être modifié visuellement pour ressembler à un lien normal. Par exemple, le cadre CSS Bootstrap propose les classes `btn btn-link` qui permettent au bouton d'être visuellement indiscernable des autres liens. En utilisant l'attribut `form="postForm"`, nous le lions au formulaire préparé à l'avance :
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Lorsque l'on clique sur le lien, l'action `delete` est invoquée. Pour s'assurer que les requêtes ne sont acceptées que par la méthode POST et qu'elles proviennent du même domaine (ce qui constitue une défense efficace contre les attaques CSRF), utilisez l'attribut `#[Requires]` l'attribut
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+L'attribut est disponible depuis Nette Application 3.2, et vous pouvez en apprendre plus sur ses capacités sur la page [Comment utiliser l'attribut #Requires |attribute-requires].
+
+Si vous utilisez le signal `handleDelete()` au lieu de l'action `actionDelete()`, il n'est pas nécessaire de spécifier `sameOrigin: true`, car les signaux ont cette protection implicite :
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Cette approche améliore non seulement la sécurité de votre application, mais contribue également à l'adhésion aux normes et pratiques web appropriées. En utilisant les méthodes POST pour les actions de changement d'état, vous obtenez une application plus robuste et plus sûre.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/fr/presenter-traits.texy b/best-practices/fr/presenter-traits.texy
index ad30804c3c..ccc278ef83 100644
--- a/best-practices/fr/presenter-traits.texy
+++ b/best-practices/fr/presenter-traits.texy
@@ -2,7 +2,7 @@ Composer des présentateurs à partir de traits
 *********************************************
 
 .[perex]
-Si nous devons implémenter le même code dans plusieurs présentateurs (par exemple, vérifier que l'utilisateur est connecté), il est tentant de placer le code dans un ancêtre commun. La deuxième option consiste à créer des traits à usage unique.
+Si nous devons mettre en œuvre le même code dans plusieurs présentateurs (par exemple, vérifier que l'utilisateur est connecté), il est tentant de placer le code dans un ancêtre commun. La deuxième option consiste à créer des [traits |nette:introduction-to-object-oriented-programming#traits] à usage unique.
 
 L'avantage de cette solution est que chaque présentateur peut utiliser uniquement les traits dont il a réellement besoin, alors que l'héritage multiple n'est pas possible en PHP.
 
diff --git a/best-practices/hu/@home.texy b/best-practices/hu/@home.texy
index 5d9c323f64..4d86942986 100644
--- a/best-practices/hu/@home.texy
+++ b/best-practices/hu/@home.texy
@@ -17,6 +17,8 @@ Nette alkalmazás
 - [Hogyan térjünk vissza egy korábbi oldalra |restore-request]
 - [Adatbázisok eredményeinek lapozgatása |Pagination]
 - [Dinamikus snippetek |dynamic-snippets]
+- A [#Requires attribútum használata |attribute-requires]
+- [Hogyan kell helyesen használni a POST linkeket |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Nyomtatványok
 Közös
 -----
 - [Konfigurációs fájl betöltése |bootstrap:]
+- [Hogyan írjunk microsite-okat |microsites]
 - [Miért használ a Nette PascalCase konstans jelölést? |https://blog.nette.org/hu/kevesebb-sikolyert-a-kodban]
 - [Miért nem használja a Nette az Interface utótagot? |https://blog.nette.org/hu/az-elotagok-es-utotagok-nem-tartoznak-az-interfesznevekbe]
 - [Composer használati tippek |composer]
 - [Tippek a szerkesztőkhöz és eszközökhöz |editors-and-tools]
+- [Bevezetés az objektumorientált programozásba |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/hu/attribute-requires.texy b/best-practices/hu/attribute-requires.texy
new file mode 100644
index 0000000000..22cea565bb
--- /dev/null
+++ b/best-practices/hu/attribute-requires.texy
@@ -0,0 +1,179 @@
+Hogyan használjuk a `#[Requires]` Attribútum
+********************************************
+
+.[perex]
+Webalkalmazások írása során gyakran találkozunk azzal az igénnyel, hogy korlátozni kell az alkalmazás bizonyos részeihez való hozzáférést. Talán azt szeretné, hogy egyes kérések csak űrlapon keresztül küldhessenek adatokat (tehát a POST módszerrel), vagy csak AJAX-hívások számára legyenek elérhetők. A Nette Framework 3.2-ben egy új eszköz került bevezetésre, amely lehetővé teszi az ilyen korlátozások elegáns és egyértelmű beállítását: a `#[Requires]` attribútum.
+
+Az attribútum egy speciális jelölő a PHP-ban, amelyet egy osztály vagy metódus definíciója előtt adunk meg. Mivel lényegében egy osztályról van szó, a következő példák működéséhez a use záradékot is be kell illesztenie:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Használhatja a `#[Requires]` attribútumot magával a prezentáló osztállyal és ezekkel a metódusokkal:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Az utolsó két módszer szintén komponensekre vonatkozik, így ezekkel is használhatja az attribútumot.
+
+Ha az attribútum által meghatározott feltételek nem teljesülnek, a rendszer egy HTTP 4xx hibaüzenetet küld.
+
+
+HTTP-módszerek .[#toc-http-methods]
+-----------------------------------
+
+Megadhatja, hogy mely HTTP-módszerek (például GET, POST stb.) engedélyezettek a hozzáféréshez. Ha például csak egy űrlap elküldésével akarja engedélyezni a hozzáférést, állítsa be a következőket:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Miért érdemes POST-ot használni GET helyett állapotváltoztató műveletekhez, és hogyan kell ezt megtenni? [Olvassa el az útmutatót |post-links].
+
+Megadhat egy módszert vagy módszerek tömbjét. Speciális eset a `'*'` érték, amely minden módszert engedélyez, amit a prezenterek [biztonsági okokból |application:presenters#http-method-check] alapértelmezés szerint nem engedélyeznek.
+
+
+AJAX hívások .[#toc-ajax-calls]
+-------------------------------
+
+Ha azt szeretné, hogy egy bemutató vagy metódus csak AJAX-kérések számára legyen elérhető, használja a következőt:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Ugyanaz az eredet .[#toc-same-origin]
+-------------------------------------
+
+A biztonság növelése érdekében megkövetelheti, hogy a kérés ugyanarról a tartományról érkezzen. Ez megakadályozza [a CSRF sebezhetőséget |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+A  oldalon. `handle<Signal>()` módszerek esetében automatikusan ugyanabból a tartományból való hozzáférés szükséges. Ha tehát bármilyen tartományból engedélyezni szeretné a hozzáférést, adja meg:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Hozzáférés a Forwardon keresztül .[#toc-access-via-forward]
+-----------------------------------------------------------
+
+Néha célszerű úgy korlátozni a hozzáférést egy prezentálóhoz, hogy az csak közvetve legyen elérhető, például egy másik prezentáló `forward()` vagy `switch()` módszereivel. A hiba-bemutatókat így védik, hogy megakadályozzák, hogy egy URL-ből indítsák őket:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+A gyakorlatban gyakran szükség van bizonyos nézetek megjelölésére, amelyek csak a prezenter logikája alapján érhetők el. Megint csak azért, hogy ne lehessen őket közvetlenül megnyitni:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Konkrét intézkedések .[#toc-specific-actions]
+---------------------------------------------
+
+Azt is korlátozhatja, hogy bizonyos kódok, például egy komponens létrehozása, csak bizonyos műveletek esetén legyenek elérhetők a prezenterben:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Egyetlen művelethez nem szükséges tömböt írni: `#[Requires(actions: 'default')]`
+
+
+Egyéni attribútumok .[#toc-custom-attributes]
+---------------------------------------------
+
+Ha a `#[Requires]` attribútumot ismételten ugyanazokkal a beállításokkal használni, létrehozhat saját attribútumot, amely örökli a `#[Requires]` és az igényeinek megfelelően állíthatja be.
+
+Például, `#[SingleAction]` csak a `default` műveleten keresztül engedélyezi a hozzáférést:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Vagy `#[RestMethods]` lehetővé teszi a hozzáférést a REST API-hoz használt összes HTTP-módszeren keresztül:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Következtetés .[#toc-conclusion]
+--------------------------------
+
+A `#[Requires]` attribútum nagyfokú rugalmasságot és ellenőrzést biztosít a weboldalak elérésének módját illetően. Egyszerű, de hatékony szabályok használatával fokozhatja az alkalmazás biztonságát és megfelelő működését. Amint láthatja, az attribútumok használata a Nette-ben nemcsak egyszerűsítheti, hanem biztosíthatja is a munkáját.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/hu/composer.texy b/best-practices/hu/composer.texy
index a4159ed069..d3c767b633 100644
--- a/best-practices/hu/composer.texy
+++ b/best-practices/hu/composer.texy
@@ -142,6 +142,12 @@ Vagy közvetlenül a `composer.json` fájlban:
 ```
 
 
+PHP verzió figyelmen kívül hagyása .[#toc-ignoring-php-version]
+===============================================================
+
+A csomagok általában megadják a PHP legalacsonyabb verzióját, amellyel kompatibilisek, és a legmagasabb verzióját, amellyel tesztelték őket. Ha a PHP egy még újabb verzióját tervezi használni, esetleg tesztelési céllal, a Composer elutasítja az ilyen csomag telepítését. A megoldás a `--ignore-platform-req=php+` opció használata, amelynek hatására a Composer figyelmen kívül hagyja a szükséges PHP-verzió felső határértékeit.
+
+
 Hamis jelentések .[#toc-false-reports]
 ======================================
 
@@ -183,7 +189,7 @@ Lehetőség van azonban arra is, hogy a Composer segítségével a `vendor` mapp
 
 Ezt követően minden egyes változtatásnál el kell indítani a `composer dumpautoload` parancsot, és hagyni kell, hogy az autoloading táblák újratermelődjenek. Ez rendkívül kényelmetlen, és sokkal jobb, ha ezt a feladatot a [RobotLoaderre |robot-loader:] bízzuk, amely a háttérben automatikusan és sokkal gyorsabban végzi el ugyanezt a tevékenységet.
 
-A második lehetőség a [PSR-4 |https://www.php-fig.org/psr/psr-4/] követése. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztálynevek megfelelnek a könyvtárszerkezetnek és a fájlneveknek, azaz a `App\Router\RouterFactory` a `/path/to/App/Router/RouterFactory.php` fájlban található. Konfigurációs példa:
+A második lehetőség a [PSR-4 |https://www.php-fig.org/psr/psr-4/] követése. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztálynevek megfelelnek a könyvtárszerkezetnek és a fájlneveknek, azaz a `App\Core\RouterFactory` a `/path/to/App/Core/RouterFactory.php` fájlban található. Konfigurációs példa:
 
 ```js
 {
diff --git a/best-practices/hu/dynamic-snippets.texy b/best-practices/hu/dynamic-snippets.texy
index 508065649e..9234d5b6ce 100644
--- a/best-practices/hu/dynamic-snippets.texy
+++ b/best-practices/hu/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template:
 Ajaxization .[#toc-ajaxization]
 ===============================
 
-Vigyük most az AJAX-ot ebbe az egyszerű alkalmazásba. Egy cikk értékelésének megváltoztatása nem elég fontos ahhoz, hogy HTTP-kérést igényeljen átirányítással, így ideális esetben ezt AJAX-szel kell elvégezni a háttérben. Használni fogjuk a [kezelőszkriptet a kiegészítésekből |https://componette.org/vojtech-dobes/nette.ajax.js/] a szokásos konvencióval, hogy az AJAX linkek CSS osztálya a `ajax`.
+Vigyük most az AJAX-ot ebbe az egyszerű alkalmazásba. Egy cikk értékelésének megváltoztatása nem elég fontos ahhoz, hogy HTTP-kérést igényeljen átirányítással, így ideális esetben ezt AJAX-szel kell elvégezni a háttérben. Használni fogjuk a [kezelőszkriptet a kiegészítésekből |application:ajax#toc-naja] a szokásos konvencióval, hogy az AJAX linkek CSS osztálya a `ajax`.
 
 Azonban hogyan kell ezt konkrétan megtenni? A Nette 2 módszert kínál: a dinamikus snippet módot és a komponens módot. Mindkettőnek megvannak az előnyei és hátrányai, ezért egyenként mutatjuk be őket.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Természetesen meg fogjuk változtatni a nézetsablont, és hozzá kell adnunk e
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/hu/form-reuse.texy b/best-practices/hu/form-reuse.texy
index 9245624d97..d3ceabe3e2 100644
--- a/best-practices/hu/form-reuse.texy
+++ b/best-practices/hu/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Nagyon fontos, hogy a `FormFactory` és a `EditFormFactory` osztályok közötti kötés kompozícióval, nem pedig objektumörökléssel valósuljon meg:
+Nagyon fontos, hogy a `FormFactory` és a `EditFormFactory` osztályok közötti kötés [kompozícióval |nette:introduction-to-object-oriented-programming#composition], nem pedig [objektumörökléssel |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance] valósul meg:
 
 ```php
 // ⛔ NO! AZ ÖRÖKSÉG NEM TARTOZIK IDE
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Az öröklés használata ebben az esetben teljesen kontraproduktív lenne. Nagyon gyorsan problémákba ütközne. Például, ha paramétereket akarnánk hozzáadni a `create()` metódushoz; a PHP hibát jelezne, hogy a metódus aláírása eltér a szülőétől.
 Vagy ha a konstruktoron keresztül átadnánk egy függőséget a `EditFormFactory` osztálynak. Ez azt okozná, amit mi [konstruktor pokolnak |dependency-injection:passing-dependencies#Constructor hell] hívunk.
 
-Általánosságban elmondható, hogy jobb a kompozíciót előnyben részesíteni az örökléssel szemben.
+Általában jobb, ha a [kompozíciót |dependency-injection:faq#Why composition is preferred over inheritance] előnyben részesítjük az [örökléssel szemben |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Form kezelés .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/hu/lets-create-contact-form.texy b/best-practices/hu/lets-create-contact-form.texy
index 0f6e9b14d8..f13d2dc808 100644
--- a/best-practices/hu/lets-create-contact-form.texy
+++ b/best-practices/hu/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Mint látható, két metódust hoztunk létre. Az első metódus `createComponen
 De mi van akkor, ha a felhasználó nem tölt ki néhány mezőt? Ebben az esetben tudatnunk kell vele, hogy az adott mező kötelezően kitöltendő. Ezt a `setRequired()` metódussal tettük meg.
 Végül hozzáadtunk egy `onSuccess`[eseményt |nette:glossary#events] is, amely akkor lép működésbe, ha az űrlapot sikeresen elküldtük. A mi esetünkben meghívja a `contactFormSucceeded` metódust , amely a beküldött űrlap feldolgozásáról gondoskodik. Ezt is hozzáadjuk a kódhoz egy pillanat múlva.
 
-Legyen a `contantForm` komponens megjelenítve a `templates/Home/default.latte` sablonban:
+Legyen a `contantForm` komponens megjelenítve a `Home/default.latte` sablonban:
 
 ```latte
 {block content}
diff --git a/best-practices/hu/microsites.texy b/best-practices/hu/microsites.texy
new file mode 100644
index 0000000000..13c9024a32
--- /dev/null
+++ b/best-practices/hu/microsites.texy
@@ -0,0 +1,63 @@
+Hogyan írjunk mikrooldalakat
+****************************
+
+Képzelje el, hogy gyorsan létre kell hoznia egy kis weboldalt a cégének egy közelgő eseményéhez. Egyszerűnek, gyorsnak és felesleges bonyodalmak nélkülinek kell lennie. Azt gondolhatod, hogy egy ilyen kis projekt nem igényel robusztus keretrendszert. De mi van akkor, ha a Nette keretrendszer használatával jelentősen leegyszerűsítheti és felgyorsíthatja ezt a folyamatot?
+
+Még egyszerű weboldalak készítésekor sem szeretne lemondani a kényelemről. Nem akarja újra feltalálni a kereket. Legyen nyugodtan lusta és kényeztesse magát. A Nette keretrendszer mikro keretrendszerként is kiválóan használható.
+
+Hogyan nézhet ki egy ilyen mikrooldal? Például a weboldal teljes kódja egyetlen `index.php` fájlba helyezhető a nyilvános mappában:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// létrehoz egy DI konténert a config.neon konfiguráció alapján
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// útválasztás beállítása
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// útvonal az URL https://example.com/ URL-hez
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// a böngésző nyelvének felismerése és átirányítás az URL /en vagy /de stb. címre.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// útvonal az URL-hez https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// a megfelelő sablon megjelenítése, például ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// futtassuk az alkalmazást!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Minden más a `/templates` szülőmappában tárolt sablonok lesznek.
+
+A `index.php` oldalon található PHP-kód először beállítja [a környezetet |bootstrap:], majd definiálja az [útvonalakat |application:routing#dynamic-routing-with-callbacks], végül pedig futtatja az alkalmazást. Ennek előnye, hogy a `addRoute()` függvény második paramétere lehet egy hívható, amely a megfelelő oldal megnyitásakor végrehajtódik.
+
+
+Miért használja a Nette-et a mikrooldalakhoz? .[#toc-why-use-nette-for-microsites]
+----------------------------------------------------------------------------------
+
+- Azok a fejlesztők, akik valaha is kipróbálták a [Tracy-t |tracy:], ma már el sem tudják képzelni a kódolást nélküle.
+- De mindenekelőtt a [Latte |latte:] templating rendszert fogja kihasználni, mert mindössze 2 oldalról akarja szétválasztani [az elrendezést és a tartalmat |latte:template-inheritance].
+- És mindenképpen az [automatikus escapingre |latte:safety-first] akarsz támaszkodni az XSS sebezhetőségek elkerülése érdekében.
+- A Nette gondoskodik arról is, hogy hiba esetén soha ne jelenjenek meg PHP hibaüzenetek, hanem egy felhasználóbarát oldal jelenjen meg.
+- Ha visszajelzést szeretne kapni a felhasználóktól, például kapcsolatfelvételi űrlap formájában, akkor [űrlapokat |forms:] és [adatbázist |database:] is hozzáadhat.
+- A kitöltött űrlapokat is könnyen [elküldheti e-mailben |mail:].
+- Néha hasznos lehet a [gyorsítótárazás |caching:], például a feedek letöltésekor és megjelenítésekor.
+
+A mai korban, amikor a gyorsaság és a hatékonyság kulcsfontosságú, fontos, hogy olyan eszközökkel rendelkezzen, amelyekkel felesleges késedelmek nélkül érhet el eredményeket. A Nette keretrendszer pontosan ezt kínálja: gyors fejlesztést, biztonságot és olyan eszközök széles skáláját, mint a Tracy és a Latte, amelyek leegyszerűsítik a folyamatot. Csak telepítsen néhány Nette csomagot, és egy ilyen microsite építése gyerekjátékká válik. És tudja, hogy nincsenek rejtett biztonsági hibák.
diff --git a/best-practices/hu/pagination.texy b/best-practices/hu/pagination.texy
index eee3c4024b..f9611c6e3f 100644
--- a/best-practices/hu/pagination.texy
+++ b/best-practices/hu/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 A Presenterben ezután befecskendezzük a modell osztályt, és a render metódusban lekérdezzük a publikált cikkeket, amelyeket átadunk a sablonhoz:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-A sablonban gondoskodunk egy cikklista rendereléséről:
+A `default.latte` sablon ezután gondoskodik a cikkek felsorolásáról:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ A következő lépés a bemutató szerkesztése. Az aktuálisan megjelenített o
 A render metódust kibővítjük a Paginator példány megszerzésével, beállításával és a sablonban megjelenítendő megfelelő cikkek kiválasztásával is. A HomePresenter így fog kinézni:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Nem kell Paginátort létrehoznunk a Presenterben, helyette az adattár által visszaadott `Selection` objektum metódusát fogjuk használni:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/hu/post-links.texy b/best-practices/hu/post-links.texy
new file mode 100644
index 0000000000..7fa8a2a16e
--- /dev/null
+++ b/best-practices/hu/post-links.texy
@@ -0,0 +1,59 @@
+Hogyan kell helyesen használni a POST linkeket
+**********************************************
+
+A webes alkalmazásokban, különösen az adminisztrációs felületeken alapvető szabály kell, hogy legyen, hogy a kiszolgáló állapotát megváltoztató műveleteket nem szabad a HTTP GET módszerrel végrehajtani. Ahogy a módszer neve is sugallja, a GET csak adatok lekérdezésére használható, azok megváltoztatására nem.
+Az olyan műveletekhez, mint például a rekordok törlése, célszerűbb a POST módszert használni. Bár az ideális a DELETE módszer használata lenne, ez nem hívható elő JavaScript nélkül, ezért a POST módszert használják.
+
+Hogyan kell ezt a gyakorlatban csinálni? Használja ezt az egyszerű trükköt. A sablon elején hozzon létre egy segédűrlapot a `postForm` azonosítóval, amelyet aztán a törlés gombokhoz fog használni:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Ezzel az űrlappal használhat egy `<button>` a klasszikus `<a>` link helyett, amely vizuálisan úgy módosítható, hogy úgy nézzen ki, mint egy hagyományos link. A Bootstrap CSS keretrendszer például a `btn btn-link` osztályokat kínálja, amelyek lehetővé teszik, hogy a gomb vizuálisan megkülönböztethetetlen legyen más linkektől. A `form="postForm"` attribútum segítségével az előre elkészített űrlapra linkeljük:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+A linkre kattintva mostantól a `delete` műveletet hívjuk elő. Annak biztosítására, hogy a kéréseket csak POST módszerrel és ugyanabból a tartományból fogadjuk el (ami hatékony védekezés a CSRF-támadások ellen), használjuk a `#[Requires]` attribútumot:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Az attribútum a Nette Application 3.2 óta áll rendelkezésre, és lehetőségeiről többet megtudhat a [Hogyan használjuk a #Requires attribútumot |attribute-requires] című oldalon.
+
+Ha a `actionDelete()` művelet helyett a `handleDelete()` jelet használná, nem szükséges a `sameOrigin: true` megadása, mivel a jeleknél ez a védelem implicit módon van beállítva:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Ez a megközelítés nemcsak az alkalmazás biztonságát javítja, hanem hozzájárul a megfelelő webes szabványok és gyakorlatok betartásához is. A POST-módszerek használatával az állapotváltoztató műveletekhez robusztusabb és biztonságosabb alkalmazást érhet el.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/hu/presenter-traits.texy b/best-practices/hu/presenter-traits.texy
index 15a65bf31f..7e1c996e54 100644
--- a/best-practices/hu/presenter-traits.texy
+++ b/best-practices/hu/presenter-traits.texy
@@ -2,7 +2,7 @@ Előadók összeállítása tulajdonságokból
 **************************************
 
 .[perex]
-Ha ugyanazt a kódot több prezenterben kell implementálnunk (pl. annak ellenőrzése, hogy a felhasználó be van-e jelentkezve), akkor csábító, hogy a kódot egy közös ősben helyezzük el. A második lehetőség az egycélú tulajdonságok létrehozása.
+Ha ugyanazt a kódot több prezenterben kell implementálnunk (pl. annak ellenőrzése, hogy a felhasználó be van-e jelentkezve), akkor csábító, hogy a kódot egy közös ősben helyezzük el. A második lehetőség az egycélú [tulajdonságok |nette:introduction-to-object-oriented-programming#traits] létrehozása.
 
 Ennek a megoldásnak az az előnye, hogy minden egyes prezenter csak azokat a tulajdonságokat használhatja, amelyekre ténylegesen szüksége van, míg a többszörös öröklés nem lehetséges a PHP-ben.
 
diff --git a/best-practices/it/@home.texy b/best-practices/it/@home.texy
index 10f16cec1d..969e19bec2 100644
--- a/best-practices/it/@home.texy
+++ b/best-practices/it/@home.texy
@@ -17,6 +17,8 @@ Applicazione Nette
 - [Come tornare a una pagina precedente |restore-request]
 - [Impaginazione dei risultati del database |Pagination]
 - [Snippet dinamici |dynamic-snippets]
+- [Come utilizzare l'attributo #Requires |attribute-requires]
+- [Come utilizzare correttamente i link POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Moduli
 Comune
 ------
 - [Come caricare il file di configurazione |bootstrap:]
+- [Come scrivere micrositi |microsites]
 - [Perché Nette usa la notazione costante PascalCase? |https://blog.nette.org/it/per-non-urlare-nel-codice]
 - [Perché Nette non usa il suffisso Interface? |https://blog.nette.org/it/i-prefissi-e-i-suffissi-non-appartengono-ai-nomi-delle-interfacce]
 - [Suggerimenti per l'uso di Composer |composer]
 - [Suggerimenti su editor e strumenti |editors-and-tools]
+- [Introduzione alla programmazione orientata agli oggetti |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/it/attribute-requires.texy b/best-practices/it/attribute-requires.texy
new file mode 100644
index 0000000000..f6a54bf381
--- /dev/null
+++ b/best-practices/it/attribute-requires.texy
@@ -0,0 +1,179 @@
+Come utilizzare l'attributo `#[Requires]` Attributo
+***************************************************
+
+.[perex]
+Quando si scrive un'applicazione web, spesso si incontra la necessità di limitare l'accesso a certe parti dell'applicazione. Forse si desidera che alcune richieste possano essere inviate solo tramite un modulo (utilizzando quindi il metodo POST) o che siano accessibili solo alle chiamate AJAX. In Nette Framework 3.2 è stato introdotto un nuovo strumento che consente di impostare tali restrizioni in modo elegante e chiaro: l'attributo `#[Requires]` attributo.
+
+L'attributo è un marcatore speciale in PHP, che si aggiunge prima della definizione di una classe o di un metodo. Poiché si tratta essenzialmente di una classe, è necessario includere la clausola use per far funzionare gli esempi seguenti:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+È possibile utilizzare l'attributo `#[Requires]` con la classe del presentatore e con questi metodi:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Anche gli ultimi due metodi riguardano i componenti, quindi è possibile utilizzare l'attributo anche con essi.
+
+Se le condizioni specificate dall'attributo non sono soddisfatte, viene generato un errore HTTP 4xx.
+
+
+Metodi HTTP .[#toc-http-methods]
+--------------------------------
+
+È possibile specificare quali metodi HTTP (come GET, POST, ecc.) sono consentiti per l'accesso. Ad esempio, se si desidera consentire l'accesso solo tramite l'invio di un modulo, impostare:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Perché usare POST invece di GET per le azioni di modifica dello stato e come farlo? [Leggete la guida |post-links].
+
+È possibile specificare un metodo o una serie di metodi. Un caso particolare è il valore `'*'` per abilitare tutti i metodi, che i presentatori non consentono di default per [motivi di sicurezza |application:presenters#http-method-check].
+
+
+Chiamate AJAX .[#toc-ajax-calls]
+--------------------------------
+
+Se si desidera che un presentatore o un metodo sia accessibile solo per le richieste AJAX, utilizzare:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Stessa origine .[#toc-same-origin]
+----------------------------------
+
+Per migliorare la sicurezza, è possibile richiedere che la richiesta venga effettuata dallo stesso dominio. In questo modo si evita la [vulnerabilità al CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Per i metodi `handle<Signal>()` l'accesso dallo stesso dominio è automaticamente richiesto. Pertanto, se si desidera consentire l'accesso da qualsiasi dominio, specificare:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Accesso tramite Forward .[#toc-access-via-forward]
+--------------------------------------------------
+
+A volte è utile limitare l'accesso a un presentatore in modo che sia disponibile solo indirettamente, ad esempio utilizzando i metodi `forward()` o `switch()` di un altro presentatore. In questo modo si proteggono i presentatori di errori, per evitare che vengano attivati da un URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+In pratica, spesso è necessario contrassegnare alcune viste a cui si può accedere solo in base alla logica del presentatore. Anche in questo caso, in modo che non possano essere aperte direttamente:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Azioni specifiche .[#toc-specific-actions]
+------------------------------------------
+
+È anche possibile limitare l'accesso a determinati codici, come la creazione di un componente, solo per azioni specifiche nel presentatore:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Per una singola azione, non è necessario scrivere un array: `#[Requires(actions: 'default')]`
+
+
+Attributi personalizzati .[#toc-custom-attributes]
+--------------------------------------------------
+
+Se si desidera utilizzare l'attributo `#[Requires]` con le stesse impostazioni, è possibile creare un attributo personalizzato che erediterà `#[Requires]` e impostarlo secondo le proprie esigenze.
+
+Ad esempio, `#[SingleAction]` consente l'accesso solo attraverso l'azione `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Oppure `#[RestMethods]` consentirà l'accesso tramite tutti i metodi HTTP utilizzati per l'API REST:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Conclusione .[#toc-conclusion]
+------------------------------
+
+L'attributo `#[Requires]` offre grande flessibilità e controllo sulle modalità di accesso alle pagine web. Utilizzando regole semplici ma potenti, è possibile migliorare la sicurezza e il corretto funzionamento dell'applicazione. Come si può vedere, l'uso degli attributi in Nette non solo semplifica il lavoro, ma lo rende anche sicuro.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/it/composer.texy b/best-practices/it/composer.texy
index c30fc6d908..6ca7aff82e 100644
--- a/best-practices/it/composer.texy
+++ b/best-practices/it/composer.texy
@@ -142,6 +142,12 @@ Oppure direttamente nel file `composer.json`:
 ```
 
 
+Ignorare la versione di PHP .[#toc-ignoring-php-version]
+========================================================
+
+I pacchetti di solito specificano sia la versione più bassa di PHP con cui sono compatibili sia la versione più alta con cui sono stati testati. Se si prevede di usare una versione di PHP ancora più recente, magari a scopo di test, Composer si rifiuterà di installare tale pacchetto. La soluzione è usare l'opzione `--ignore-platform-req=php+`, che fa sì che Composer ignori i limiti superiori della versione PHP richiesta.
+
+
 Rapporti falsi .[#toc-false-reports]
 ====================================
 
@@ -183,7 +189,7 @@ Tuttavia, è anche possibile usare Composer per caricare altre classi al di fuor
 
 Successivamente, è necessario eseguire il comando `composer dumpautoload` a ogni modifica e lasciare che le tabelle di autocaricamento si rigenerino. Questo è estremamente scomodo ed è molto meglio affidare questo compito a [RobotLoader |robot-loader:], che svolge la stessa attività automaticamente in background e molto più velocemente.
 
-La seconda opzione consiste nel seguire [PSR-4 |https://www.php-fig.org/psr/psr-4/]. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, cioè `App\Router\RouterFactory` si trova nel file `/path/to/App/Router/RouterFactory.php`. Esempio di configurazione:
+La seconda opzione consiste nel seguire [PSR-4 |https://www.php-fig.org/psr/psr-4/]. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, cioè `App\Core\RouterFactory` si trova nel file `/path/to/App/Core/RouterFactory.php`. Esempio di configurazione:
 
 ```js
 {
diff --git a/best-practices/it/dynamic-snippets.texy b/best-practices/it/dynamic-snippets.texy
index 870ac5ebdc..c195b97853 100644
--- a/best-practices/it/dynamic-snippets.texy
+++ b/best-practices/it/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template:
 Ajaxization .[#toc-ajaxization]
 ===============================
 
-Ora aggiungiamo AJAX a questa semplice applicazione. La modifica della valutazione di un articolo non è abbastanza importante da richiedere una richiesta HTTP con redirect, quindi idealmente dovrebbe essere fatta con AJAX in background. Utilizzeremo lo [script handler di add-on |https://componette.org/vojtech-dobes/nette.ajax.js/] con la solita convenzione che i link AJAX abbiano la classe CSS `ajax`.
+Ora aggiungiamo AJAX a questa semplice applicazione. La modifica della valutazione di un articolo non è abbastanza importante da richiedere una richiesta HTTP con redirect, quindi idealmente dovrebbe essere fatta con AJAX in background. Utilizzeremo lo [script handler di add-on |application:ajax#toc-naja] con la solita convenzione che i link AJAX abbiano la classe CSS `ajax`.
 
 Tuttavia, come farlo in modo specifico? Nette offre due modi: quello degli snippet dinamici e quello dei componenti. Entrambi hanno pro e contro, quindi li mostreremo uno per uno.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Naturalmente cambieremo il modello della vista e dovremo aggiungere un factory a
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/it/form-reuse.texy b/best-practices/it/form-reuse.texy
index 26e0e30dbb..696ad6d9c6 100644
--- a/best-practices/it/form-reuse.texy
+++ b/best-practices/it/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-È molto importante che il legame tra le classi `FormFactory` e `EditFormFactory` sia implementato tramite composizione, non tramite ereditarietà degli oggetti:
+È molto importante che il legame tra le classi `FormFactory` e `EditFormFactory` sia implementato [tramite composizione |nette:introduction-to-object-oriented-programming#composition] e non tramite [ereditarietà degli oggetti |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // NO! L'EREDITÀ NON È QUI
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 L'uso dell'ereditarietà in questo caso sarebbe completamente controproducente. Si incorrerebbe in problemi molto rapidamente. Per esempio, se si volessero aggiungere parametri al metodo `create()`, PHP segnalerebbe un errore perché la sua firma è diversa da quella del genitore.
 Oppure quando si passa una dipendenza alla classe `EditFormFactory` tramite il costruttore. Questo causerebbe quello che chiamiamo l'[inferno dei costruttori |dependency-injection:passing-dependencies#Constructor hell].
 
-In generale, è meglio preferire la composizione all'ereditarietà.
+In genere è meglio preferire la [composizione all'ereditarietà |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Gestione dei moduli .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/it/lets-create-contact-form.texy b/best-practices/it/lets-create-contact-form.texy
index 463ed21c39..468790dce9 100644
--- a/best-practices/it/lets-create-contact-form.texy
+++ b/best-practices/it/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Come si può vedere, abbiamo creato due metodi. Il primo metodo `createComponent
 Ma cosa succede se l'utente non compila alcuni campi? In questo caso, dovremmo fargli sapere che si tratta di un campo obbligatorio. Lo abbiamo fatto con il metodo `setRequired()`.
 Infine, abbiamo aggiunto anche un [evento |nette:glossary#events] `onSuccess`, che si attiva se il form viene inviato con successo. Nel nostro caso, richiama il metodo `contactFormSucceeded`, che si occupa di elaborare il modulo inviato. Lo aggiungeremo al codice tra poco.
 
-Il componente `contantForm` deve essere reso nel template `templates/Home/default.latte`:
+Il componente `contantForm` deve essere reso nel template `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/it/microsites.texy b/best-practices/it/microsites.texy
new file mode 100644
index 0000000000..d023f24d7d
--- /dev/null
+++ b/best-practices/it/microsites.texy
@@ -0,0 +1,63 @@
+Come scrivere micrositi
+***********************
+
+Immaginate di dover creare rapidamente un piccolo sito web per un evento imminente della vostra azienda. Dovrebbe essere semplice, veloce e senza inutili complicazioni. Potreste pensare che un progetto così piccolo non richieda un framework robusto. Ma se l'utilizzo del framework Nette semplificasse e velocizzasse notevolmente questo processo?
+
+Anche quando si creano siti web semplici, non si vuole rinunciare al comfort. Non volete reinventare la ruota. Sentitevi liberi di essere pigri e di coccolarvi. Il framework Nette può essere utilizzato in modo eccellente anche come micro framework.
+
+Come potrebbe essere un microsito di questo tipo? Ad esempio, l'intero codice del sito web può essere inserito in un singolo file `index.php` nella cartella pubblica:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// creare un contenitore DI basato sulla configurazione in config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// impostare l'instradamento
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// rotta per l'URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// rilevare la lingua del browser e reindirizzare all'URL /en o /de ecc.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// rotta per l'URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// visualizza il modello appropriato, ad esempio ../templates/it.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// eseguire l'applicazione!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Tutto il resto saranno modelli memorizzati nella cartella madre `/templates`.
+
+Il codice PHP in `index.php` imposta prima l'[ambiente |bootstrap:], poi definisce le [rotte |application:routing#dynamic-routing-with-callbacks] e infine esegue l'applicazione. Il vantaggio è che il secondo parametro della funzione `addRoute()` può essere un callable che viene eseguito quando viene aperta la pagina corrispondente.
+
+
+Perché usare Nette per i micrositi? .[#toc-why-use-nette-for-microsites]
+------------------------------------------------------------------------
+
+- Gli sviluppatori che hanno provato [Tracy |tracy:] non possono immaginare di codificare senza di esso oggi.
+- Ma soprattutto, utilizzerete il sistema di template [Latte |latte:], perché da sole 2 pagine, vorrete separare [layout e contenuti |latte:template-inheritance].
+- E sicuramente vorrete affidarvi all'[escape automatico |latte:safety-first] per prevenire le vulnerabilità XSS.
+- Nette garantisce inoltre che, in caso di errore, non vengano mai visualizzati messaggi di errore PHP, ma una pagina di facile consultazione.
+- Se si desidera ottenere un feedback dagli utenti, ad esempio sotto forma di modulo di contatto, è possibile aggiungere [moduli |forms:] e [database |database:].
+- È anche possibile [inviare |mail:] facilmente [via e-mail |mail:] i moduli compilati.
+- A volte può essere utile la [cache |caching:], ad esempio quando si scaricano e si visualizzano i feed.
+
+Nell'era odierna, in cui velocità ed efficienza sono fondamentali, è importante disporre di strumenti che consentano di ottenere risultati senza inutili ritardi. Il framework Nette offre proprio questo: sviluppo veloce, sicurezza e un'ampia gamma di strumenti come Tracy e Latte che semplificano il processo. Basta installare alcuni pacchetti Nette e la costruzione di un microsito di questo tipo diventa un gioco da ragazzi. E si sa che non ci sono falle di sicurezza nascoste.
diff --git a/best-practices/it/pagination.texy b/best-practices/it/pagination.texy
index f88acbacb5..adf166b262 100644
--- a/best-practices/it/pagination.texy
+++ b/best-practices/it/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Nel Presenter iniettiamo poi la classe Model e nel metodo render chiediamo gli articoli pubblicati che passiamo al template:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Nel modello, ci occuperemo di rendere un elenco di articoli:
+Il modello `default.latte` si occuperà di elencare gli articoli:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Il passo successivo è modificare il presentatore. Inoltreremo il numero della p
 Espandiamo inoltre il metodo render per ottenere l'istanza di Paginator, impostandola e selezionando gli articoli corretti da visualizzare nel template. HomePresenter avrà questo aspetto:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Non è necessario creare il Paginator nel Presenter, ma si utilizzerà il metodo dell'oggetto `Selection` restituito dal repository:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/it/post-links.texy b/best-practices/it/post-links.texy
new file mode 100644
index 0000000000..8fbca0e2c4
--- /dev/null
+++ b/best-practices/it/post-links.texy
@@ -0,0 +1,59 @@
+Come utilizzare correttamente i link POST
+*****************************************
+
+Nelle applicazioni web, soprattutto nelle interfacce amministrative, dovrebbe essere una regola di base che le azioni che modificano lo stato del server non dovrebbero essere eseguite tramite il metodo HTTP GET. Come suggerisce il nome del metodo, GET deve essere usato solo per recuperare dati, non per modificarli.
+Per azioni come la cancellazione di record, è più appropriato usare il metodo POST. Anche se l'ideale sarebbe usare il metodo DELETE, questo non può essere invocato senza JavaScript, quindi storicamente si usa POST.
+
+Come fare nella pratica? Utilizzando questo semplice trucco. All'inizio del modello, creare un modulo di aiuto con l'identificatore `postForm`, che verrà poi utilizzato per i pulsanti di cancellazione:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Con questo modulo, è possibile utilizzare un elemento `<button>` invece del classico link `<a>` che può essere modificato visivamente per sembrare un normale link. Ad esempio, il framework CSS Bootstrap offre le classi `btn btn-link`, che consentono al pulsante di essere visivamente indistinguibile dagli altri link. Utilizzando l'attributo `form="postForm"`, lo colleghiamo al modulo già pronto:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Quando si clicca sul link, viene richiamata l'azione `delete`. Per garantire che le richieste siano accettate solo attraverso il metodo POST e dallo stesso dominio (che è una difesa efficace contro gli attacchi CSRF), utilizzare l'attributo `#[Requires]` ...l'attributo:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+L'attributo è disponibile da Nette Application 3.2 e per saperne di più sulle sue funzionalità si può consultare la pagina [Come usare l'attributo #Requires |attribute-requires].
+
+Se si utilizza il segnale `handleDelete()` invece dell'azione `actionDelete()`, non è necessario specificare `sameOrigin: true`, perché i segnali hanno questa protezione impostata implicitamente:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Questo approccio non solo migliora la sicurezza dell'applicazione, ma contribuisce anche a rispettare gli standard e le pratiche web. Utilizzando i metodi POST per le azioni che cambiano stato, si ottiene un'applicazione più robusta e sicura.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/it/presenter-traits.texy b/best-practices/it/presenter-traits.texy
index 4837d5769c..9e10beab70 100644
--- a/best-practices/it/presenter-traits.texy
+++ b/best-practices/it/presenter-traits.texy
@@ -2,7 +2,7 @@ Comporre i presentatori dai tratti
 **********************************
 
 .[perex]
-Se occorre implementare lo stesso codice in più presentatori (ad esempio, la verifica che l'utente sia loggato), si è tentati di collocare il codice in un antenato comune. La seconda opzione è quella di creare tratti a scopo singolo.
+Se abbiamo bisogno di implementare lo stesso codice in più presentatori (ad esempio, la verifica che l'utente sia connesso), siamo tentati di collocare il codice in un antenato comune. La seconda opzione è quella di creare [tratti |nette:introduction-to-object-oriented-programming#traits] a scopo singolo.
 
 Il vantaggio di questa soluzione è che ogni presentatore può utilizzare solo i tratti di cui ha effettivamente bisogno, mentre l'ereditarietà multipla non è possibile in PHP.
 
diff --git a/best-practices/pl/@home.texy b/best-practices/pl/@home.texy
index 32416cbcfb..a89af33e7f 100644
--- a/best-practices/pl/@home.texy
+++ b/best-practices/pl/@home.texy
@@ -17,6 +17,8 @@ Aplikacje Nette
 - [Jak wrócić do wcześniejszej strony |restore-request]
 - [Paginowanie wyników bazy danych |pagination]
 - [Dynamiczne fragmenty |dynamic-snippets]
+- [Jak używać atrybutu #Requires |attribute-requires]
+- [Jak prawidłowo używać linków POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formularze
 Wspólne
 -------
 - [Jak załadować plik konfiguracyjny |bootstrap:]
+- [Jak pisać mikrowitryny |microsites]
 - [Dlaczego Nette używa notacji stałej PascalCase? |https://blog.nette.org/pl/aby-mniej-krzyczec-w-kodzie]
 - [Dlaczego Nette nie używa przyrostka Interface? |https://blog.nette.org/pl/przedrostki-i-przyrostki-nie-sa-czescia-nazw-interfejsow]
 - [Kompozytor: wskazówki dotyczące użytkowania |composer]
 - [Porady dotyczące edytorów i narzędzi |editors-and-tools]
+- [Wprowadzenie do programowania obiektowego |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/pl/attribute-requires.texy b/best-practices/pl/attribute-requires.texy
new file mode 100644
index 0000000000..2c79b3fc87
--- /dev/null
+++ b/best-practices/pl/attribute-requires.texy
@@ -0,0 +1,179 @@
+Jak używać atrybutu `#[Requires]` Atrybut
+*****************************************
+
+.[perex]
+Podczas pisania aplikacji internetowej często pojawia się potrzeba ograniczenia dostępu do niektórych jej części. Być może chcesz, aby niektóre żądania mogły wysyłać dane tylko za pośrednictwem formularza (a więc przy użyciu metody POST) lub aby były dostępne tylko dla wywołań AJAX. W Nette Framework 3.2 wprowadzono nowe narzędzie, które pozwala ustawić takie ograniczenia w elegancki i przejrzysty sposób: atrybut `#[Requires]` atrybut.
+
+Atrybut jest specjalnym znacznikiem w PHP, który dodaje się przed definicją klasy lub metody. Ponieważ jest to zasadniczo klasa, musisz dołączyć klauzulę use, aby poniższe przykłady działały:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Atrybutu `#[Requires]` z samą klasą prezentera i tymi metodami:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Dwie ostatnie metody również dotyczą komponentów, więc można użyć atrybutu również z nimi.
+
+Jeśli warunki określone przez atrybut nie są spełnione, wywoływany jest błąd HTTP 4xx.
+
+
+Metody HTTP .[#toc-http-methods]
+--------------------------------
+
+Można określić, które metody HTTP (takie jak GET, POST itp.) są dozwolone dla dostępu. Na przykład, jeśli chcesz zezwolić na dostęp tylko poprzez przesłanie formularza, ustaw:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Dlaczego należy używać POST zamiast GET do akcji zmieniających stan i jak to zrobić? [Przeczytaj przewodnik |post-links].
+
+Można określić metodę lub tablicę metod. Szczególnym przypadkiem jest wartość `'*'`, która włącza wszystkie metody, na które prezentery nie pozwalają domyślnie ze [względów |application:presenters#http-method-check] bezpieczeństwa.
+
+
+Wywołania AJAX .[#toc-ajax-calls]
+---------------------------------
+
+Jeśli chcesz, aby prezenter lub metoda były dostępne tylko dla żądań AJAX, użyj:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+To samo pochodzenie .[#toc-same-origin]
+---------------------------------------
+
+Aby zwiększyć bezpieczeństwo, można wymagać, aby żądanie zostało wykonane z tej samej domeny. Zapobiega to [podatności na CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Dla `handle<Signal>()` automatycznie wymagany jest dostęp z tej samej domeny. Jeśli więc chcesz zezwolić na dostęp z dowolnej domeny, określ:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Dostęp przez Forward .[#toc-access-via-forward]
+-----------------------------------------------
+
+Czasami przydatne jest ograniczenie dostępu do prezentera, tak aby był on dostępny tylko pośrednio, na przykład przy użyciu metod `forward()` lub `switch()` z innego prezentera. W ten sposób chronione są prezentery błędów, aby uniemożliwić ich wywołanie z adresu URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+W praktyce często konieczne jest oznaczenie pewnych widoków, do których można uzyskać dostęp tylko w oparciu o logikę w prezenterze. Ponownie, aby nie można było ich otworzyć bezpośrednio:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Konkretne działania .[#toc-specific-actions]
+--------------------------------------------
+
+Można również ograniczyć dostęp do określonego kodu, takiego jak tworzenie komponentu, tylko dla określonych akcji w prezenterze:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Dla pojedynczej akcji nie ma potrzeby pisania tablicy: `#[Requires(actions: 'default')]`
+
+
+Atrybuty niestandardowe .[#toc-custom-attributes]
+-------------------------------------------------
+
+Jeśli chcesz używać atrybutu `#[Requires]` z tymi samymi ustawieniami, można utworzyć własny atrybut, który będzie dziedziczył `#[Requires]` i ustawić go zgodnie z własnymi potrzebami.
+
+Na przykład, `#[SingleAction]` zezwala na dostęp tylko poprzez akcję `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+lub `#[RestMethods]` umożliwi dostęp za pośrednictwem wszystkich metod HTTP używanych w interfejsie API REST:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Wnioski .[#toc-conclusion]
+--------------------------
+
+Atrybut `#[Requires]` zapewnia dużą elastyczność i kontrolę nad sposobem dostępu do stron internetowych. Korzystając z prostych, ale potężnych reguł, można zwiększyć bezpieczeństwo i prawidłowe funkcjonowanie aplikacji. Jak widać, korzystanie z atrybutów w Nette może nie tylko uprościć pracę, ale także ją zabezpieczyć.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/pl/composer.texy b/best-practices/pl/composer.texy
index f208932801..77950657da 100644
--- a/best-practices/pl/composer.texy
+++ b/best-practices/pl/composer.texy
@@ -142,6 +142,12 @@ Lub bezpośrednio w pliku `composer.json`:
 ```
 
 
+Ignorowanie wersji PHP .[#toc-ignoring-php-version]
+===================================================
+
+Pakiety zazwyczaj określają zarówno najniższą wersję PHP, z którą są kompatybilne, jak i najwyższą wersję, z którą zostały przetestowane. Jeśli planujesz użyć jeszcze nowszej wersji PHP, być może w celach testowych, Composer odmówi instalacji takiego pakietu. Rozwiązaniem jest użycie opcji `--ignore-platform-req=php+`, która powoduje, że Composer ignoruje górne limity wymaganej wersji PHP.
+
+
 Fałszywe raporty .[#toc-false-reports]
 ======================================
 
@@ -183,7 +189,7 @@ Jednakże możliwe jest również użycie Composera do załadowania innych klas
 
 Następnie musisz uruchomić polecenie `composer dumpautoload` za każdym razem, gdy dokonujesz zmiany i masz ponownie wygenerowane tabele autoloader. Jest to niezwykle uciążliwe i zdecydowanie lepiej powierzyć to zadanie [RobotLoaderowi |robot-loader:], który wykonuje tę samą pracę automatycznie w tle i znacznie szybciej.
 
-Inną możliwością jest zastosowanie się do [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Mówiąc najprościej, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów i nazwom plików, więc na przykład `App\Router\RouterFactory` będzie w pliku `/path/to/App/Router/RouterFactory.php`. Przykładowa konfiguracja:
+Inną możliwością jest zastosowanie się do [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Mówiąc najprościej, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów i nazwom plików, więc na przykład `App\Core\RouterFactory` będzie w pliku `/path/to/App/Core/RouterFactory.php`. Przykładowa konfiguracja:
 
 ```js
 {
diff --git a/best-practices/pl/dynamic-snippets.texy b/best-practices/pl/dynamic-snippets.texy
index c1ad93724d..74c1c17c1f 100644
--- a/best-practices/pl/dynamic-snippets.texy
+++ b/best-practices/pl/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Szablon:
 Ajaxizacja .[#toc-ajaxization]
 ==============================
 
-Wyposażmy teraz tę prostą aplikację w AJAX. Zmiana oceny artykułu nie jest na tyle ważna, aby wymagała przekierowania, więc idealnie powinna być wykonana z AJAX w tle. Wykorzystamy [skrypt handler z dodatków ze |https://componette.org/vojtech-dobes/nette.ajax.js/] zwykłą konwencją, że linki AJAX mają klasę CSS `ajax`.
+Wyposażmy teraz tę prostą aplikację w AJAX. Zmiana oceny artykułu nie jest na tyle ważna, aby wymagała przekierowania, więc idealnie powinna być wykonana z AJAX w tle. Wykorzystamy [skrypt handler z dodatków ze |application:ajax#toc-naja] zwykłą konwencją, że linki AJAX mają klasę CSS `ajax`.
 
 Jednak jak to konkretnie zrobić? Nette oferuje 2 ścieżki: tzw. ścieżkę dynamicznych snippetów oraz ścieżkę komponentów. Oba mają swoje plusy i minusy, więc pokażemy je po kolei.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Oczywiście zmienimy szablon widoku i będziemy musieli dodać fabrykę do preze
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/pl/form-reuse.texy b/best-practices/pl/form-reuse.texy
index 46ee665dec..735904cffb 100644
--- a/best-practices/pl/form-reuse.texy
+++ b/best-practices/pl/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Bardzo ważne jest, że wiązanie między klasami `FormFactory` i `EditFormFactory` jest realizowane przez kompozycję, a nie dziedziczenie obiektów:
+Bardzo ważne jest, aby powiązanie między klasami `FormFactory` i `EditFormFactory` było realizowane [przez kompozycję |nette:introduction-to-object-oriented-programming#composition], a nie [dziedziczenie obiektów |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ NIE! DZIEDZICZENIE NIE NALEŻY DO TEGO MIEJSCA
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Używanie dziedziczenia w tym przypadku byłoby całkowicie przeciwne do zamierzonego. Bardzo szybko napotkałbyś problemy. Na przykład, gdybyś chciał dodać parametry do metody `create()`; PHP zgłosiłoby błąd, że jej podpis jest inny niż rodzica.
 Albo podczas przekazywania zależności do klasy `EditFormFactory` poprzez konstruktor. To spowodowałoby coś, co nazywamy [piekłem konstru |dependency-injection:passing-dependencies#Constructor hell]ktora.
 
-Ogólnie rzecz biorąc, lepiej jest preferować kompozycję niż dziedziczenie.
+Ogólnie rzecz biorąc, lepiej jest preferować [kompozycję niż dziedziczenie |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Obsługa formularzy .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/pl/lets-create-contact-form.texy b/best-practices/pl/lets-create-contact-form.texy
index 25c109b3c9..40f832e01b 100644
--- a/best-practices/pl/lets-create-contact-form.texy
+++ b/best-practices/pl/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Jak widać, stworzyliśmy dwie metody. Pierwsza metoda `createComponentContactFo
 Ale co jeśli użytkownik nie wypełni niektórych pól? W takim przypadku powinniśmy dać mu znać, że jest to pole wymagane. Zrobiliśmy to za pomocą metody `setRequired()`.
 Na koniec dodaliśmy również [zdarzenie |nette:glossary#events] `onSuccess`, które jest wywoływane, jeśli formularz zostanie przesłany pomyślnie. W naszym przypadku wywołuje ono metodę `contactFormSucceeded`, która zajmuje się przetwarzaniem przesłanego formularza. Za chwilę dodamy to do kodu.
 
-Niech komponent `contantForm` będzie renderowany w szablonie `templates/Home/default.latte`:
+Niech komponent `contantForm` będzie renderowany w szablonie `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/pl/microsites.texy b/best-practices/pl/microsites.texy
new file mode 100644
index 0000000000..64a7bfcc71
--- /dev/null
+++ b/best-practices/pl/microsites.texy
@@ -0,0 +1,63 @@
+Jak pisać mikrostrony internetowe
+*********************************
+
+Wyobraź sobie, że musisz szybko stworzyć małą stronę internetową na nadchodzące wydarzenie Twojej firmy. Powinna być prosta, szybka i bez zbędnych komplikacji. Można by pomyśleć, że tak mały projekt nie wymaga solidnego frameworka. Ale co, jeśli użycie frameworka Nette może znacznie uprościć i przyspieszyć ten proces?
+
+Nawet tworząc proste strony internetowe, nie chcesz rezygnować z wygody. Nie chcesz wymyślać koła na nowo. Możesz być leniwy i rozpieszczać samego siebie. Nette Framework może być również doskonale wykorzystywany jako mikro framework.
+
+Jak może wyglądać taka mikrostrona? Na przykład, cały kod strony może być umieszczony w pojedynczym pliku `index.php` w folderze publicznym:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// utworzenie kontenera DI na podstawie konfiguracji w config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// skonfigurować routing
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// trasa dla adresu URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// wykrywanie języka przeglądarki i przekierowanie na URL /en lub /de itp.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// trasa dla adresu URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// wyświetla odpowiedni szablon, na przykład ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// uruchom aplikację!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Cała reszta będzie szablonami przechowywanymi w folderze nadrzędnym `/templates`.
+
+Kod PHP w `index.php` najpierw konfiguruje [środowisko |bootstrap:], następnie definiuje [trasy |application:routing#dynamic-routing-with-callbacks], a na końcu uruchamia aplikację. Zaletą jest to, że drugim parametrem funkcji `addRoute()` może być wywołanie, które jest wykonywane po otwarciu odpowiedniej strony.
+
+
+Dlaczego warto używać Nette dla mikrostron? .[#toc-why-use-nette-for-microsites]
+--------------------------------------------------------------------------------
+
+- Programiści, którzy kiedykolwiek wypróbowali [Tracy |tracy:], nie wyobrażają sobie dziś kodowania bez niego.
+- Ale przede wszystkim będziesz korzystać z systemu szablonów [Latte |latte:], ponieważ z zaledwie 2 stron będziesz chciał oddzielić [układ i zawartość |latte:template-inheritance].
+- I zdecydowanie chcesz polegać na [automatycznym uciekaniu |latte:safety-first], aby zapobiec lukom w zabezpieczeniach XSS.
+- Nette zapewnia również, że w przypadku błędu komunikaty o błędach PHP nigdy nie będą wyświetlane, ale zamiast tego pojawi się przyjazna dla użytkownika strona.
+- Jeśli chcesz uzyskać informacje zwrotne od użytkowników, na przykład w formie formularza kontaktowego, możesz również dodać [formularze |forms:] i [bazę danych |database:].
+- Możesz także łatwo wysyłać wypełnione formularze [pocztą e-mail |mail:].
+- Czasami przydatne może okazać się [buforowanie |caching:], na przykład podczas pobierania i wyświetlania kanałów.
+
+W dzisiejszych czasach, gdzie szybkość i wydajność są kluczowe, ważne jest, aby mieć narzędzia, które pozwalają osiągnąć wyniki bez zbędnych opóźnień. Framework Nette oferuje właśnie to - szybki rozwój, bezpieczeństwo i szeroką gamę narzędzi, takich jak Tracy i Latte, które upraszczają proces. Wystarczy zainstalować kilka pakietów Nette, a zbudowanie takiej mikrostrony staje się dziecinnie proste. I wiesz, że nie ma żadnych ukrytych luk w zabezpieczeniach.
diff --git a/best-practices/pl/pagination.texy b/best-practices/pl/pagination.texy
index 83ff2c4cd9..13e39bab4a 100644
--- a/best-practices/pl/pagination.texy
+++ b/best-practices/pl/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Następnie wstrzykujemy klasę modelu w prezenterze i w metodzie render żądamy opublikowanych artykułów do przekazania do szablonu:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-W szablonie zajmujemy się następnie wyszczególnieniem artykułów:
+Szablon `default.latte` zajmie się następnie listą artykułów:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Następnie zabierzemy się do pracy nad modyfikacją prezentera. Do metody rende
 Następnie rozszerzymy również metodę render, aby uzyskać instancję Paginatora, skonfigurować ją i wybrać odpowiednie artykuły do wyświetlenia w szablonie. HomePresenter po modyfikacjach będzie wyglądał tak:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Nie musimy tworzyć Paginatora w prezenterze, zamiast tego używamy metody klasy `Selection` zwracanej przez repozytorium:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/pl/post-links.texy b/best-practices/pl/post-links.texy
new file mode 100644
index 0000000000..9db658ec70
--- /dev/null
+++ b/best-practices/pl/post-links.texy
@@ -0,0 +1,59 @@
+Jak prawidłowo używać linków POST
+*********************************
+
+W aplikacjach internetowych, zwłaszcza w interfejsach administracyjnych, podstawową zasadą powinno być to, że działania zmieniające stan serwera nie powinny być wykonywane za pomocą metody HTTP GET. Jak sugeruje nazwa metody, GET powinien być używany tylko do pobierania danych, a nie do ich zmiany.
+W przypadku działań takich jak usuwanie rekordów, bardziej odpowiednie jest użycie metody POST. Chociaż idealnym rozwiązaniem byłoby użycie metody DELETE, nie można jej wywołać bez JavaScript, dlatego POST jest historycznie używany.
+
+Jak to zrobić w praktyce? Użyj tej prostej sztuczki. Na początku szablonu utwórz formularz pomocniczy o identyfikatorze `postForm`, który następnie użyjesz dla przycisków usuwania:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+W tym formularzu możesz użyć `<button>` zamiast klasycznego linku `<a>` który można wizualnie zmodyfikować, aby wyglądał jak zwykły link. Na przykład framework Bootstrap CSS oferuje klasy `btn btn-link`, które pozwalają na wizualne odróżnienie przycisku od innych linków. Korzystając z atrybutu `form="postForm"`, łączymy go z wcześniej przygotowanym formularzem:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Po kliknięciu linku wywoływana jest akcja `delete`. Aby upewnić się, że żądania są akceptowane tylko za pomocą metody POST i z tej samej domeny (co jest skuteczną obroną przed atakami CSRF), użyj atrybutu `#[Requires]` atrybut:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Atrybut ten jest dostępny od wersji Nette Application 3.2, a więcej o jego możliwościach można dowiedzieć się na stronie [Jak używać atrybutu #Requires |attribute-requires].
+
+Jeśli używasz sygnału `handleDelete()` zamiast akcji `actionDelete()`, nie jest konieczne określanie `sameOrigin: true`, ponieważ sygnały mają domyślnie ustawioną tę ochronę:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Takie podejście nie tylko poprawia bezpieczeństwo aplikacji, ale także przyczynia się do przestrzegania odpowiednich standardów i praktyk internetowych. Używając metod POST dla akcji zmieniających stan, uzyskuje się bardziej niezawodną i bezpieczną aplikację.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/pl/presenter-traits.texy b/best-practices/pl/presenter-traits.texy
index 577763646c..9a5976a811 100644
--- a/best-practices/pl/presenter-traits.texy
+++ b/best-practices/pl/presenter-traits.texy
@@ -2,7 +2,7 @@ Komponowanie prezenterów z cech
 *******************************
 
 .[perex]
-Jeśli potrzebujemy zaimplementować ten sam kod w wielu prezenterach (np. w celu sprawdzenia, czy użytkownik jest zalogowany), sugeruje się umieszczenie kodu we wspólnym przodku. Inną opcją jest tworzenie cech jednozadaniowych.
+Jeśli musimy zaimplementować ten sam kod w wielu prezenterach (np. weryfikacja, czy użytkownik jest zalogowany), kuszące jest umieszczenie kodu we wspólnym przodku. Drugą opcją jest stworzenie [cech |nette:introduction-to-object-oriented-programming#traits] jednego przeznaczenia.
 
 Zaletą tego rozwiązania jest to, że każdy prezenter może używać tylko cech, których faktycznie potrzebuje, podczas gdy wielokrotne dziedziczenie nie jest możliwe w PHP.
 
diff --git a/best-practices/pt/@home.texy b/best-practices/pt/@home.texy
index 5435e5eceb..214aea98f8 100644
--- a/best-practices/pt/@home.texy
+++ b/best-practices/pt/@home.texy
@@ -17,6 +17,8 @@ Aplicação Nette
 - [Como voltar a uma página anterior |restore-request]
 - [Paginação dos resultados do banco de dados |Pagination]
 - [Trechos dinâmicos |dynamic-snippets]
+- [Como usar o atributo #Requires |attribute-requires]
+- [Como usar corretamente os links POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formulários
 Comum
 -----
 - [Como carregar o arquivo de configuração |bootstrap:]
+- [Como escrever microsites |microsites]
 - [Por que a Nette usa a notação constante PascalCase? |https://blog.nette.org/pt/por-menos-gritos-no-codigo]
 - [Por que Nette não usa o sufixo Interface? |https://blog.nette.org/pt/prefixos-e-sufixos-nao-pertencem-a-nomes-de-interface]
 - [Dicas de uso do compositor |composer]
 - [Dicas sobre editores e ferramentas |editors-and-tools]
+- [Introdução à programação orientada a objetos |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/pt/attribute-requires.texy b/best-practices/pt/attribute-requires.texy
new file mode 100644
index 0000000000..af9f1f4ec0
--- /dev/null
+++ b/best-practices/pt/attribute-requires.texy
@@ -0,0 +1,179 @@
+Como usar o `#[Requires]` Atributo
+**********************************
+
+.[perex]
+Ao escrever um aplicativo da Web, você frequentemente se depara com a necessidade de restringir o acesso a determinadas partes do aplicativo. Talvez você queira que algumas solicitações só possam enviar dados por meio de um formulário (usando, portanto, o método POST) ou que sejam acessíveis somente a chamadas AJAX. No Nette Framework 3.2, foi introduzida uma nova ferramenta que permite que você defina essas restrições de forma elegante e clara: o atributo `#[Requires]` atributo.
+
+O atributo é um marcador especial no PHP, que você adiciona antes da definição de uma classe ou método. Como ele é essencialmente uma classe, você precisa incluir a cláusula use para que os exemplos a seguir funcionem:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Você pode usar o atributo `#[Requires]` com a própria classe do apresentador e nesses métodos:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Os dois últimos métodos também se referem a componentes, portanto, você também pode usar o atributo com eles.
+
+Se as condições especificadas pelo atributo não forem atendidas, será acionado um erro HTTP 4xx.
+
+
+Métodos HTTP .[#toc-http-methods]
+---------------------------------
+
+Você pode especificar quais métodos HTTP (como GET, POST, etc.) são permitidos para acesso. Por exemplo, se você quiser permitir o acesso somente por meio do envio de um formulário, defina:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Por que você deve usar POST em vez de GET para ações de alteração de estado e como fazer isso? [Leia o guia |post-links].
+
+Você pode especificar um método ou uma matriz de métodos. Um caso especial é o valor `'*'` para ativar todos os métodos, que os apresentadores não permitem por padrão por [motivos de segurança |application:presenters#http-method-check].
+
+
+Chamadas AJAX .[#toc-ajax-calls]
+--------------------------------
+
+Se você quiser que um apresentador ou método seja acessível somente para solicitações AJAX, use:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Mesma origem .[#toc-same-origin]
+--------------------------------
+
+Para aumentar a segurança, você pode exigir que a solicitação seja feita a partir do mesmo domínio. Isso evita a [vulnerabilidade ao CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Para os métodos `handle<Signal>()` o acesso do mesmo domínio é automaticamente necessário. Portanto, se você quiser permitir o acesso de qualquer domínio, especifique:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Acesso via Forward .[#toc-access-via-forward]
+---------------------------------------------
+
+Às vezes, é útil restringir o acesso a um apresentador para que ele esteja disponível apenas indiretamente, por exemplo, usando os métodos `forward()` ou `switch()` de outro apresentador. É assim que os apresentadores de erros são protegidos para evitar que sejam acionados a partir de um URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Na prática, muitas vezes é necessário marcar determinadas exibições que só podem ser acessadas com base na lógica do apresentador. Novamente, para que elas não possam ser abertas diretamente:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Ações específicas .[#toc-specific-actions]
+------------------------------------------
+
+Você também pode restringir o acesso a determinados códigos, como a criação de um componente, apenas para ações específicas no apresentador:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Para uma única ação, não há necessidade de escrever uma matriz: `#[Requires(actions: 'default')]`
+
+
+Atributos personalizados .[#toc-custom-attributes]
+--------------------------------------------------
+
+Se você quiser usar o atributo `#[Requires]` repetidamente com as mesmas configurações, você pode criar seu próprio atributo que herdará o atributo `#[Requires]` e defini-lo de acordo com suas necessidades.
+
+Por exemplo, `#[SingleAction]` permite o acesso somente por meio da ação `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Ou `#[RestMethods]` permitirá o acesso por meio de todos os métodos HTTP usados para a API REST:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Conclusão .[#toc-conclusion]
+----------------------------
+
+O atributo `#[Requires]` oferece grande flexibilidade e controle sobre como as páginas da Web são acessadas. Usando regras simples, porém poderosas, você pode aumentar a segurança e o funcionamento adequado do seu aplicativo. Como você pode ver, o uso de atributos no Nette pode não apenas simplificar seu trabalho, mas também torná-lo seguro.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/pt/composer.texy b/best-practices/pt/composer.texy
index d6f7112628..bc48d771b3 100644
--- a/best-practices/pt/composer.texy
+++ b/best-practices/pt/composer.texy
@@ -142,6 +142,12 @@ Ou diretamente no arquivo `composer.json':
 ```
 
 
+Ignorando a versão do PHP .[#toc-ignoring-php-version]
+======================================================
+
+Normalmente, os pacotes especificam a versão mais baixa do PHP com a qual são compatíveis e a versão mais alta com a qual foram testados. Se você planeja usar uma versão ainda mais recente do PHP, talvez para fins de teste, o Composer se recusará a instalar esse pacote. A solução é usar a opção `--ignore-platform-req=php+`, que faz com que o Composer ignore os limites superiores da versão do PHP necessária.
+
+
 Falsos relatórios .[#toc-false-reports]
 =======================================
 
@@ -183,7 +189,7 @@ Entretanto, também é possível utilizar o Composer para carregar outras classe
 
 Em seguida, é necessário executar o comando `composer dumpautoload` a cada mudança e deixar as mesas de auto-carga se regenerar. Isto é extremamente inconveniente, e é muito melhor confiar esta tarefa ao [RobotLoader |robot-loader:], que executa a mesma atividade automaticamente em segundo plano e muito mais rápido.
 
-A segunda opção é seguir o [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simplesmente dizendo, é um sistema onde os namespaces e nomes de classes correspondem à estrutura do diretório e nomes de arquivos, ou seja, `App\Router\RouterFactory` está localizado no arquivo `/path/to/App/Router/RouterFactory.php`. Exemplo de configuração:
+A segunda opção é seguir o [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simplesmente dizendo, é um sistema onde os namespaces e nomes de classes correspondem à estrutura do diretório e nomes de arquivos, ou seja, `App\Core\RouterFactory` está localizado no arquivo `/path/to/App/Core/RouterFactory.php`. Exemplo de configuração:
 
 ```js
 {
diff --git a/best-practices/pt/dynamic-snippets.texy b/best-practices/pt/dynamic-snippets.texy
index 660329a182..65434b41c0 100644
--- a/best-practices/pt/dynamic-snippets.texy
+++ b/best-practices/pt/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Modelo:
 Ajaxização .[#toc-ajaxization]
 ==============================
 
-Vamos agora trazer o AJAX para esta simples aplicação. Mudar a classificação de um artigo não é suficientemente importante para exigir um pedido HTTP com redirecionamento, então o ideal é que isso seja feito com AJAX em segundo plano. Usaremos o [script do handler dos add-ons |https://componette.org/vojtech-dobes/nette.ajax.js/] com a convenção usual de que os links AJAX têm a classe CSS `ajax`.
+Vamos agora trazer o AJAX para esta simples aplicação. Mudar a classificação de um artigo não é suficientemente importante para exigir um pedido HTTP com redirecionamento, então o ideal é que isso seja feito com AJAX em segundo plano. Usaremos o [script do handler dos add-ons |application:ajax#toc-naja] com a convenção usual de que os links AJAX têm a classe CSS `ajax`.
 
 No entanto, como fazer isso especificamente? A Nette oferece 2 maneiras: a maneira dinâmica do snippet e a maneira dos componentes. Ambas têm seus prós e contras, por isso vamos mostrar-lhes uma a uma.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Modelo de componente:
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/pt/form-reuse.texy b/best-practices/pt/form-reuse.texy
index 90da87b3c5..7555fad062 100644
--- a/best-practices/pt/form-reuse.texy
+++ b/best-practices/pt/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-É muito importante que a ligação entre as classes `FormFactory` e `EditFormFactory` seja implementada por composição e não por herança de objetos:
+É muito importante que a vinculação entre as classes `FormFactory` e `EditFormFactory` seja implementada [por composição |nette:introduction-to-object-oriented-programming#composition], e não por [herança de objetos |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ NÃO! A HERANÇA NÃO PERTENCE AQUI
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Usar a herança neste caso seria completamente contraproducente. Você se depararia com problemas muito rapidamente. Por exemplo, se você quisesse adicionar parâmetros ao método `create()`; o PHP relataria um erro de que sua assinatura era diferente da dos pais.
 Ou ao passar uma dependência para a classe `EditFormFactory` através do construtor. Isto causaria o que chamamos de [inferno do construtor |dependency-injection:passing-dependencies#Constructor hell].
 
-Em geral, é melhor preferir a composição do que a herança.
+Em geral, é melhor preferir a [composição à herança |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Manuseio de formulários .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/pt/lets-create-contact-form.texy b/best-practices/pt/lets-create-contact-form.texy
index 73db878db9..6fd619dd72 100644
--- a/best-practices/pt/lets-create-contact-form.texy
+++ b/best-practices/pt/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Como você pode ver, nós criamos dois métodos. O primeiro método `createCompo
 Mas e se o usuário não preencher alguns campos? Nesse caso, devemos avisá-lo que se trata de um campo obrigatório. Fizemos isso com o método `setRequired()`.
 Finalmente, adicionamos também um [evento |nette:glossary#events] `onSuccess`, que é acionado se o formulário for submetido com sucesso. Em nosso caso, ele chama o método `contactFormSucceeded`, que se encarrega de processar o formulário submetido. Acrescentaremos isso ao código em um momento.
 
-Deixe o componente `contantForm` ser apresentado no modelo `templates/Home/default.latte`:
+Deixe o componente `contantForm` ser apresentado no modelo `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/pt/microsites.texy b/best-practices/pt/microsites.texy
new file mode 100644
index 0000000000..d436664b88
--- /dev/null
+++ b/best-practices/pt/microsites.texy
@@ -0,0 +1,63 @@
+Como escrever microsites
+************************
+
+Imagine que você precise criar rapidamente um pequeno site para um evento futuro da sua empresa. Ele deve ser simples, rápido e sem complicações desnecessárias. Você pode pensar que um projeto tão pequeno não requer uma estrutura robusta. Mas e se o uso da estrutura Nette pudesse simplificar e acelerar significativamente esse processo?
+
+Mesmo ao criar sites simples, você não quer abrir mão do conforto. Você não quer reinventar a roda. Sinta-se à vontade para ser preguiçoso e se mimar. O Nette Framework também pode ser usado de forma excelente como uma microestrutura.
+
+Como seria esse microsite? Por exemplo, todo o código do site pode ser colocado em um único arquivo `index.php` na pasta pública:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// Crie um contêiner DI com base na configuração em config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// configurar o roteamento
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// rota para o URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// detectar o idioma do navegador e redirecionar para o URL /en ou /de etc.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// rota para o URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// exibir o modelo apropriado, por exemplo, ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// Execute o aplicativo!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Todo o resto serão modelos armazenados na pasta principal `/templates`.
+
+O código PHP em `index.php` primeiro [configura o ambiente |bootstrap:], depois define [as rotas |application:routing#dynamic-routing-with-callbacks] e, por fim, executa o aplicativo. A vantagem é que o segundo parâmetro da função `addRoute()` pode ser um chamável que é executado quando a página correspondente é aberta.
+
+
+Por que usar o Nette para microsites? .[#toc-why-use-nette-for-microsites]
+--------------------------------------------------------------------------
+
+- Os desenvolvedores que já experimentaram [o Tracy |tracy:] não conseguem imaginar a codificação sem ele hoje.
+- Mas, acima de tudo, você utilizará o sistema de modelos [Latte |latte:], pois a partir de apenas duas páginas, você desejará separar [o layout do conteúdo |latte:template-inheritance].
+- E, com certeza, você vai querer contar com o [escape automático |latte:safety-first] para evitar vulnerabilidades de XSS.
+- O Nette também garante que, em caso de erro, as mensagens de erro do PHP nunca serão exibidas, mas, em vez disso, será exibida uma página de fácil utilização.
+- Se quiser obter feedback dos usuários, por exemplo, na forma de um formulário de contato, também é possível adicionar [formulários |forms:] e [banco de dados |database:].
+- Os formulários preenchidos também podem ser facilmente [enviados por e-mail |mail:].
+- Às vezes, o armazenamento [em cache |caching:] pode ser útil, por exemplo, ao baixar e exibir feeds.
+
+Na era atual, em que velocidade e eficiência são fundamentais, é importante ter ferramentas que permitam obter resultados sem atrasos desnecessários. A estrutura Nette oferece exatamente isso: desenvolvimento rápido, segurança e uma ampla variedade de ferramentas, como Tracy e Latte, que simplificam o processo. Basta instalar alguns pacotes Nette e criar um microsite como esse se torna muito fácil. E você sabe que não há falhas de segurança ocultas.
diff --git a/best-practices/pt/pagination.texy b/best-practices/pt/pagination.texy
index dfce31dfc6..149dfc1b72 100644
--- a/best-practices/pt/pagination.texy
+++ b/best-practices/pt/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 No Apresentador injetamos então a classe do modelo e no método de renderização pediremos os artigos publicados que passamos para o modelo:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-No modelo, nós nos encarregaremos de elaborar uma lista de artigos:
+O modelo `default.latte` se encarregará de listar os artigos:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ O próximo passo é editar o apresentador. Nós encaminharemos o número da pág
 Também expandimos o método de renderização para obter a instância Paginator, configurando-a e selecionando os artigos corretos a serem exibidos no modelo. Home PagePresenter terá este aspecto:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Não temos que criar o Paginador no Apresentador, em vez disso usaremos o método do objeto `Selection` devolvido pelo repositório:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/pt/post-links.texy b/best-practices/pt/post-links.texy
new file mode 100644
index 0000000000..453fc217e1
--- /dev/null
+++ b/best-practices/pt/post-links.texy
@@ -0,0 +1,59 @@
+Como usar corretamente os links POST
+************************************
+
+Em aplicativos da Web, especialmente em interfaces administrativas, deve ser uma regra básica que as ações que alteram o estado do servidor não sejam executadas por meio do método HTTP GET. Como o nome do método sugere, o GET deve ser usado somente para recuperar dados, não para alterá-los.
+Para ações como a exclusão de registros, é mais apropriado usar o método POST. Embora o ideal fosse usar o método DELETE, ele não pode ser invocado sem JavaScript, por isso o POST é historicamente usado.
+
+Como fazer isso na prática? Use este truque simples. No início do seu modelo, crie um formulário auxiliar com o identificador `postForm`, que você usará para os botões de exclusão:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Com esse formulário, você pode usar um `<button>` em vez do clássico link `<a>` clássico, que pode ser visualmente modificado para parecer um link normal. Por exemplo, a estrutura CSS do Bootstrap oferece as classes `btn btn-link` que permitem que o botão seja visualmente indistinguível de outros links. Usando o atributo `form="postForm"`, nós o vinculamos ao formulário pré-preparado:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Ao clicar no link, a ação `delete` é invocada. Para garantir que as solicitações sejam aceitas somente por meio do método POST e do mesmo domínio (o que é uma defesa eficaz contra ataques CSRF), use o atributo `#[Requires]` atributo:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+O atributo está disponível desde o Nette Application 3.2, e você pode saber mais sobre seus recursos na página [Como usar o atributo #Requires |attribute-requires].
+
+Se você estiver usando o sinal `handleDelete()` em vez da ação `actionDelete()`, não será necessário especificar `sameOrigin: true`, pois os sinais têm essa proteção definida implicitamente:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Essa abordagem não só aumenta a segurança do seu aplicativo, mas também contribui para a adesão aos padrões e práticas adequados da Web. Ao usar métodos POST para ações de mudança de estado, você obtém um aplicativo mais robusto e seguro.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/pt/presenter-traits.texy b/best-practices/pt/presenter-traits.texy
index 65834541f8..d65e2304a4 100644
--- a/best-practices/pt/presenter-traits.texy
+++ b/best-practices/pt/presenter-traits.texy
@@ -2,7 +2,7 @@ Composição dos apresentadores a partir de traços
 ************************************************
 
 .[perex]
-Se precisarmos implementar o mesmo código em vários apresentadores (por exemplo, verificação de que o usuário está logado), é tentador colocar o código em um ancestral comum. A segunda opção é criar características de uso único.
+Se precisarmos implementar o mesmo código em vários apresentadores (por exemplo, verificação de que o usuário está conectado), é tentador colocar o código em um ancestral comum. A segunda opção é criar [características |nette:introduction-to-object-oriented-programming#traits] de finalidade única.
 
 A vantagem desta solução é que cada apresentador pode usar apenas os traços de que realmente precisa, enquanto a herança múltipla não é possível em PHP.
 
diff --git a/best-practices/ro/@home.texy b/best-practices/ro/@home.texy
index 823591e492..a1fa6467dc 100644
--- a/best-practices/ro/@home.texy
+++ b/best-practices/ro/@home.texy
@@ -17,6 +17,8 @@ Aplicație Nette
 - [Cum să vă întoarceți la o pagină anterioară |restore-request]
 - [Paginarea rezultatelor bazei de date |Pagination]
 - [Fragmente dinamice |dynamic-snippets]
+- [Cum se utilizează atributul #Requires |attribute-requires]
+- [Cum se utilizează corect linkurile POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formulare
 Comună
 ------
 - [Cum se încarcă fișierul de configurare |bootstrap:]
+- [Cum să scrieți microsite-uri |microsites]
 - [De ce Nette folosește notația constantă PascalCase? |https://blog.nette.org/ro/pentru-mai-putine-tipete-in-cod]
 - [De ce Nette nu folosește sufixul Interface? |https://blog.nette.org/ro/prefixele-si-sufixele-nu-se-regasesc-in-numele-interfetelor]
 - [Sfaturi pentru utilizarea Composer |composer]
 - [Sfaturi privind editorii și instrumentele |editors-and-tools]
+- [Introducere în programarea orientată pe obiecte |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/ro/attribute-requires.texy b/best-practices/ro/attribute-requires.texy
new file mode 100644
index 0000000000..7d541aaa50
--- /dev/null
+++ b/best-practices/ro/attribute-requires.texy
@@ -0,0 +1,179 @@
+Cum se utilizează `#[Requires]` Atributul
+*****************************************
+
+.[perex]
+Atunci când scrieți o aplicație web, vă confruntați adesea cu necesitatea de a restricționa accesul la anumite părți ale aplicației. Poate doriți ca unele cereri să poată trimite date doar prin intermediul unui formular (utilizând astfel metoda POST) sau să fie accesibile doar apelurilor AJAX. În Nette Framework 3.2, a fost introdus un nou instrument care vă permite să stabiliți astfel de restricții în mod elegant și clar: instrumentul `#[Requires]` atribut.
+
+Atributul este un marker special în PHP, pe care îl adăugați înainte de definiția unei clase sau metode. Deoarece este în esență o clasă, trebuie să includeți clauza use pentru ca următoarele exemple să funcționeze:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Puteți utiliza funcția `#[Requires]` cu clasa presenter în sine și cu aceste metode:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Ultimele două metode se referă, de asemenea, la componente, astfel încât puteți utiliza atributul și cu acestea.
+
+În cazul în care condițiile specificate de atribut nu sunt îndeplinite, se declanșează o eroare HTTP 4xx.
+
+
+Metode HTTP .[#toc-http-methods]
+--------------------------------
+
+Puteți specifica ce metode HTTP (cum ar fi GET, POST etc.) sunt permise pentru acces. De exemplu, dacă doriți să permiteți accesul numai prin trimiterea unui formular, setați:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+De ce ar trebui să folosiți POST în loc de GET pentru acțiunile de schimbare a stării și cum să faceți acest lucru? [Citiți ghidul |post-links].
+
+Puteți specifica o metodă sau o serie de metode. Un caz special este valoarea `'*'` pentru a activa toate metodele, pe care prezentatorii nu o permit în mod implicit din [motive de securitate |application:presenters#http-method-check].
+
+
+Apeluri AJAX .[#toc-ajax-calls]
+-------------------------------
+
+Dacă doriți ca un prezentator sau o metodă să fie accesibilă numai pentru cererile AJAX, utilizați:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Aceeași origine .[#toc-same-origin]
+-----------------------------------
+
+Pentru a spori securitatea, puteți solicita ca solicitarea să fie făcută din același domeniu. Acest lucru previne [vulnerabilitatea la CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Pentru `handle<Signal>()` este necesar în mod automat accesul din același domeniu. Prin urmare, dacă doriți să permiteți accesul din orice domeniu, specificați:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Acces prin Forward .[#toc-access-via-forward]
+---------------------------------------------
+
+Uneori este util să se restricționeze accesul la un prezentator astfel încât acesta să fie disponibil doar indirect, de exemplu, prin utilizarea metodelor `forward()` sau `switch()` de la un alt prezentator. Acesta este modul în care sunt protejați prezentatorii de erori pentru a împiedica declanșarea lor de la un URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+În practică, este adesea necesar să se marcheze anumite vizualizări care pot fi accesate numai pe baza logicii din prezentator. Din nou, pentru ca acestea să nu poată fi deschise direct:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Acțiuni specifice .[#toc-specific-actions]
+------------------------------------------
+
+Puteți, de asemenea, să restricționați accesul la anumite coduri, cum ar fi crearea unei componente, numai pentru anumite acțiuni din prezentator:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Pentru o singură acțiune, nu este nevoie să scrieți o matrice: `#[Requires(actions: 'default')]`
+
+
+Atribute personalizate .[#toc-custom-attributes]
+------------------------------------------------
+
+Dacă doriți să utilizați `#[Requires]` în mod repetat cu aceleași setări, puteți crea propriul atribut care va moșteni atributul `#[Requires]` și să îl setați în funcție de nevoile dumneavoastră.
+
+De exemplu, `#[SingleAction]` permite accesul numai prin intermediul acțiunii `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Sau `#[RestMethods]` va permite accesul prin toate metodele HTTP utilizate pentru API REST:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Concluzie .[#toc-conclusion]
+----------------------------
+
+The `#[Requires]` vă oferă o mare flexibilitate și control asupra modului în care sunt accesate paginile dvs. web. Utilizând reguli simple, dar puternice, puteți spori securitatea și buna funcționare a aplicației dumneavoastră. După cum puteți vedea, utilizarea atributelor în Nette nu numai că vă poate simplifica munca, dar o poate și securiza.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/ro/composer.texy b/best-practices/ro/composer.texy
index ef98ebdb69..0905a7c202 100644
--- a/best-practices/ro/composer.texy
+++ b/best-practices/ro/composer.texy
@@ -142,6 +142,12 @@ Sau direct în fișierul `composer.json`:
 ```
 
 
+Ignorarea versiunii PHP .[#toc-ignoring-php-version]
+====================================================
+
+Pachetele specifică de obicei atât cea mai mică versiune de PHP cu care sunt compatibile, cât și cea mai mare versiune cu care au fost testate. Dacă intenționați să utilizați o versiune chiar mai nouă de PHP, poate în scopuri de testare, Composer va refuza să instaleze un astfel de pachet. Soluția este de a utiliza opțiunea `--ignore-platform-req=php+`, care face ca Composer să ignore limitele superioare ale versiunii PHP solicitate.
+
+
 Rapoarte false .[#toc-false-reports]
 ====================================
 
@@ -183,7 +189,7 @@ Cu toate acestea, este de asemenea posibil să utilizați Composer pentru a înc
 
 Ulterior, este necesar să executați comanda `composer dumpautoload` cu fiecare modificare și să lăsați tabelele de autoloading să se regenereze. Acest lucru este extrem de incomod și este mult mai bine să încredințați această sarcină lui [RobotLoader |robot-loader:], care efectuează aceeași activitate în mod automat în fundal și mult mai rapid.
 
-A doua opțiune este să urmați [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Spunând simplu, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, adică `App\Router\RouterFactory` se află în fișierul `/path/to/App/Router/RouterFactory.php`. Exemplu de configurare:
+A doua opțiune este să urmați [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Spunând simplu, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, adică `App\Core\RouterFactory` se află în fișierul `/path/to/App/Core/RouterFactory.php`. Exemplu de configurare:
 
 ```js
 {
diff --git a/best-practices/ro/dynamic-snippets.texy b/best-practices/ro/dynamic-snippets.texy
index c5201295d5..3635169fd9 100644
--- a/best-practices/ro/dynamic-snippets.texy
+++ b/best-practices/ro/dynamic-snippets.texy
@@ -35,7 +35,7 @@ public function handleUnlike(int $articleId): void
 Ajaxizare .[#toc-ajaxization]
 =============================
 
-Să aducem acum AJAX în această aplicație simplă. Modificarea ratingului unui articol nu este suficient de importantă pentru a necesita o cerere HTTP cu redirecționare, așa că, în mod ideal, ar trebui să se facă cu AJAX în fundal. Vom folosi [scriptul handler din add-ons |https://componette.org/vojtech-dobes/nette.ajax.js/] cu convenția obișnuită ca legăturile AJAX să aibă clasa CSS `ajax`.
+Să aducem acum AJAX în această aplicație simplă. Modificarea ratingului unui articol nu este suficient de importantă pentru a necesita o cerere HTTP cu redirecționare, așa că, în mod ideal, ar trebui să se facă cu AJAX în fundal. Vom folosi [scriptul handler din add-ons |application:ajax#toc-naja] cu convenția obișnuită ca legăturile AJAX să aibă clasa CSS `ajax`.
 
 Totuși, cum să o facem în mod specific? Nette oferă 2 modalități: modalitatea cu fragmente dinamice și modalitatea cu componente. Ambele au avantajele și dezavantajele lor, așa că le vom prezenta pe rând.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Bineînțeles că vom schimba șablonul de vizualizare și va trebui să adăug
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/ro/form-reuse.texy b/best-practices/ro/form-reuse.texy
index 0f1e60600b..4c9d7dede0 100644
--- a/best-practices/ro/form-reuse.texy
+++ b/best-practices/ro/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Este foarte important ca legătura dintre clasele `FormFactory` și `EditFormFactory` să fie implementată prin compoziție, nu prin moștenirea obiectelor:
+Este foarte important ca legătura dintre clasele `FormFactory` și `EditFormFactory` să fie implementată [prin compoziție |nette:introduction-to-object-oriented-programming#composition], nu prin [moștenirea obiectelor |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ NU! MOȘTENIREA NU ARE CE CĂUTA AICI
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Utilizarea moștenirii în acest caz ar fi complet contraproductivă. Ați întâmpina foarte repede probleme. De exemplu, dacă ați dori să adăugați parametri la metoda `create()`, PHP ar raporta o eroare deoarece semnătura acesteia este diferită de cea a metodei părinte.
 Sau atunci când treceți o dependență clasei `EditFormFactory` prin intermediul constructorului. Acest lucru ar cauza ceea ce numim " [iadul constructorilor |dependency-injection:passing-dependencies#Constructor hell]".
 
-În general, este mai bine să preferați compoziția decât moștenirea.
+În general, este mai bine să se prefere [compoziția decât moștenirea |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Gestionarea formularelor .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/ro/lets-create-contact-form.texy b/best-practices/ro/lets-create-contact-form.texy
index eecffd9791..42435507e4 100644
--- a/best-practices/ro/lets-create-contact-form.texy
+++ b/best-practices/ro/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ După cum puteți vedea, am creat două metode. Prima metodă `createComponentCo
 Dar ce se întâmplă dacă utilizatorul nu completează unele câmpuri? În acest caz, ar trebui să-l anunțăm că este un câmp obligatoriu. Am făcut acest lucru cu metoda `setRequired()`.
 În cele din urmă, am adăugat și un [eveniment |nette:glossary#events] `onSuccess`, care este declanșat dacă formularul este trimis cu succes. În cazul nostru, acesta apelează metoda `contactFormSucceeded`, care se ocupă de procesarea formularului trimis. Vom adăuga acest lucru în cod imediat.
 
-Lăsați componenta `contantForm` să fie redată în șablonul `templates/Home/default.latte`:
+Lăsați componenta `contantForm` să fie redată în șablonul `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/ro/microsites.texy b/best-practices/ro/microsites.texy
new file mode 100644
index 0000000000..bdeb94a83c
--- /dev/null
+++ b/best-practices/ro/microsites.texy
@@ -0,0 +1,63 @@
+Cum să scrieți microsite-uri
+****************************
+
+Imaginați-vă că trebuie să creați rapid un mic site web pentru un eveniment viitor al companiei dumneavoastră. Acesta trebuie să fie simplu, rapid și fără complicații inutile. S-ar putea să vă gândiți că un proiect atât de mic nu necesită un framework robust. Dar dacă utilizarea cadrului Nette ar putea simplifica și accelera semnificativ acest proces?
+
+Chiar și atunci când creați site-uri web simple, nu doriți să renunțați la confort. Nu doriți să reinventați roata. Simțiți-vă liber să fiți leneș și să vă răsfățați. Cadrul Nette Framework poate fi folosit excelent și ca microcadru.
+
+Cum ar putea arăta un astfel de microsite? De exemplu, întregul cod al site-ului poate fi plasat într-un singur fișier `index.php` în folderul public:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// creați un container DI pe baza configurației din config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// configurați rutarea
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// ruta pentru URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// detectează limba browserului și redirecționează la URL /en sau /de etc.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// ruta pentru URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// afișează șablonul corespunzător, de exemplu ../template/ro.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// rulați aplicația!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Restul vor fi șabloane stocate în dosarul părinte `/templates`.
+
+Codul PHP din `index.php` [stabilește |bootstrap:] mai întâi [mediul |bootstrap:], apoi definește [rutele |application:routing#dynamic-routing-with-callbacks] și, în final, rulează aplicația. Avantajul este că al doilea parametru al funcției `addRoute()` poate fi un callable care este executat atunci când se deschide pagina corespunzătoare.
+
+
+De ce să folosiți Nette pentru microsite-uri? .[#toc-why-use-nette-for-microsites]
+----------------------------------------------------------------------------------
+
+- Dezvoltatorii care au încercat vreodată [Tracy |tracy:] nu-și pot imagina astăzi codarea fără el.
+- Dar, mai presus de toate, veți utiliza sistemul de template-uri [Latte |latte:], deoarece de la doar 2 pagini, veți dori să separați [aspectul și conținutul |latte:template-inheritance].
+- Și, cu siguranță, veți dori să vă bazați pe [escape-ul automat |latte:safety-first] pentru a preveni vulnerabilitățile XSS.
+- De asemenea, Latte se asigură că, în caz de eroare, nu vor fi afișate niciodată mesaje de eroare PHP, ci în schimb, o pagină ușor de utilizat.
+- Dacă doriți să obțineți feedback de la utilizatori, de exemplu sub forma unui formular de contact, puteți adăuga, de asemenea, [formulare |forms:] și [bază de date |database:].
+- De asemenea, puteți face cu ușurință ca formularele completate să fie [trimise prin e-mail |mail:].
+- Uneori s-ar putea să vă fie utilă [memoria cache |caching:], de exemplu, atunci când descărcați și afișați fluxuri.
+
+În epoca actuală, în care viteza și eficiența sunt esențiale, este important să dispuneți de instrumente care vă permit să obțineți rezultate fără întârzieri inutile. Cadrul Nette oferă exact acest lucru - dezvoltare rapidă, securitate și o gamă largă de instrumente precum Tracy și Latte, care simplifică procesul. Este suficient să instalați câteva pachete Nette, iar construirea unui astfel de microsite devine o joacă de copii. Și știți că nu există defecte de securitate ascunse.
diff --git a/best-practices/ro/pagination.texy b/best-practices/ro/pagination.texy
index 4175e89bd9..ee9ac16acc 100644
--- a/best-practices/ro/pagination.texy
+++ b/best-practices/ro/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 În Presenter vom injecta apoi clasa model, iar în metoda render vom cere articolele publicate pe care le vom trece în șablon:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-În șablon, ne vom ocupa de redarea unei liste de articole:
+Șablonul `default.latte` se va ocupa apoi de listarea articolelor:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Următorul pas este să modificăm prezentatorul. Vom transmite numărul paginii
 De asemenea, extindem metoda de randare pentru a obține instanța Paginator, configurând-o și selectând articolele corecte pentru a fi afișate în șablon. HomePresenter va arăta astfel:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Nu trebuie să creăm Paginator în Presenter, în schimb vom folosi metoda obiectului `Selection` returnat de depozit:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/ro/post-links.texy b/best-practices/ro/post-links.texy
new file mode 100644
index 0000000000..d81e2aa8bb
--- /dev/null
+++ b/best-practices/ro/post-links.texy
@@ -0,0 +1,59 @@
+Cum să folosiți corect legăturile POST
+**************************************
+
+În aplicațiile web, în special în interfețele administrative, ar trebui să fie o regulă de bază ca acțiunile care modifică starea serverului să nu fie efectuate prin metoda HTTP GET. După cum sugerează și numele metodei, GET ar trebui să fie utilizată numai pentru a prelua date, nu pentru a le modifica.
+Pentru acțiuni precum ștergerea înregistrărilor, este mai indicat să se utilizeze metoda POST. Deși ideal ar fi să se folosească metoda DELETE, aceasta nu poate fi invocată fără JavaScript, de aceea se folosește în mod obișnuit metoda POST.
+
+Cum se procedează în practică? Folosiți acest truc simplu. La începutul șablonului dumneavoastră, creați un formular ajutător cu identificatorul `postForm`, pe care îl veți folosi apoi pentru butoanele de ștergere:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Cu acest formular, puteți utiliza un `<button>` în loc de clasicul `<a>` care poate fi modificat vizual pentru a arăta ca un link obișnuit. De exemplu, cadrul CSS Bootstrap oferă clasele `btn btn-link` care permit ca butonul să nu se distingă vizual de alte linkuri. Folosind atributul `form="postForm"`, îl legăm la formularul pregătit în prealabil:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Atunci când se face clic pe link, acțiunea `delete` este acum invocată. Pentru a vă asigura că cererile sunt acceptate numai prin metoda POST și din același domeniu (ceea ce reprezintă o apărare eficientă împotriva atacurilor CSRF), utilizați atributul `#[Requires]` attribute:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Atributul este disponibil de la Nette Application 3.2 și puteți afla mai multe despre capacitățile sale pe pagina [Cum se utilizează atributul #Requires |attribute-requires].
+
+Dacă foloseați semnalul `handleDelete()` în loc de acțiunea `actionDelete()`, nu este necesar să specificați `sameOrigin: true`, deoarece semnalele au această protecție setată implicit:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Această abordare nu numai că îmbunătățește securitatea aplicației dumneavoastră, dar contribuie, de asemenea, la respectarea standardelor și practicilor web adecvate. Prin utilizarea metodelor POST pentru acțiunile de schimbare a stării, obțineți o aplicație mai robustă și mai sigură.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/ro/presenter-traits.texy b/best-practices/ro/presenter-traits.texy
index 496296a400..a3c77846b7 100644
--- a/best-practices/ro/presenter-traits.texy
+++ b/best-practices/ro/presenter-traits.texy
@@ -2,7 +2,7 @@ Compunerea prezentatorilor din trăsături
 ****************************************
 
 .[perex]
-Dacă trebuie să implementăm același cod în mai multe prezentări (de exemplu, verificarea faptului că utilizatorul este conectat), este tentant să plasăm codul într-un strămoș comun. A doua opțiune este crearea unor trăsături cu scop unic.
+Dacă trebuie să implementăm același cod în mai multe prezentări (de exemplu, verificarea faptului că utilizatorul este conectat), este tentant să plasăm codul într-un strămoș comun. A doua opțiune este de a crea [trăsături |nette:introduction-to-object-oriented-programming#traits] cu scop unic.
 
 Avantajul acestei soluții este că fiecare prezentator poate utiliza doar trăsăturile de care are nevoie efectiv, în timp ce moștenirea multiplă nu este posibilă în PHP.
 
diff --git a/best-practices/ru/@home.texy b/best-practices/ru/@home.texy
index 05f2905032..103103ada6 100644
--- a/best-practices/ru/@home.texy
+++ b/best-practices/ru/@home.texy
@@ -17,6 +17,8 @@
 - [Как вернуться на предыдущую страницу |restore-request]
 - [Пагинация результатов базы данных |Pagination]
 - [Динамические фрагменты |dynamic-snippets]
+- [Как использовать атрибут #Requires |attribute-requires]
+- [Как правильно использовать POST-ссылки |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@
 Общие
 -----
 - [Как загрузить файл конфигурации |bootstrap:]
+- [Как писать микросайты |microsites]
 - [Почему Nette использует константную нотацию PascalCase? |https://blog.nette.org/ru/ctoby-men-se-kricat-v-kode]
 - [Почему Nette не использует суффикс Interface? |https://blog.nette.org/ru/prefiksy-i-suffiksy-ne-dolzny-prisutstvovat-v-imenah-interfejsov]
 - [Советы по использованию Composer |composer]
 - [Советы по редакторам и инструментам |editors-and-tools]
+- [Введение в объектно-ориентированное программирование |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/ru/attribute-requires.texy b/best-practices/ru/attribute-requires.texy
new file mode 100644
index 0000000000..f91273fa06
--- /dev/null
+++ b/best-practices/ru/attribute-requires.texy
@@ -0,0 +1,179 @@
+Как использовать `#[Requires]` Атрибут
+**************************************
+
+.[perex]
+При написании веб-приложений вы часто сталкиваетесь с необходимостью ограничить доступ к определенным частям вашего приложения. Возможно, вы хотите, чтобы некоторые запросы могли отправлять данные только через форму (таким образом, используя метод POST) или были доступны только для вызовов AJAX. В Nette Framework 3.2 появился новый инструмент, позволяющий элегантно и четко задать такие ограничения: атрибут `#[Requires]` атрибут.
+
+Атрибут - это специальный маркер в PHP, который добавляется перед определением класса или метода. Так как по сути это класс, вам необходимо включить условие use, чтобы следующие примеры работали:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Вы можете использовать атрибут `#[Requires]` атрибут в самом классе ведущего и в этих методах:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Последние два метода также относятся к компонентам, поэтому вы можете использовать атрибут и с ними.
+
+Если условия, указанные в атрибуте, не выполняются, возникает ошибка HTTP 4xx.
+
+
+Методы HTTP .[#toc-http-methods]
+--------------------------------
+
+Вы можете указать, какие методы HTTP (такие как GET, POST и т. д.) разрешены для доступа. Например, если вы хотите разрешить доступ только при отправке формы, установите:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Почему для действий, изменяющих состояние, следует использовать POST, а не GET, и как это сделать? [Читайте руководство |post-links].
+
+Вы можете указать метод или массив методов. Особым случаем является значение `'*'` для включения всех методов, что по умолчанию не разрешается презентаторами из [соображений безопасности |application:presenters#http-method-check].
+
+
+Вызовы AJAX .[#toc-ajax-calls]
+------------------------------
+
+Если вы хотите, чтобы ведущий или метод был доступен только для AJAX-запросов, используйте:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+То же происхождение .[#toc-same-origin]
+---------------------------------------
+
+Для повышения безопасности можно потребовать, чтобы запрос выполнялся из одного и того же домена. Это предотвратит [уязвимость к CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Для `handle<Signal>()` методов автоматически требуется доступ из того же домена. Поэтому, если вы хотите разрешить доступ из любого домена, укажите:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Доступ через Forward .[#toc-access-via-forward]
+-----------------------------------------------
+
+Иногда полезно ограничить доступ к презентатору так, чтобы он был доступен только косвенно, например, с помощью методов `forward()` или `switch()` из другого презентатора. Так защищаются презентаторы ошибок, чтобы их нельзя было вызвать с URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+На практике часто возникает необходимость пометить определенные представления, доступ к которым возможен только на основе логики в презентере. Опять же, чтобы их нельзя было открыть напрямую:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Конкретные действия .[#toc-specific-actions]
+--------------------------------------------
+
+Вы также можете ограничить доступ к определенному коду, например к созданию компонента, только для определенных действий в презентере:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Для одного действия нет необходимости писать массив: `#[Requires(actions: 'default')]`
+
+
+Пользовательские атрибуты .[#toc-custom-attributes]
+---------------------------------------------------
+
+Если вы хотите использовать атрибут `#[Requires]` атрибут многократно с одними и теми же настройками, вы можете создать собственный атрибут, который будет наследоваться `#[Requires]` и настроить его в соответствии с вашими потребностями.
+
+Например, `#[SingleAction]` разрешает доступ только через действие `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Или `#[RestMethods]` позволит получить доступ через все методы HTTP, используемые для REST API:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Заключение .[#toc-conclusion]
+-----------------------------
+
+Атрибут `#[Requires]` предоставляет вам большую гибкость и контроль над тем, как осуществляется доступ к вашим веб-страницам. Используя простые, но мощные правила, вы можете повысить безопасность и правильное функционирование вашего приложения. Как видите, использование атрибутов в Nette может не только упростить вашу работу, но и обезопасить ее.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/ru/composer.texy b/best-practices/ru/composer.texy
index 8b6c3fca4a..6e77697023 100644
--- a/best-practices/ru/composer.texy
+++ b/best-practices/ru/composer.texy
@@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update
 ```
 
 
+Игнорирование версии PHP .[#toc-ignoring-php-version]
+=====================================================
+
+В пакетах обычно указывается как самая низкая версия PHP, с которой они совместимы, так и самая высокая версия, с которой они были протестированы. Если вы планируете использовать еще более новую версию PHP, возможно, в целях тестирования, Composer откажется устанавливать такой пакет. Решением является использование опции `--ignore-platform-req=php+`, которая заставляет Composer игнорировать верхние границы требуемой версии PHP.
+
+
 Ложные отчеты .[#toc-false-reports]
 ===================================
 
@@ -183,7 +189,7 @@ Packagist.org — глобальный репозиторий .[#toc-packagist-o
 
 Впоследствии необходимо выполнять команду `composer dumpautoload` при каждом изменении и позволять таблицам автозагрузки регенерироваться. Это крайне неудобно, и гораздо лучше доверить эту задачу [RobotLoader|robot-loader:], который выполняет ту же самую работу автоматически в фоновом режиме и гораздо быстрее.
 
-Второй вариант — следовать [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, т. е. `App\Router\RouterFactory` находится в файле `/path/to/App/Router/RouterFactory.php`. Пример конфигурации:
+Второй вариант — следовать [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, т. е. `App\Core\RouterFactory` находится в файле `/path/to/App/Core/RouterFactory.php`. Пример конфигурации:
 
 ```js
 {
diff --git a/best-practices/ru/dynamic-snippets.texy b/best-practices/ru/dynamic-snippets.texy
index 744b905458..2d90f071b4 100644
--- a/best-practices/ru/dynamic-snippets.texy
+++ b/best-practices/ru/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template:
 Аяксизация .[#toc-ajaxization]
 ==============================
 
-Теперь давайте привнесем AJAX в это простое приложение. Изменение рейтинга статьи не настолько важно, чтобы требовать HTTP-запрос с перенаправлением, поэтому в идеале это должно быть сделано с помощью AJAX в фоновом режиме. Мы будем использовать [скрипт обработчика из дополнений |https://componette.org/vojtech-dobes/nette.ajax.js/] с обычным соглашением, что AJAX ссылки имеют CSS класс `ajax`.
+Теперь давайте привнесем AJAX в это простое приложение. Изменение рейтинга статьи не настолько важно, чтобы требовать HTTP-запрос с перенаправлением, поэтому в идеале это должно быть сделано с помощью AJAX в фоновом режиме. Мы будем использовать [скрипт обработчика из дополнений |application:ajax#toc-naja] с обычным соглашением, что AJAX ссылки имеют CSS класс `ajax`.
 
 Однако как это сделать конкретно? Nette предлагает 2 способа: способ динамических фрагментов и способ компонентов. У обоих есть свои плюсы и минусы, поэтому мы покажем их по очереди.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ class LikeControl extends Nette\Application\UI\Control
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/ru/form-reuse.texy b/best-practices/ru/form-reuse.texy
index 534ce944d8..f79fc541af 100644
--- a/best-practices/ru/form-reuse.texy
+++ b/best-practices/ru/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Очень важно, чтобы связь между классами `FormFactory` и `EditFormFactory` была реализована композицией, а не наследованием объектов:
+Очень важно, что привязка между классами `FormFactory` и `EditFormFactory` осуществляется [путем композиции |nette:introduction-to-object-oriented-programming#composition], а не [наследования объектов |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ НЕТ! НАСЛЕДСТВУ ЗДЕСЬ НЕ МЕСТО
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Использование наследования в этом случае было бы совершенно непродуктивным. Вы бы очень быстро столкнулись с проблемами. Например, если бы вы захотели добавить параметры в метод `create()`, PHP выдал бы ошибку, что его сигнатура отличается от родительской.
 Или при передаче зависимости классу `EditFormFactory` через конструктор. Это привело бы к тому, что мы называем " [ад конструктора |dependency-injection:passing-dependencies#Constructor hell]".
 
-В целом, лучше предпочесть композицию наследованию.
+В целом лучше отдать предпочтение [композиции, а не наследованию |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Работа с формами .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/ru/lets-create-contact-form.texy b/best-practices/ru/lets-create-contact-form.texy
index f81335f4ef..bed8cf51df 100644
--- a/best-practices/ru/lets-create-contact-form.texy
+++ b/best-practices/ru/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ class HomePresenter extends Presenter
 Но что, если пользователь не заполнит некоторые поля? В этом случае мы должны сообщить ему, что это обязательное поле. Мы сделали это с помощью метода `setRequired()`.
 Наконец, мы также добавили [событие |nette:glossary#events] `onSuccess`, которое срабатывает в случае успешной отправки формы. В нашем случае оно вызывает метод `contactFormSucceeded`, который обрабатывает отправленную форму. Мы добавим это в код через некоторое время.
 
-Пусть компонент `contantForm` будет отображен в шаблоне `templates/Home/default.latte`:
+Пусть компонент `contantForm` будет отображен в шаблоне `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/ru/microsites.texy b/best-practices/ru/microsites.texy
new file mode 100644
index 0000000000..4db9a76100
--- /dev/null
+++ b/best-practices/ru/microsites.texy
@@ -0,0 +1,63 @@
+Как писать микросайты
+*********************
+
+Представьте себе, что вам нужно быстро создать небольшой сайт для предстоящего мероприятия вашей компании. Он должен быть простым, быстрым и без лишних сложностей. Вы можете подумать, что для такого небольшого проекта не нужен надежный фреймворк. Но что если использование фреймворка Nette значительно упростит и ускорит этот процесс?
+
+Даже при создании простых сайтов не стоит отказываться от удобства. Не стоит изобретать колесо. Не стесняйтесь лениться и баловать себя. Фреймворк Nette Framework можно прекрасно использовать и в качестве микрофреймворка.
+
+Как может выглядеть такой микросайт? Например, весь код сайта может быть размещен в одном файле `index.php` в общей папке:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// создание DI-контейнера на основе конфигурации в config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// настройка маршрутизации
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// маршрут для URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// определять язык браузера и перенаправлять на URL /en или /de и т.д.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// маршрут для URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// отобразить соответствующий шаблон, например ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// запустите приложение!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Все остальное будет представлять собой шаблоны, хранящиеся в родительской папке `/templates`.
+
+PHP-код в папке `index.php` сначала устанавливает [окружение |bootstrap:], затем определяет [маршруты |application:routing#dynamic-routing-with-callbacks] и, наконец, запускает приложение. Преимуществом является то, что вторым параметром функции `addRoute()` может быть вызываемая переменная, которая выполняется при открытии соответствующей страницы.
+
+
+Почему стоит использовать Nette для микросайтов? .[#toc-why-use-nette-for-microsites]
+-------------------------------------------------------------------------------------
+
+- Разработчики, которые когда-либо пробовали [Tracy |tracy:], сегодня не могут представить себе кодирование без нее.
+- Но прежде всего вам пригодится система шаблонов [Latte |latte:], поскольку всего с 2 страниц вы захотите разделить [верстку и контент |latte:template-inheritance].
+- А для предотвращения XSS-уязвимостей вам обязательно понадобится [автоматическое экранирование |latte:safety-first].
+- Nette также гарантирует, что в случае ошибки никогда не будут выводиться сообщения об ошибках PHP, а вместо них будет отображаться удобная для пользователя страница.
+- Если вы хотите получать обратную связь от пользователей, например, в виде контактной формы, вы также можете добавить [формы |forms:] и [базу данных |database:].
+- Кроме того, заполненные формы можно легко отправить по [электронной почте |mail:].
+- Иногда может пригодиться [кэширование |caching:], например, при загрузке и отображении лент.
+
+В наше время, когда скорость и эффективность являются ключевыми факторами, важно иметь инструменты, позволяющие достигать результатов без лишних задержек. Фреймворк Nette предлагает именно такие инструменты - быструю разработку, безопасность и широкий набор средств, таких как Tracy и Latte, которые упрощают процесс. Достаточно установить несколько пакетов Nette, и создание такого микросайта превращается в легкое дело. При этом вы будете уверены, что в системе безопасности нет никаких скрытых недостатков.
diff --git a/best-practices/ru/pagination.texy b/best-practices/ru/pagination.texy
index 11f52f40f2..87693d2c25 100644
--- a/best-practices/ru/pagination.texy
+++ b/best-practices/ru/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Затем в презентере мы вводим класс модели и в методе `render` запрашиваем опубликованные статьи, которые передаем в шаблон:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-В шаблоне мы позаботимся о выводе списка статей:
+Шаблон `default.latte` позаботится о перечислении статей:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ class ArticleRepository
 Мы также расширяем метод `render` для получения экземпляра Paginator, его настройки и выбора нужных статей для отображения в шаблоне. HomePresenter будет выглядеть следующим образом:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Нам не нужно создавать Paginator в презентере, вместо этого мы будем использовать метод объекта `Selection`, возвращаемый репозиторием:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/ru/post-links.texy b/best-practices/ru/post-links.texy
new file mode 100644
index 0000000000..ac941e667a
--- /dev/null
+++ b/best-practices/ru/post-links.texy
@@ -0,0 +1,59 @@
+Как правильно использовать POST-ссылки
+**************************************
+
+В веб-приложениях, особенно в административных интерфейсах, должно быть основным правилом, что действия, изменяющие состояние сервера, не должны выполняться с помощью метода HTTP GET. Как следует из названия метода, GET должен использоваться только для получения данных, а не для их изменения.
+Для таких действий, как удаление записей, целесообразнее использовать метод POST. Хотя идеальным вариантом было бы использование метода DELETE, его невозможно вызвать без JavaScript, поэтому исторически используется POST.
+
+Как сделать это на практике? Используйте этот простой прием. В начале вашего шаблона создайте вспомогательную форму с идентификатором `postForm`, которую вы затем будете использовать для кнопок удаления:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+В этой форме вы можете использовать `<button>` вместо классической `<a>` ссылку, которая может быть визуально изменена, чтобы выглядеть как обычная ссылка. Например, CSS-фреймворк Bootstrap предлагает классы `btn btn-link`, которые позволяют сделать кнопку визуально неотличимой от других ссылок. Используя атрибут `form="postForm"`, мы связываем ее с заранее подготовленной формой:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+При нажатии на ссылку теперь вызывается действие `delete`. Чтобы убедиться, что запросы принимаются только методом POST и из одного домена (что является эффективной защитой от CSRF-атак), используйте атрибут `#[Requires]` атрибут:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Атрибут доступен с версии Nette Application 3.2, а подробнее о его возможностях вы можете узнать на странице [Как использовать атрибут #Requires |attribute-requires].
+
+Если вы использовали сигнал `handleDelete()` вместо действия `actionDelete()`, то нет необходимости указывать `sameOrigin: true`, так как у сигналов эта защита установлена неявно:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Такой подход не только повышает безопасность вашего приложения, но и способствует соблюдению надлежащих веб-стандартов и практик. Используя методы POST для действий, изменяющих состояние, вы получаете более надежное и безопасное приложение.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/ru/presenter-traits.texy b/best-practices/ru/presenter-traits.texy
index 91ec5df365..9c95a17890 100644
--- a/best-practices/ru/presenter-traits.texy
+++ b/best-practices/ru/presenter-traits.texy
@@ -2,7 +2,7 @@
 ************************************
 
 .[perex]
-Если нам нужно реализовать один и тот же код в нескольких презентерах (например, проверка того, что пользователь вошел в систему), заманчиво поместить этот код в общего предка. Второй вариант - создать одноцелевые трейты.
+Если нам необходимо реализовать один и тот же код в нескольких презентаторах (например, проверку того, что пользователь вошел в систему), то заманчиво поместить этот код в общего предка. Второй вариант - создание одноцелевых [трейтов |nette:introduction-to-object-oriented-programming#traits].
 
 Преимущество этого решения заключается в том, что каждый ведущий может использовать только те признаки, которые ему действительно нужны, в то время как множественное наследование в PHP невозможно.
 
diff --git a/best-practices/sl/@home.texy b/best-practices/sl/@home.texy
index ea4899f2ec..79810b73da 100644
--- a/best-practices/sl/@home.texy
+++ b/best-practices/sl/@home.texy
@@ -17,6 +17,8 @@ Nette aplikacija
 - [Kako se vrniti na prejšnjo stran |restore-request]
 - [Postransko prikazovanje rezultatov podatkovne zbirke |Pagination]
 - [Dinamični utrinki |dynamic-snippets]
+- [Kako uporabiti atribut #Requires |attribute-requires]
+- [Kako pravilno uporabljati povezave POST |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Obrazci
 Skupna spletna stran
 --------------------
 - [Kako naložiti konfiguracijsko datoteko |bootstrap:]
+- [Kako napisati mikrostrani |microsites]
 - [Zakaj Nette uporablja konstantni zapis PascalCase |https://blog.nette.org/sl/za-manj-kricanja-v-kodi]?
 - [Zakaj Nette ne uporablja končnice Interface |https://blog.nette.org/sl/predpone-in-pripone-ne-sodijo-v-imena-vmesnikov]?
 - [Nasveti za uporabo programa Composer |composer]
 - [Nasveti o urejevalnikih in orodjih |editors-and-tools]
+- [Uvod v objektno usmerjeno programiranje |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/sl/attribute-requires.texy b/best-practices/sl/attribute-requires.texy
new file mode 100644
index 0000000000..9c1494eb09
--- /dev/null
+++ b/best-practices/sl/attribute-requires.texy
@@ -0,0 +1,179 @@
+Kako uporabljati `#[Requires]` Atribut
+**************************************
+
+.[perex]
+Pri pisanju spletne aplikacije se pogosto srečate s potrebo po omejitvi dostopa do določenih delov aplikacije. Morda želite, da lahko nekatere zahteve pošljejo podatke samo prek obrazca (torej z uporabo metode POST) ali da so dostopne samo za klice AJAX. V okolju Nette Framework 3.2 je bilo uvedeno novo orodje, ki vam omogoča elegantno in jasno določanje takšnih omejitev: orodje `#[Requires]` atribut.
+
+Atribut je posebna oznaka v jeziku PHP, ki jo dodate pred definicijo razreda ali metode. Ker gre v bistvu za razred, morate za delovanje naslednjih primerov vključiti klavzulo use:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Uporabite lahko `#[Requires]` atribut v samem razredu presenter in v teh metodah:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Tudi zadnji dve metodi se nanašata na komponente, zato lahko atribut uporabite tudi z njima.
+
+Če pogoji, določeni z atributom, niso izpolnjeni, se sproži napaka HTTP 4xx.
+
+
+Metode HTTP .[#toc-http-methods]
+--------------------------------
+
+Določite lahko, katere metode HTTP (kot so GET, POST itd.) so dovoljene za dostop. Če želite na primer dovoliti dostop samo z oddajo obrazca, nastavite:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Zakaj za spreminjanje stanja uporabiti POST namesto GET in kako to storiti? [Preberite vodnik |post-links].
+
+Določite lahko metodo ali niz metod. Poseben primer je vrednost `'*'` za omogočanje vseh metod, ki jih predstavniki zaradi [varnostnih razlogov |application:presenters#http-method-check] privzeto ne omogočajo.
+
+
+Klici AJAX .[#toc-ajax-calls]
+-----------------------------
+
+Če želite, da je predstavnik ali metoda dostopna samo za zahteve AJAX, uporabite:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Enako poreklo .[#toc-same-origin]
+---------------------------------
+
+Če želite povečati varnost, lahko zahtevate, da je zahteva poslana iz iste domene. S tem preprečite [ranljivost CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Za `handle<Signal>()` je samodejno potreben dostop iz iste domene. Če torej želite dovoliti dostop iz katere koli domene, določite:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Dostop prek spletne strani Forward .[#toc-access-via-forward]
+-------------------------------------------------------------
+
+Včasih je koristno omejiti dostop do predstavnika, tako da je na voljo le posredno, na primer z uporabo metod `forward()` ali `switch()` iz drugega predstavnika. Tako so predstavniki napak zaščiteni, da jih ni mogoče sprožiti z naslova URL:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+V praksi je pogosto treba označiti določene poglede, do katerih je mogoče dostopati le na podlagi logike v predstavitvenem programu. Spet tako, da jih ni mogoče odpreti neposredno:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Posebni ukrepi .[#toc-specific-actions]
+---------------------------------------
+
+Prav tako lahko omejite, da bo določena koda, na primer ustvarjanje komponente, dostopna samo za določena dejanja v predstavitvenem programu:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Za posamezno dejanje ni treba pisati polja: `#[Requires(actions: 'default')]`
+
+
+Atributi po meri .[#toc-custom-attributes]
+------------------------------------------
+
+Če želite uporabiti `#[Requires]` atribut večkrat uporabiti z enakimi nastavitvami, lahko ustvarite svoj atribut, ki bo podedoval `#[Requires]` in ga nastavite v skladu s svojimi potrebami.
+
+Na primer, `#[SingleAction]` omogoča dostop samo prek dejanja `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Ali `#[RestMethods]` omogoči dostop prek vseh metod HTTP, ki se uporabljajo za API REST:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Zaključek .[#toc-conclusion]
+----------------------------
+
+Na spletni strani `#[Requires]` vam omogoča veliko prilagodljivost in nadzor nad načinom dostopa do spletnih strani. Z uporabo preprostih, a zmogljivih pravil lahko izboljšate varnost in pravilno delovanje svoje aplikacije. Kot lahko vidite, lahko z uporabo atributov v Nette ne le poenostavite svoje delo, temveč ga tudi zavarujete.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/sl/composer.texy b/best-practices/sl/composer.texy
index 52eb9cc2da..6a3fa3ffdc 100644
--- a/best-practices/sl/composer.texy
+++ b/best-practices/sl/composer.texy
@@ -142,6 +142,12 @@ Ali neposredno v datoteki `composer.json`:
 ```
 
 
+Ignoriranje različice PHP .[#toc-ignoring-php-version]
+======================================================
+
+V paketih je običajno navedena najnižja različica PHP, s katero so združljivi, in najvišja različica, s katero so bili testirani. Če nameravate uporabiti še novejšo različico PHP, morda za namene testiranja, bo Composer zavrnil namestitev takega paketa. Rešitev je uporaba možnosti `--ignore-platform-req=php+`, ki povzroči, da Composer ne upošteva zgornje meje zahtevane različice PHP.
+
+
 Napačna poročila .[#toc-false-reports]
 ======================================
 
@@ -183,7 +189,7 @@ Vendar je mogoče Composer uporabiti tudi za nalaganje drugih razredov zunaj map
 
 Nato je treba ob vsaki spremembi zagnati ukaz `composer dumpautoload` in pustiti, da se tabele za samodejno nalaganje regenerirajo. To je izredno neprijetno in veliko bolje je to nalogo zaupati programu [RobotLoader |robot-loader:], ki isto dejavnost opravi samodejno v ozadju in veliko hitreje.
 
-Druga možnost je, da sledite [priporočilu PSR-4 |https://www.php-fig.org/psr/psr-4/]. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, tj. `App\Router\RouterFactory` se nahaja v datoteki `/path/to/App/Router/RouterFactory.php`. Primer konfiguracije:
+Druga možnost je, da sledite [priporočilu PSR-4 |https://www.php-fig.org/psr/psr-4/]. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, tj. `App\Core\RouterFactory` se nahaja v datoteki `/path/to/App/Core/RouterFactory.php`. Primer konfiguracije:
 
 ```js
 {
diff --git a/best-practices/sl/dynamic-snippets.texy b/best-practices/sl/dynamic-snippets.texy
index dcd25eb0c7..0554bab175 100644
--- a/best-practices/sl/dynamic-snippets.texy
+++ b/best-practices/sl/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Predloga:
 Ajaksizacija .[#toc-ajaxization]
 ================================
 
-V to preprosto aplikacijo zdaj vnesimo AJAX. Spreminjanje ocene članka ni dovolj pomembno, da bi zahtevalo zahtevo HTTP s preusmeritvijo, zato bi bilo idealno, če bi to opravili z AJAXom v ozadju. Uporabili bomo [skript za obdelavo iz dodatkov |https://componette.org/vojtech-dobes/nette.ajax.js/] z običajno konvencijo, da imajo povezave AJAX razred CSS `ajax`.
+V to preprosto aplikacijo zdaj vnesimo AJAX. Spreminjanje ocene članka ni dovolj pomembno, da bi zahtevalo zahtevo HTTP s preusmeritvijo, zato bi bilo idealno, če bi to opravili z AJAXom v ozadju. Uporabili bomo [skript za obdelavo iz dodatkov |application:ajax#toc-naja] z običajno konvencijo, da imajo povezave AJAX razred CSS `ajax`.
 
 Vendar pa, kako to storiti konkretno? Nette ponuja dva načina: način z dinamičnimi utrinki in način s komponentami. Oba načina imata svoje prednosti in slabosti, zato ju bomo prikazali enega za drugim.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Seveda bomo spremenili predlogo pogleda in morali bomo dodati tovarno za predsta
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/sl/form-reuse.texy b/best-practices/sl/form-reuse.texy
index 398e4490b0..7eaa8a578e 100644
--- a/best-practices/sl/form-reuse.texy
+++ b/best-practices/sl/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Zelo pomembno je, da se vezava med razredoma `FormFactory` in `EditFormFactory` izvaja s kompozicijo in ne z dedovanjem objektov:
+Zelo pomembno je, da se povezava med razredoma `FormFactory` in `EditFormFactory` izvaja [s kompozicijo |nette:introduction-to-object-oriented-programming#composition] in ne z [dedovanjem objektov |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // ⛔ NE! DEDIŠČINA NE SPADA SEM
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Uporaba dedovanja bi bila v tem primeru popolnoma neproduktivna. Zelo hitro bi naleteli na težave. Na primer, če bi želeli metodi `create()` dodati parametre; PHP bi sporočil napako, ker se njen podpis razlikuje od podpisa nadrejene metode.
 Ali pa pri posredovanju odvisnosti razredu `EditFormFactory` prek konstruktorja. To bi povzročilo tako imenovani [konstruktorski pekel |dependency-injection:passing-dependencies#Constructor hell].
 
-Na splošno je bolje dati prednost kompoziciji pred dedovanjem.
+Na splošno je bolje dati prednost [sestavi pred dedovanjem |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Ravnanje z obrazci .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/sl/lets-create-contact-form.texy b/best-practices/sl/lets-create-contact-form.texy
index feeae86ee8..0fe2c371a9 100644
--- a/best-practices/sl/lets-create-contact-form.texy
+++ b/best-practices/sl/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Kot lahko vidite, smo ustvarili dve metodi. Prva metoda `createComponentContactF
 Kaj pa, če uporabnik ne izpolni nekaterih polj? V tem primeru mu moramo sporočiti, da gre za zahtevano polje. To smo storili z metodo `setRequired()`.
 Na koncu smo dodali še [dogodek |nette:glossary#events] `onSuccess`, ki se sproži, če je obrazec uspešno oddan. V našem primeru pokliče metodo `contactFormSucceeded`, ki poskrbi za obdelavo oddanega obrazca. To bomo v kodo dodali v naslednjem trenutku.
 
-Naj bo komponenta `contantForm` prikazana v predlogi `templates/Home/default.latte`:
+Naj bo komponenta `contantForm` prikazana v predlogi `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/sl/microsites.texy b/best-practices/sl/microsites.texy
new file mode 100644
index 0000000000..ce6af7d0da
--- /dev/null
+++ b/best-practices/sl/microsites.texy
@@ -0,0 +1,63 @@
+Kako napisati mikrostrani
+*************************
+
+Predstavljajte si, da morate na hitro ustvariti majhno spletno stran za prihajajoči dogodek vašega podjetja. Biti mora preprosta, hitra in brez nepotrebnih zapletov. Morda mislite, da tako majhen projekt ne zahteva robustnega ogrodja. Kaj pa, če lahko z uporabo ogrodja Nette ta postopek bistveno poenostavite in pospešite?
+
+Tudi pri ustvarjanju preprostih spletnih mest se ne želite odpovedati udobju. Ne želite na novo izumljati kolesa. Privoščite si, da ste leni in se razvajate. Okvir Nette je mogoče odlično uporabiti tudi kot mikrookvir.
+
+Kako je lahko videti takšna mikrostrani? Celotno kodo spletnega mesta lahko na primer postavite v eno samo datoteko `index.php` v javni mapi:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// ustvarite vsebnik DI na podlagi konfiguracije v config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// nastavi usmerjanje
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// pot za URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// zaznajo jezik brskalnika in preusmerijo na URL /en ali /de itd.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// pot za URL https://example.com/cs ali https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// prikaže ustrezno predlogo, na primer ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// zaženite aplikacijo!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Vse drugo bodo predloge, shranjene v nadrejeni mapi `/templates`.
+
+Koda PHP v mapi `index.php` najprej vzpostavi [okolje |bootstrap:], nato definira [poti |application:routing#dynamic-routing-with-callbacks] in nazadnje zažene aplikacijo. Prednost je, da je lahko drugi parameter funkcije `addRoute()` klicni ukaz, ki se izvede, ko se odpre ustrezna stran.
+
+
+Zakaj uporabljati Nette za mikrostrani? .[#toc-why-use-nette-for-microsites]
+----------------------------------------------------------------------------
+
+- Razvijalci, ki so kdaj preizkusili [Tracy |tracy:], si danes ne morejo predstavljati kodiranja brez njega.
+- Predvsem pa boste uporabili sistem za oblikovanje predlog [Latte |latte:], saj boste iz samo dveh strani želeli ločiti [postavitev in vsebino |latte:template-inheritance].
+- In vsekakor se boste želeli zanesti na [samodejno pobeganje, |latte:safety-first] da bi preprečili ranljivosti XSS.
+- Nette zagotavlja tudi, da se v primeru napake ne bodo nikoli prikazala sporočila o napaki PHP, temveč bo namesto tega prikazana uporabniku prijazna stran.
+- Če želite od uporabnikov pridobiti povratne informacije, na primer v obliki kontaktnega obrazca, lahko dodate tudi [obrazce |forms:] in [zbirko podatkov |database:].
+- Izpolnjene obrazce lahko preprosto [pošljete |mail:] tudi po [elektronski pošti |mail:].
+- Včasih se vam lahko zdi koristno [predpomnjenje |caching:], na primer pri prenašanju in prikazovanju virov.
+
+V današnjem času, ko sta hitrost in učinkovitost ključnega pomena, je pomembno imeti orodja, ki vam omogočajo doseganje rezultatov brez nepotrebnih zamud. Okvir Nette ponuja prav to - hiter razvoj, varnost in široko paleto orodij, kot sta Tracy in Latte, ki poenostavljajo postopek. Samo namestite nekaj paketov Nette in gradnja takšne mikrostrani bo postala enostavna. Poleg tega veste, da ni nobenih skritih varnostnih pomanjkljivosti.
diff --git a/best-practices/sl/pagination.texy b/best-practices/sl/pagination.texy
index b5322e1cd1..f0136cebbc 100644
--- a/best-practices/sl/pagination.texy
+++ b/best-practices/sl/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 V Presenter nato injiciramo razred model in v metodi render bomo zahtevali objavljene članke, ki jih posredujemo predlogi:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-V predlogi bomo poskrbeli za upodobitev seznama člankov:
+Predloga `default.latte` bo nato poskrbela za seznam člankov:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Naslednji korak je urejanje predstavnika. Številko trenutno prikazane strani bo
 Metodo upodabljanja razširimo tudi na pridobitev primerka Paginatorja, njegovo nastavitev in izbiro pravilnih člankov za prikaz v predlogi. HomePresenter bo videti takole:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Namesto tega bomo uporabili metodo predmeta `Selection`, ki ga je vrnil repozitorij:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/sl/post-links.texy b/best-practices/sl/post-links.texy
new file mode 100644
index 0000000000..8c588b5864
--- /dev/null
+++ b/best-practices/sl/post-links.texy
@@ -0,0 +1,59 @@
+Kako pravilno uporabljati povezave POST
+***************************************
+
+V spletnih aplikacijah, zlasti v upravnih vmesnikih, bi moralo veljati osnovno pravilo, da se dejanja, ki spreminjajo stanje strežnika, ne smejo izvajati z metodo HTTP GET. Kot pove že ime metode, naj se GET uporablja samo za pridobivanje podatkov in ne za njihovo spreminjanje.
+Za dejanja, kot je brisanje zapisov, je primerneje uporabiti metodo POST. Čeprav bi bilo idealno uporabiti metodo DELETE, je brez JavaScripta ni mogoče izvesti, zato se v preteklosti uporablja metoda POST.
+
+Kako to storiti v praksi? Uporabite ta preprost trik. Na začetku predloge ustvarite pomožni obrazec z identifikatorjem `postForm`, ki ga boste nato uporabili za gumbe za brisanje:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+S tem obrazcem lahko uporabite `<button>` namesto klasičnega `<a>` povezavo, ki jo lahko vizualno spremenite tako, da je videti kot običajna povezava. Ogrodje Bootstrap CSS na primer ponuja razrede `btn btn-link`, ki omogočajo, da se gumb vizualno ne razlikuje od drugih povezav. Z uporabo atributa `form="postForm"` ga povežemo z vnaprej pripravljenim obrazcem:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Ob kliku na povezavo se zdaj sproži dejanje `delete`. Če želite zagotoviti, da se zahtevki sprejemajo samo z metodo POST in iz iste domene (kar je učinkovita obramba pred napadi CSRF), uporabite `#[Requires]` atribut:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Atribut je na voljo od različice Nette Application 3.2, več o njegovih zmogljivostih pa lahko izveste na strani [Kako uporabljati atribut #Requires |attribute-requires].
+
+Če bi namesto akcije `actionDelete()` uporabili signal `handleDelete()`, vam ni treba navesti `sameOrigin: true`, saj imajo signali implicitno nastavljeno to zaščito:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Ta pristop ne izboljša le varnosti vaše aplikacije, temveč prispeva tudi k upoštevanju ustreznih spletnih standardov in praks. Z uporabo metod POST za dejanja, ki spreminjajo stanje, dosežete robustnejšo in varnejšo aplikacijo.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/sl/presenter-traits.texy b/best-practices/sl/presenter-traits.texy
index e20064a8e4..61924099ae 100644
--- a/best-practices/sl/presenter-traits.texy
+++ b/best-practices/sl/presenter-traits.texy
@@ -2,7 +2,7 @@ Sestavljanje predavateljev iz lastnosti
 ***************************************
 
 .[perex]
-Če moramo isto kodo implementirati v več predstavitvah (npr. preverjanje, ali je uporabnik prijavljen), je skušnjava, da kodo postavimo v skupnega prednika. Druga možnost je, da ustvarimo enonamenske lastnosti.
+Če moramo isto kodo implementirati v več prikazovalnikih (npr. preverjanje, ali je uporabnik prijavljen), je skušnjava, da bi kodo prenesli v skupnega prednika. Druga možnost je, da ustvarimo enonamenske [lastnosti |nette:introduction-to-object-oriented-programming#traits].
 
 Prednost te rešitve je, da lahko vsak predstavnik uporablja samo lastnosti, ki jih dejansko potrebuje, medtem ko večkratno dedovanje v PHP ni mogoče.
 
diff --git a/best-practices/tr/@home.texy b/best-practices/tr/@home.texy
index 1cc97db6f5..bbd6bc2f3c 100644
--- a/best-practices/tr/@home.texy
+++ b/best-practices/tr/@home.texy
@@ -17,6 +17,8 @@ Nette Uygulama
 - [Önceki bir sayfaya nasıl dönülür |restore-request]?
 - [Veritabanı sonuçlarını sayfalandırma |Pagination]
 - [Dinamik snippet'ler |dynamic-snippets]
+- [Requires özniteliği nasıl kullanılır |attribute-requires]?
+- [POST bağlantıları nasıl doğru kullanılır |post-links]?
 
 </div>
 <div>
@@ -36,10 +38,12 @@ Formlar
 Ortak
 -----
 - [Yapılandırma dosyası nasıl yüklenir |bootstrap:]
+- [Mikro siteler nasıl yazılır |microsites]
 - [Nette neden PascalCase sabit gösterimini kullanıyor? |https://blog.nette.org/tr/kodda-daha-az-ciglik-atmak-icin]
 - [Nette neden Interface son ekini kullanmıyor? |https://blog.nette.org/tr/oenek-ve-sonekler-arayuez-adlarina-ait-degildir]
 - [Composer kullanım ipuçları |composer]
 - [Editörler ve araçlar hakkında ipuçları |editors-and-tools]
+- [Nesne yönelimli programlamaya giriş |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/tr/attribute-requires.texy b/best-practices/tr/attribute-requires.texy
new file mode 100644
index 0000000000..41ce8c21e6
--- /dev/null
+++ b/best-practices/tr/attribute-requires.texy
@@ -0,0 +1,179 @@
+Nasıl Kullanılır `#[Requires]` Öznitelik
+****************************************
+
+.[perex]
+Bir web uygulaması yazarken, uygulamanızın belirli bölümlerine erişimi kısıtlama ihtiyacıyla sık sık karşılaşırsınız. Belki de bazı isteklerin yalnızca bir form aracılığıyla veri gönderebilmesini (dolayısıyla POST yöntemini kullanarak) veya yalnızca AJAX çağrıları tarafından erişilebilir olmasını istiyorsunuzdur. Nette Framework 3.2'de, bu tür kısıtlamaları zarif ve açık bir şekilde ayarlamanıza olanak tanıyan yeni bir araç sunulmuştur: `#[Requires]` nitelik.
+
+Nitelik, PHP'de bir sınıf veya yöntemin tanımından önce eklediğiniz özel bir işarettir. Esasen bir sınıf olduğu için, aşağıdaki örneklerin çalışması için use cümlesini eklemeniz gerekir:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Kullanabilirsiniz `#[Requires]` özniteliğinin sunum yapan sınıfın kendisiyle ve bu yöntemlerle olan ilişkisi:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Son iki yöntem de bileşenlerle ilgilidir, bu nedenle özniteliği onlarla da kullanabilirsiniz.
+
+Öznitelik tarafından belirtilen koşullar karşılanmazsa, bir HTTP 4xx hatası tetiklenir.
+
+
+HTTP Yöntemleri .[#toc-http-methods]
+------------------------------------
+
+Erişim için hangi HTTP yöntemlerine (GET, POST, vb.) izin verileceğini belirtebilirsiniz. Örneğin, yalnızca bir form göndererek erişime izin vermek istiyorsanız, şunu ayarlayın:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Durum değiştirme eylemleri için neden GET yerine POST kullanmalısınız ve bunu nasıl yapmalısınız? [Kılavuzu okuyun |post-links].
+
+Bir yöntem veya bir dizi yöntem belirtebilirsiniz. Özel bir durum, sunum yapanların [güvenlik nedeniyle |application:presenters#http-method-check] varsayılan olarak izin vermediği tüm yöntemleri etkinleştirmek için `'*'` değeridir.
+
+
+AJAX Çağrıları .[#toc-ajax-calls]
+---------------------------------
+
+Bir sunucunun veya yöntemin yalnızca AJAX istekleri için erişilebilir olmasını istiyorsanız, şunu kullanın:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Aynı Köken .[#toc-same-origin]
+------------------------------
+
+Güvenliği artırmak için, isteğin aynı etki alanından yapılmasını zorunlu tutabilirsiniz. Bu, [CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]'ye karşı güvenlik açığını önler:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+İçin `handle<Signal>()` yöntemlerinde, aynı etki alanından erişim otomatik olarak gereklidir. Bu nedenle, herhangi bir etki alanından erişime izin vermek istiyorsanız, şunu belirtin:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Forward üzerinden erişim .[#toc-access-via-forward]
+---------------------------------------------------
+
+Bazen bir sunucuya erişimi kısıtlamak yararlı olabilir, böylece yalnızca dolaylı olarak, örneğin başka bir sunucudan `forward()` veya `switch()` yöntemleri kullanılarak kullanılabilir. Hata sunucuları, bir URL'den tetiklenmelerini önlemek için bu şekilde korunur:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Pratikte, yalnızca sunum yapan kişideki mantığa dayalı olarak erişilebilen belirli görünümleri işaretlemek genellikle gereklidir. Yine, böylece doğrudan açılamazlar:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Spesifik Eylemler .[#toc-specific-actions]
+------------------------------------------
+
+Ayrıca, bir bileşen oluşturmak gibi belirli kodların yalnızca sunum aracındaki belirli eylemler için erişilebilir olmasını da kısıtlayabilirsiniz:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Tek bir eylem için bir dizi yazmaya gerek yoktur: `#[Requires(actions: 'default')]`
+
+
+Özel Nitelikler .[#toc-custom-attributes]
+-----------------------------------------
+
+Eğer kullanmak istiyorsanız `#[Requires]` özniteliğini aynı ayarlarla tekrar tekrar kullanmak istemiyorsanız, kendi özniteliğinizi oluşturabilirsiniz. `#[Requires]` ve ihtiyaçlarınıza göre ayarlayın.
+
+Örneğin, `#[SingleAction]` yalnızca `default` eylemi aracılığıyla erişime izin verir:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Ya da `#[RestMethods]` REST API için kullanılan tüm HTTP yöntemleri aracılığıyla erişime izin verecektir:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Sonuç .[#toc-conclusion]
+------------------------
+
+Bu `#[Requires]` özelliği, web sayfalarınıza nasıl erişileceği konusunda size büyük esneklik ve kontrol sağlar. Basit ama güçlü kurallar kullanarak uygulamanızın güvenliğini ve düzgün çalışmasını artırabilirsiniz. Gördüğünüz gibi, Nette öznitelikleri kullanmak sadece işinizi basitleştirmekle kalmaz, aynı zamanda güvenli hale de getirir.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/tr/composer.texy b/best-practices/tr/composer.texy
index 74d2c032f1..f16faee810 100644
--- a/best-practices/tr/composer.texy
+++ b/best-practices/tr/composer.texy
@@ -142,6 +142,12 @@ Veya doğrudan `composer.json` dosyasında:
 ```
 
 
+PHP Sürümünü Yoksayma .[#toc-ignoring-php-version]
+==================================================
+
+Paketler genellikle hem uyumlu oldukları en düşük PHP sürümünü hem de test edildikleri en yüksek sürümü belirtirler. PHP'nin daha yeni bir sürümünü kullanmayı planlıyorsanız, belki de test amacıyla, Composer böyle bir paketi yüklemeyi reddedecektir. Çözüm, Composer'ın gerekli PHP sürümünün üst sınırlarını göz ardı etmesine neden olan `--ignore-platform-req=php+` seçeneğini kullanmaktır.
+
+
 Yanlış Raporlar .[#toc-false-reports]
 =====================================
 
@@ -183,7 +189,7 @@ Ancak, Composer'ı `vendor` klasörü dışındaki diğer sınıfları yüklemek
 
 Daha sonra, her değişiklikte `composer dumpautoload` komutunu çalıştırmak ve otomatik yükleme tablolarının yeniden oluşturulmasına izin vermek gerekir. Bu son derece zahmetlidir ve bu görevi, aynı etkinliği arka planda otomatik olarak ve çok daha hızlı gerçekleştiren [RobotLoader'a |robot-loader:] emanet etmek çok daha iyidir.
 
-İkinci seçenek [PSR-4'ü |https://www.php-fig.org/psr/psr-4/] takip etmektir. Basitçe söylemek gerekirse, ad alanlarının ve sınıf adlarının dizin yapısına ve dosya adlarına karşılık geldiği bir sistemdir, yani `App\Router\RouterFactory`, `/path/to/App/Router/RouterFactory.php` dosyasında bulunur. Yapılandırma örneği:
+İkinci seçenek [PSR-4'ü |https://www.php-fig.org/psr/psr-4/] takip etmektir. Basitçe söylemek gerekirse, ad alanlarının ve sınıf adlarının dizin yapısına ve dosya adlarına karşılık geldiği bir sistemdir, yani `App\Core\RouterFactory`, `/path/to/App/Core/RouterFactory.php` dosyasında bulunur. Yapılandırma örneği:
 
 ```js
 {
diff --git a/best-practices/tr/dynamic-snippets.texy b/best-practices/tr/dynamic-snippets.texy
index bae43f06d3..30980e895e 100644
--- a/best-practices/tr/dynamic-snippets.texy
+++ b/best-practices/tr/dynamic-snippets.texy
@@ -35,7 +35,7 @@ public function handleUnlike(int $articleId): void
 Ajaxlaştırma .[#toc-ajaxization]
 ================================
 
-Şimdi bu basit uygulamaya AJAX'ı getirelim. Bir makalenin derecelendirmesini değiştirmek, yönlendirmeli bir HTTP isteği gerektirecek kadar önemli değildir, bu nedenle ideal olarak arka planda AJAX ile yapılmalıdır. AJAX bağlantılarının `ajax` CSS sınıfına sahip olduğu olağan kuralıyla [eklentilerdeki işleyici |https://componette.org/vojtech-dobes/nette.ajax.js/] komut dosyasını kullanacağız.
+Şimdi bu basit uygulamaya AJAX'ı getirelim. Bir makalenin derecelendirmesini değiştirmek, yönlendirmeli bir HTTP isteği gerektirecek kadar önemli değildir, bu nedenle ideal olarak arka planda AJAX ile yapılmalıdır. AJAX bağlantılarının `ajax` CSS sınıfına sahip olduğu olağan kuralıyla [eklentilerdeki işleyici |application:ajax#toc-naja] komut dosyasını kullanacağız.
 
 Ancak, bunu özellikle nasıl yapmalı? Nette 2 yol sunuyor: dinamik snippet yolu ve bileşen yolu. Her ikisinin de artıları ve eksileri var, bu yüzden bunları tek tek göstereceğiz.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ Elbette görünüm şablonunu değiştireceğiz ve sunucuya bir fabrika eklememi
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/tr/form-reuse.texy b/best-practices/tr/form-reuse.texy
index 338dee09ef..f6a3cd40a4 100644
--- a/best-practices/tr/form-reuse.texy
+++ b/best-practices/tr/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
- `FormFactory` ve `EditFormFactory` sınıfları arasındaki bağın nesne kalıtımı ile değil, bileşim ile uygulanması çok önemlidir:
+`FormFactory` ve `EditFormFactory` sınıfları arasındaki bağın [nesne kalıtımı |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance] ile değil, [bileşim |nette:introduction-to-object-oriented-programming#composition] ile uygulanması çok önemlidir:
 
 ```php
 // ⛔ HAYIR! MİRAS BURAYA AİT DEĞİL
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Bu durumda kalıtım kullanmak tamamen ters etki yaratacaktır. Çok hızlı bir şekilde sorunlarla karşılaşırsınız. Örneğin, `create()` yöntemine parametre eklemek isterseniz; PHP, imzasının ebeveynden farklı olduğuna dair bir hata bildirecektir.
 Ya da `EditFormFactory` sınıfına yapıcı aracılığıyla bir bağımlılık aktarırken. Bu, yapıcı [cehennemi |dependency-injection:passing-dependencies#Constructor hell] dediğimiz şeye neden olur.
 
-Genel olarak, kalıtım yerine bileşimi tercih etmek daha iyidir.
+Genellikle [kalıtım yerine bileşimi |dependency-injection:faq#Why composition is preferred over inheritance] tercih etmek daha iyidir.
 
 
 Form İşleme .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/tr/lets-create-contact-form.texy b/best-practices/tr/lets-create-contact-form.texy
index 52d307b8bf..306be16c72 100644
--- a/best-practices/tr/lets-create-contact-form.texy
+++ b/best-practices/tr/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ Gördüğünüz gibi iki metot oluşturduk. İlk yöntem `createComponentContact
 Peki ya kullanıcı bazı alanları doldurmazsa? Bu durumda, ona bunun gerekli bir alan olduğunu bildirmeliyiz. Bunu `setRequired()` metodu ile yaptık.
 Son olarak, form başarıyla gönderildiğinde tetiklenen bir `onSuccess`[olayı |nette:glossary#events] da ekledik. Bizim durumumuzda, gönderilen formun işlenmesiyle ilgilenen `contactFormSucceeded` yöntemini çağırır. Bunu birazdan koda ekleyeceğiz.
 
- `contantForm` bileşeninin `templates/Home/default.latte` şablonunda oluşturulmasına izin verin:
+ `contantForm` bileşeninin `Home/default.latte` şablonunda oluşturulmasına izin verin:
 
 ```latte
 {block content}
diff --git a/best-practices/tr/microsites.texy b/best-practices/tr/microsites.texy
new file mode 100644
index 0000000000..977df38b40
--- /dev/null
+++ b/best-practices/tr/microsites.texy
@@ -0,0 +1,63 @@
+Mikro Siteler Nasıl Yazılır
+***************************
+
+Şirketinizin yaklaşan bir etkinliği için hızlı bir şekilde küçük bir web sitesi oluşturmanız gerektiğini düşünün. Basit, hızlı ve gereksiz komplikasyonlardan uzak olmalı. Bu kadar küçük bir projenin sağlam bir framework gerektirmediğini düşünebilirsiniz. Peki ya Nette çerçevesini kullanmak bu süreci önemli ölçüde basitleştirip hızlandırabilirse?
+
+Basit web siteleri oluştururken bile konfordan vazgeçmek istemezsiniz. Tekerleği yeniden icat etmek istemezsiniz. Tembel olmaktan ve kendinizi şımartmaktan çekinmeyin. Nette Framework mikro framework olarak da mükemmel bir şekilde kullanılabilir.
+
+Böyle bir mikro site neye benzeyebilir? Örneğin, web sitesinin tüm kodu genel klasördeki tek bir `index.php` dosyasına yerleştirilebilir:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// config.neon dosyasındaki yapılandırmaya göre bir DI konteyneri oluşturun
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// Yönlendirmeyi ayarlayın
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// URL için rota https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// tarayıcı dilini algılar ve /en veya /de vb. URL'ye yönlendirir.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// URL için rota https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// uygun şablonu görüntüleyin, örneğin ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// uygulamayı çalıştırın!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Diğer her şey üst `/templates` klasöründe depolanan şablonlar olacaktır.
+
+ `index.php` adresindeki PHP kodu önce [ortamı kur |bootstrap:]ar, sonra [rotaları |application:routing#dynamic-routing-with-callbacks] tanımlar ve son olarak uygulamayı çalıştırır. Bunun avantajı, `addRoute()` işlevinin ikinci parametresinin, ilgili sayfa açıldığında çalıştırılan bir çağrılabilir olmasıdır.
+
+
+Mikro Siteler için Neden Nette Kullanılmalı? .[#toc-why-use-nette-for-microsites]
+---------------------------------------------------------------------------------
+
+- [Tracy |tracy:] 'yi denemiş olan geliştiriciler bugün onsuz kodlama yapmayı hayal bile edemezler.
+- Ancak her şeyden önce, [Latte |latte:] şablonlama sistemini kullanacaksınız, çünkü sadece 2 sayfadan [düzen ve içeriği |latte:template-inheritance] ayırmak isteyeceksiniz.
+- Ve XSS güvenlik açıklarını önlemek için kesinlikle [otomatik kaçışa |latte:safety-first] güvenmek isteyeceksiniz.
+- Nette ayrıca bir hata durumunda PHP hata mesajlarının asla görüntülenmemesini, bunun yerine kullanıcı dostu bir sayfanın görüntülenmesini sağlar.
+- Kullanıcılardan geri bildirim almak istiyorsanız, örneğin bir iletişim formu şeklinde, [formlar |forms:] ve [veritabanı |database:] da ekleyebilirsiniz.
+- Doldurulan formların [e-posta ile gönderilmesini |mail:] de kolayca sağlayabilirsiniz.
+- Bazen, örneğin beslemeleri indirirken ve görüntülerken [önbelleğe |caching:] almayı yararlı bulabilirsiniz.
+
+Hız ve verimliliğin kilit önem taşıdığı günümüzde, gereksiz gecikmeler olmadan sonuçlara ulaşmanızı sağlayan araçlara sahip olmak önemlidir. Nette framework tam da bunu sunuyor - hızlı geliştirme, güvenlik ve süreci basitleştiren Tracy ve Latte gibi çok çeşitli araçlar. Sadece birkaç Nette paketi kurun ve böyle bir mikro site oluşturmak çocuk oyuncağı haline gelsin. Ve hiçbir gizli güvenlik açığı olmadığını bilirsiniz.
diff --git a/best-practices/tr/pagination.texy b/best-practices/tr/pagination.texy
index 5ae4641731..e6513d47d1 100644
--- a/best-practices/tr/pagination.texy
+++ b/best-practices/tr/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Presenter'da daha sonra model sınıfını enjekte edeceğiz ve render yönteminde şablona aktardığımız yayınlanmış makaleleri isteyeceğiz:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-Şablonda, bir makale listesi oluşturmaya özen göstereceğiz:
+`default.latte` şablonu daha sonra makaleleri listelemekle ilgilenecektir:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ Bir sonraki adım sunucuyu düzenlemektir. Şu anda görüntülenen sayfanın nu
 Ayrıca Paginator örneğini almak, ayarlamak ve şablonda görüntülenecek doğru makaleleri seçmek için render yöntemini genişletiyoruz. HomePresenter şu şekilde görünecektir:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Presenter'da Paginator oluşturmak zorunda değiliz, bunun yerine repository tarafından döndürülen `Selection` nesnesinin yöntemini kullanacağız:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/tr/post-links.texy b/best-practices/tr/post-links.texy
new file mode 100644
index 0000000000..94bef4ceec
--- /dev/null
+++ b/best-practices/tr/post-links.texy
@@ -0,0 +1,59 @@
+POST Bağlantıları Nasıl Doğru Kullanılır?
+*****************************************
+
+Web uygulamalarında, özellikle de yönetim arayüzlerinde, sunucunun durumunu değiştiren eylemlerin HTTP GET yöntemi ile gerçekleştirilmemesi temel bir kural olmalıdır. Metot adından da anlaşılacağı üzere GET sadece veri almak için kullanılmalıdır, değiştirmek için değil.
+Kayıt silme gibi eylemler için POST yönteminin kullanılması daha uygundur. İdeal olan DELETE yöntemini kullanmak olsa da, bu JavaScript olmadan çağrılamaz, bu nedenle POST tarihsel olarak kullanılır.
+
+Pratikte nasıl yapılır? Bu basit numarayı kullanın. Şablonunuzun başında, daha sonra silme düğmeleri için kullanacağınız `postForm` tanımlayıcısına sahip bir yardımcı form oluşturun:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+Bu form ile, bir `<button>` klasik yerine `<a>` bağlantısı, görsel olarak normal bir bağlantı gibi görünecek şekilde değiştirilebilir. Örneğin, Bootstrap CSS çerçevesi, düğmenin görsel olarak diğer bağlantılardan ayırt edilememesini sağlayan `btn btn-link` sınıflarını sunar. `form="postForm"` niteliğini kullanarak, önceden hazırlanmış forma bağlarız:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+Bağlantıya tıklandığında, `delete` eylemi artık çağrılır. İsteklerin yalnızca POST yöntemiyle ve aynı etki alanından (CSRF saldırılarına karşı etkili bir savunmadır) kabul edilmesini sağlamak için `#[Requires]` nitelik:
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Bu öznitelik Nette Application 3.2'den beri mevcuttur ve [#Requires özniteliği nasıl kullanılır |attribute-requires] sayfasında özellikleri hakkında daha fazla bilgi edinebilirsiniz.
+
+ `actionDelete()` eylemi yerine `handleDelete()` sinyalini kullanıyor olsaydınız, `sameOrigin: true` belirtmeniz gerekmezdi, çünkü sinyaller bu korumaya dolaylı olarak sahiptir:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Bu yaklaşım yalnızca uygulamanızın güvenliğini artırmakla kalmaz, aynı zamanda uygun web standartlarına ve uygulamalarına bağlı kalmanıza da katkıda bulunur. Durum değiştiren eylemler için POST yöntemlerini kullanarak daha sağlam ve güvenli bir uygulama elde edersiniz.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/tr/presenter-traits.texy b/best-practices/tr/presenter-traits.texy
index 1ef3223f6e..c568a8bb9d 100644
--- a/best-practices/tr/presenter-traits.texy
+++ b/best-practices/tr/presenter-traits.texy
@@ -2,7 +2,7 @@
 ******************************
 
 .[perex]
-Aynı kodu birden fazla sunucuda uygulamamız gerekiyorsa (örneğin, kullanıcının oturum açtığının doğrulanması), kodu ortak bir ataya yerleştirmek caziptir. İkinci seçenek ise tek amaçlı özellikler oluşturmaktır.
+Aynı kodu birden fazla sunucuda uygulamamız gerekiyorsa (örneğin, kullanıcının oturum açtığının doğrulanması), kodu ortak bir ataya yerleştirmek caziptir. İkinci seçenek ise tek amaçlı [özellikler |nette:introduction-to-object-oriented-programming#traits] oluşturmaktır.
 
 Bu çözümün avantajı, PHP'de çoklu kalıtım mümkün değilken, her sunucunun yalnızca gerçekten ihtiyaç duyduğu özellikleri kullanabilmesidir.
 
diff --git a/best-practices/uk/@home.texy b/best-practices/uk/@home.texy
index 25d1fa8493..532d51b40e 100644
--- a/best-practices/uk/@home.texy
+++ b/best-practices/uk/@home.texy
@@ -17,6 +17,8 @@
 - [Як повернутися на попередню сторінку |restore-request]
 - [Пагінація результатів бази даних |Pagination]
 - [Динамічні фрагменти |dynamic-snippets]
+- [Як використовувати атрибут #Requires |attribute-requires]
+- [Як правильно використовувати POST-посилання |post-links]
 
 </div>
 <div>
@@ -36,10 +38,12 @@
 Спільне
 -------
 - [Як завантажити конфігураційний файл |bootstrap:]
+- [Як писати мікросайти |microsites]
 - [Чому Nette використовує нотацію констант у регістрі PascalCase? |https://blog.nette.org/uk/sob-mense-kriku-v-kodi]
 - [Чому Nette не використовує суфікс Interface? |https://blog.nette.org/uk/prefiksi-ta-sufiksi-ne-potribni-v-nazvah-interfejsiv]
 - [Поради щодо використання Composer |composer]
 - [Поради щодо редакторів та інструментів |editors-and-tools]
+- [Вступ до об'єктно-орієнтованого програмування |nette:introduction-to-object-oriented-programming]
 
 </div>
 <div>
diff --git a/best-practices/uk/attribute-requires.texy b/best-practices/uk/attribute-requires.texy
new file mode 100644
index 0000000000..543ae066c2
--- /dev/null
+++ b/best-practices/uk/attribute-requires.texy
@@ -0,0 +1,179 @@
+Як використовувати атрибут `#[Requires]` Атрибут
+************************************************
+
+.[perex]
+При написанні веб-додатків часто виникає потреба обмежити доступ до певних частин вашого додатку. Можливо, ви хочете, щоб деякі запити могли надсилати дані лише через форму (використовуючи метод POST) або щоб вони були доступні лише для AJAX-викликів. У Nette Framework 3.2 з'явився новий інструмент, який дозволяє елегантно і зрозуміло встановлювати такі обмеження: атрибут `#[Requires]` атрибут
+
+Атрибут - це спеціальний маркер в PHP, який ви додаєте перед визначенням класу або методу. Оскільки це, по суті, клас, вам потрібно включити речення use, щоб наведені нижче приклади працювали:
+
+```php
+use Nette\Application\Attributes\Requires;
+```
+
+Ви можете використовувати атрибут `#[Requires]` з самим класом доповідача та з цими методами:
+
+- `action<Action>()`
+- `render<View>()`
+- `handle<Signal>()`
+- `createComponent<Name>()`
+
+Останні два методи також стосуються компонентів, тому ви можете використовувати атрибут і з ними.
+
+Якщо умови, визначені атрибутом, не виконуються, генерується помилка HTTP 4xx.
+
+
+Методи HTTP .[#toc-http-methods]
+--------------------------------
+
+Ви можете вказати, які HTTP-методи (наприклад, GET, POST тощо) дозволені для доступу. Наприклад, якщо ви хочете дозволити доступ тільки за допомогою відправки форми, встановіть:
+
+```php
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST')]
+	public function actionDelete(int $id): void
+	{
+	}
+}
+```
+
+Чому для зміни стану слід використовувати POST, а не GET, і як це зробити? [Читайте гайд |post-links].
+
+Ви можете вказати метод або масив методів. Особливим випадком є значення `'*'`, щоб увімкнути всі методи, що не дозволяється за замовчуванням з [міркувань безпеки |application:presenters#http-method-check].
+
+
+AJAX-дзвінки .[#toc-ajax-calls]
+-------------------------------
+
+Якщо ви хочете, щоб доповідач або метод був доступний лише для AJAX-запитів, використовуйте цей параметр:
+
+```php
+#[Requires(ajax: true)]
+class AjaxPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Одного походження .[#toc-same-origin]
+-------------------------------------
+
+Щоб підвищити безпеку, ви можете вимагати, щоб запит був зроблений з того ж домену. Це запобігає [вразливості до CSRF |nette:vulnerability-protection#cross-site-request-forgery-csrf]:
+
+```php
+#[Requires(sameOrigin: true)]
+class SecurePresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Для методів `handle<Signal>()` автоматично вимагається доступ з того ж домену. Тому, якщо ви хочете дозволити доступ з будь-якого домену, вкажіть це:
+
+```php
+#[Requires(sameOrigin: false)]
+public function handleList(): void
+{
+}
+```
+
+
+Доступ через Форвард .[#toc-access-via-forward]
+-----------------------------------------------
+
+Іноді корисно обмежити доступ до презентера так, щоб він був доступний лише опосередковано, наприклад, за допомогою методів `forward()` або `switch()` з іншого презентера. Так захищаються презентери, що спричиняють помилки, щоб запобігти їхньому запуску з URL-адреси:
+
+```php
+#[Requires(forward: true)]
+class ForwardedPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+На практиці часто виникає потреба позначити певні подання, доступ до яких можна отримати лише на основі логіки в презентері. Знову ж таки, щоб їх не можна було відкрити безпосередньо:
+
+```php
+class ProductPresenter extends Nette\Application\UI\Presenter
+{
+
+	public function actionDefault(int $id): void
+	{
+		$product = this->facade->getProduct($id);
+		if (!product) {
+			this->setView('notfound');
+		}
+	}
+
+	#[Requires(forward: true)]
+	public function renderNotFound(): void
+	{
+	}
+}
+```
+
+
+Конкретні дії .[#toc-specific-actions]
+--------------------------------------
+
+Ви також можете обмежити доступ до певного коду, наприклад, створення компонента, лише для певних дій у презентері:
+
+```php
+class EditDeletePresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(actions: ['add', 'edit'])]
+	public function createComponentPostForm()
+	{
+	}
+}
+```
+
+Для однієї дії не потрібно писати масив: `#[Requires(actions: 'default')]`
+
+
+Користувацькі атрибути .[#toc-custom-attributes]
+------------------------------------------------
+
+Якщо ви хочете використовувати атрибут `#[Requires]` з тими самими налаштуваннями, ви можете створити власний атрибут, який успадкує `#[Requires]` і налаштувати його відповідно до ваших потреб.
+
+Наприклад `#[SingleAction]` дозволяє доступ тільки через дію `default`:
+
+```php
+#[Attribute]
+class SingleAction extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(actions: 'default');
+	}
+}
+
+#[SingleAction]
+class SingleActionPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+Або `#[RestMethods]` дозволить доступ за допомогою всіх HTTP-методів, що використовуються для REST API:
+
+```php
+#[\Attribute]
+class RestMethods extends Nette\Application\Attributes\Requires
+{
+	public function __construct()
+	{
+		parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
+	}
+}
+
+#[RestMethods]
+class ApiPresenter extends Nette\Application\UI\Presenter
+{
+}
+```
+
+
+Висновок .[#toc-conclusion]
+---------------------------
+
+Атрибут `#[Requires]` надає вам велику гнучкість і контроль над тим, як здійснюється доступ до ваших веб-сторінок. Використовуючи прості, але потужні правила, ви можете підвищити безпеку та належне функціонування вашого додатку. Як бачите, використання атрибутів у Nette може не тільки спростити вашу роботу, але й убезпечити її.
+
+{{sitename: Best Practices}}
diff --git a/best-practices/uk/composer.texy b/best-practices/uk/composer.texy
index 2eead46d70..e6777c8700 100644
--- a/best-practices/uk/composer.texy
+++ b/best-practices/uk/composer.texy
@@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update
 ```
 
 
+Ігнорування версії PHP .[#toc-ignoring-php-version]
+===================================================
+
+Пакунки зазвичай вказують як найнижчу версію PHP, з якою вони сумісні, так і найвищу версію, з якою вони були протестовані. Якщо ви плануєте використовувати ще новішу версію PHP, можливо, з метою тестування, Composer відмовиться встановлювати такий пакунок. Вирішенням проблеми є використання параметра `--ignore-platform-req=php+`, який змушує Composer ігнорувати верхні межі необхідної версії PHP.
+
+
 Неправдиві повідомлення .[#toc-false-reports]
 =============================================
 
@@ -183,7 +189,7 @@ Packagist.org - глобальний репозиторій .[#toc-packagist-org
 
 Згодом необхідно виконувати команду `composer dumpautoload` при кожній зміні та дозволяти таблицям автозавантаження регенеруватися. Це вкрай незручно, і набагато краще довірити цю задачу [RobotLoader |robot-loader:], який виконує ту ж саму роботу автоматично у фоновому режимі і набагато швидше.
 
-Другий варіант - слідувати [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Простіше кажучи, це система, в якій простори імен та імена класів відповідають структурі каталогів та іменам файлів, тобто `App\Router\RouterFactory` знаходиться у файлі `/path/to/App/Router/RouterFactory.php`. Приклад конфігурації:
+Другий варіант - слідувати [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Простіше кажучи, це система, в якій простори імен та імена класів відповідають структурі каталогів та іменам файлів, тобто `App\Core\RouterFactory` знаходиться у файлі `/path/to/App/Core/RouterFactory.php`. Приклад конфігурації:
 
 ```js
 {
diff --git a/best-practices/uk/dynamic-snippets.texy b/best-practices/uk/dynamic-snippets.texy
index 40867a88cf..33872a3b0e 100644
--- a/best-practices/uk/dynamic-snippets.texy
+++ b/best-practices/uk/dynamic-snippets.texy
@@ -35,7 +35,7 @@ Template:
 Аяксизація .[#toc-ajaxization]
 ==============================
 
-Тепер давайте привнесемо AJAX у цей простий додаток. Зміна рейтингу статті не настільки важлива, щоб вимагати HTTP-запит із переспрямуванням, тому в ідеалі це має бути зроблено за допомогою AJAX у фоновому режимі. Ми будемо використовувати [скрипт обробника з додат |https://componette.org/vojtech-dobes/nette.ajax.js/] ків зі звичайною угодою, що AJAX-посилання мають CSS клас `ajax`.
+Тепер давайте привнесемо AJAX у цей простий додаток. Зміна рейтингу статті не настільки важлива, щоб вимагати HTTP-запит із переспрямуванням, тому в ідеалі це має бути зроблено за допомогою AJAX у фоновому режимі. Ми будемо використовувати [скрипт обробника з додат |application:ajax#toc-naja] ків зі звичайною угодою, що AJAX-посилання мають CSS клас `ajax`.
 
 Однак як це зробити конкретно? Nette пропонує 2 способи: спосіб динамічних фрагментів і спосіб компонентів. Обидва мають свої плюси та мінуси, тому ми покажемо їх по черзі.
 
@@ -92,7 +92,7 @@ public function handleLike(int $articleId): void
 	if ($this->isAjax()) {
 		// ...
 		$this->template->articles = [
-			$this->connection->table('articles')->get($articleId),
+			$this->db->table('articles')->get($articleId),
 		];
 	} else {
 		// ...
@@ -101,7 +101,7 @@ public function handleLike(int $articleId): void
 public function renderDefault(): void
 {
 	if (!isset($this->template->articles)) {
-		$this->template->articles = $this->connection->table('articles');
+		$this->template->articles = $this->db->table('articles');
 	}
 }
 ```
@@ -151,7 +151,7 @@ class LikeControl extends Nette\Application\UI\Control
 ```php
 protected function createComponentLikeControl()
 {
-	$articles = $this->connection->table('articles');
+	$articles = $this->db->table('articles');
 	return new Nette\Application\UI\Multiplier(function (int $articleId) use ($articles) {
 		return new LikeControl($articles[$articleId]);
 	});
diff --git a/best-practices/uk/form-reuse.texy b/best-practices/uk/form-reuse.texy
index 7993290a51..38d700e84f 100644
--- a/best-practices/uk/form-reuse.texy
+++ b/best-practices/uk/form-reuse.texy
@@ -152,7 +152,7 @@ class EditFormFactory
 }
 ```
 
-Дуже важливо, щоб зв'язок між класами `FormFactory` і `EditFormFactory` був реалізований за допомогою композиції, а не успадкування об'єктів:
+Дуже важливо, що зв'язування між класами `FormFactory` та `EditFormFactory` реалізовано [за допомогою композиції |nette:introduction-to-object-oriented-programming#composition], а не [успадкування об'єктів |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]:
 
 ```php
 // НІ! СПАДЩИНА ТУТ НЕ МАЄ ЗНАЧЕННЯ
@@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory
 Використання успадкування в цьому випадку було б абсолютно контрпродуктивним. Ви б дуже швидко зіткнулися з проблемами. Наприклад, якщо ви захочете додати параметри до методу `create()`; PHP повідомить про помилку, що його сигнатура відрізняється від батьківської.
 Або при передачі залежності класу `EditFormFactory` через конструктор. Це призведе до того, що ми називаємо пеклом [конструктора |dependency-injection:passing-dependencies#Constructor hell].
 
-Загалом, краще надавати перевагу композиції, а не успадкуванню.
+Як правило, краще віддавати перевагу [композиції, а не успадкуванню |dependency-injection:faq#Why composition is preferred over inheritance].
 
 
 Обробка форм .[#toc-form-handling]
@@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	protected function createComponentEditForm(): Form
+	protected function createComponentEditForm(): EditControl
 	{
 		$control = $this->controlFactory->create();
 
diff --git a/best-practices/uk/lets-create-contact-form.texy b/best-practices/uk/lets-create-contact-form.texy
index 724f0c58d7..e4cc290b82 100644
--- a/best-practices/uk/lets-create-contact-form.texy
+++ b/best-practices/uk/lets-create-contact-form.texy
@@ -39,7 +39,7 @@ class HomePresenter extends Presenter
 Але що, якщо користувач не заповнить деякі поля? У такому випадку ми повинні повідомити йому, що це поле є обов'язковим для заповнення. Ми зробили це за допомогою методу `setRequired()`.
 Нарешті, ми також додали [подію |nette:glossary#events] `onSuccess`, яка спрацьовує в разі успішного відправлення форми. У нашому випадку вона викликає метод `contactFormSucceeded`, який відповідає за обробку надісланої форми. Ми додамо його до коду за мить.
 
-Нехай компонент `contantForm` рендериться в шаблоні `templates/Home/default.latte`:
+Нехай компонент `contantForm` рендериться в шаблоні `Home/default.latte`:
 
 ```latte
 {block content}
diff --git a/best-practices/uk/microsites.texy b/best-practices/uk/microsites.texy
new file mode 100644
index 0000000000..05599232db
--- /dev/null
+++ b/best-practices/uk/microsites.texy
@@ -0,0 +1,63 @@
+Як писати мікросайти
+********************
+
+Уявіть, що вам потрібно швидко створити невеликий сайт для майбутньої події вашої компанії. Він повинен бути простим, швидким і без зайвих складнощів. Ви можете подумати, що такий невеликий проект не потребує надійного фреймворку. Але що, якщо використання фреймворку Nette може значно спростити і прискорити цей процес?
+
+Навіть при створенні простих веб-сайтів не хочеться відмовлятися від комфорту. Ви не хочете винаходити велосипед. Не соромтеся лінуватися і балувати себе. Nette Framework також можна чудово використовувати як мікрофреймворк.
+
+Як може виглядати такий мікросайт? Наприклад, весь код сайту можна розмістити в одному файлі `index.php` в загальній папці:
+
+```php
+&lt;?php
+
+require __DIR__ . '/../vendor/autoload.php';
+
+$configurator = new Nette\Bootstrap\Configurator;
+$configurator->enableTracy(__DIR__ . '/../log');
+$configurator->setTempDirectory(__DIR__ . '/../temp');
+
+// створити контейнер DI на основі конфігурації в config.neon
+$configurator->addConfig(__DIR__ . '/../app/config.neon');
+$container = $configurator->createContainer();
+
+// налаштуйте маршрутизацію
+$router = new Nette\Application\Routers\RouteList;
+$container->addService('router', $router);
+
+// маршрут для URL https://example.com/
+$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) {
+	// визначити мову браузера і перенаправити на URL /en або /de і т.д.
+	$supportedLangs = ['en', 'de', 'cs'];
+	$lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs);
+	$presenter->redirectUrl("/$lang");
+});
+
+// маршрут для URL https://example.com/cs nebo https://example.com/en
+$router->addRoute('<lang cs|en>', function ($presenter, string $lang) {
+	// відобразити відповідний шаблон, наприклад ../templates/en.latte
+	$template = $presenter->createTemplate()
+		->setFile(__DIR__ . '/../templates/' . $lang . '.latte');
+	return $template;
+});
+
+// запускаємо додаток!
+$container->getByType(Nette\Application\Application::class)->run();
+```
+
+Все інше буде шаблонами, що зберігаються в батьківській папці `/templates`.
+
+PHP-код в `index.php` спочатку налаштовує [середовище |bootstrap:], потім визначає [маршрути |application:routing#dynamic-routing-with-callbacks] і, нарешті, запускає додаток. Перевага полягає в тому, що другим параметром функції `addRoute()` може бути виклик, який виконується при відкритті відповідної сторінки.
+
+
+Чому варто використовувати Nette для мікросайтів? .[#toc-why-use-nette-for-microsites]
+--------------------------------------------------------------------------------------
+
+- Розробники, які хоч раз спробували [Tracy |tracy:], не можуть уявити собі кодування без нього сьогодні.
+- Але перш за все, ви будете використовувати систему шаблонів [Latte |latte:], тому що всього з 2 сторінок ви захочете відокремити [макет і контент |latte:template-inheritance].
+- І ви точно захочете покластися на [автоматичне |latte:safety-first] екранування, щоб запобігти XSS-уразливостям.
+- Nette також гарантує, що у випадку помилки, повідомлення про помилки PHP ніколи не будуть відображатися, а натомість буде показана зручна для користувача сторінка.
+- Якщо ви хочете отримати зворотній зв'язок від користувачів, наприклад, у вигляді контактної форми, ви також можете додати [форми |forms:] і [базу даних |database:].
+- Ви також можете легко надсилати заповнені форми [електронною |mail:] поштою.
+- Іноді вам може стати в нагоді [кешування |caching:], наприклад, при завантаженні та відображенні новин.
+
+У наш час, коли швидкість та ефективність є ключовими, важливо мати інструменти, які дозволяють досягати результатів без зайвих затримок. Фреймворк Nette пропонує саме це - швидку розробку, безпеку та широкий спектр інструментів, таких як Tracy та Latte, які спрощують процес. Просто встановіть кілька пакетів Nette, і створення такого мікросайту стане легкою справою. І ви знаєте, що немає ніяких прихованих вразливостей у безпеці.
diff --git a/best-practices/uk/pagination.texy b/best-practices/uk/pagination.texy
index b0883298b5..c74c942c2e 100644
--- a/best-practices/uk/pagination.texy
+++ b/best-practices/uk/pagination.texy
@@ -11,7 +11,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -34,7 +33,7 @@ class ArticleRepository
 Потім у презентері ми вводимо клас моделі і в методі `render` запитуємо опубліковані статті, які передаємо в шаблон:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 }
 ```
 
-У шаблоні ми подбаємо про виведення списку статей:
+Після цього шаблон `default.latte` подбає про список статей:
 
 ```latte
 {block content}
@@ -114,7 +113,7 @@ class ArticleRepository
 Ми також розширюємо метод `render` для отримання екземпляра Paginator, його налаштування та вибору потрібних статей для відображення в шаблоні. HomePresenter матиме такий вигляд:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
@@ -190,7 +189,6 @@ namespace App\Model;
 
 use Nette;
 
-
 class ArticleRepository
 {
 	public function __construct(
@@ -198,7 +196,6 @@ class ArticleRepository
 	) {
 	}
 
-
 	public function findPublishedArticles(): Nette\Database\Table\Selection
 	{
 		return $this->database->table('articles')
@@ -211,7 +208,7 @@ class ArticleRepository
 Нам не потрібно створювати Paginator у презентері, натомість ми використовуватимемо метод об'єкта `Selection`, який повертає сховище:
 
 ```php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
 use App\Model\ArticleRepository;
diff --git a/best-practices/uk/post-links.texy b/best-practices/uk/post-links.texy
new file mode 100644
index 0000000000..b0e7213fc5
--- /dev/null
+++ b/best-practices/uk/post-links.texy
@@ -0,0 +1,59 @@
+Як правильно використовувати POST-посилання
+*******************************************
+
+У веб-додатках, особливо в адміністративних інтерфейсах, основним правилом має бути те, що дії, які змінюють стан сервера, не повинні виконуватися за допомогою методу HTTP GET. Як випливає з назви методу, GET слід використовувати тільки для отримання даних, а не для їх зміни.
+Для таких дій, як видалення записів, доцільніше використовувати метод POST. Хоча ідеальним варіантом було б використання методу DELETE, але його неможливо викликати без JavaScript, тому історично використовується POST.
+
+Як це зробити на практиці? Використовуйте цей простий трюк. На початку вашого шаблону створіть допоміжну форму з ідентифікатором `postForm`, яку ви потім будете використовувати для кнопок видалення:
+
+```latte .{file:@layout.latte}
+<form method="post" id="postForm"></form>
+```
+
+У цій формі ви можете використовувати `<button>` замість класичного `<a>` посилання, яке можна візуально модифікувати, щоб воно виглядало як звичайне. Наприклад, CSS-фреймворк Bootstrap пропонує класи `btn btn-link`, які дозволяють візуально відрізнити кнопку від інших посилань. Використовуючи атрибут `form="postForm"`, ми пов'язуємо її з заздалегідь підготовленою формою:
+
+```latte .{file:admin.latte}
+<table>
+	<tr n:foreach="$posts as $post">
+		<td>{$post->title}</td>
+		<td>
+			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
+			<!-- instead of <a n:href="delete $post->id">delete</a> -->
+		</td>
+	</tr>
+</table>
+```
+
+При натисканні на посилання тепер викликається дія `delete`. Щоб запити приймалися тільки методом POST і з одного домену (що є ефективним захистом від CSRF-атак), використовуйте атрибут `#[Requires]` атрибут
+
+```php .{file:AdminPresenter.php}
+use Nette\Application\Attributes\Requires;
+
+class AdminPresenter extends Nette\Application\UI\Presenter
+{
+	#[Requires(methods: 'POST', sameOrigin: true)]
+	public function actionDelete(int $id): void
+	{
+		$this->facade->deletePost($id); // hypothetical code for deleting a record
+		$this->redirect('default');
+	}
+}
+```
+
+Атрибут доступний з версії Nette Application 3.2, і ви можете дізнатися більше про його можливості на сторінці [Як використовувати атрибут #Requires |attribute-requires].
+
+Якщо ви використовували сигнал `handleDelete()` замість дії `actionDelete()`, то не обов'язково вказувати `sameOrigin: true`, оскільки в сигналах цей захист встановлено неявно:
+
+```php .{file:AdminPresenter.php}
+#[Requires(methods: 'POST')]
+public function handleDelete(int $id): void
+{
+	$this->facade->deletePost($id);
+	$this->redirect('this');
+}
+```
+
+Такий підхід не тільки підвищує безпеку вашого додатку, але й сприяє дотриманню належних веб-стандартів і практик. Використовуючи методи POST для дій, що змінюють стан, ви отримуєте більш надійний і безпечний додаток.
+
+
+{{sitename: Best Practices}}
diff --git a/best-practices/uk/presenter-traits.texy b/best-practices/uk/presenter-traits.texy
index 9530556a56..edc2530464 100644
--- a/best-practices/uk/presenter-traits.texy
+++ b/best-practices/uk/presenter-traits.texy
@@ -2,7 +2,7 @@
 *****************************
 
 .[perex]
-Якщо нам потрібно реалізувати один і той самий код у кількох презентерах (наприклад, перевірка того, що користувач увійшов у систему), заманливо помістити цей код у спільного предка. Другий варіант - створити одноцільові трейти.
+Якщо нам потрібно реалізувати один і той самий код у декількох презентерах (наприклад, перевірка того, що користувач увійшов до системи), виникає спокуса помістити код у спільного предка. Другий варіант - створення одноцільових [ознак |nette:introduction-to-object-oriented-programming#traits].
 
 Перевага цього рішення полягає в тому, що кожен ведучий може використовувати тільки ті ознаки, які йому справді потрібні, тоді як множинне успадкування в PHP неможливе.
 
diff --git a/caching/bg/@home.texy b/caching/bg/@home.texy
index 20a4992b5a..5acf57077c 100644
--- a/caching/bg/@home.texy
+++ b/caching/bg/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Използване с PSR-16 .[#toc-using-with-psr-16]
+=============================================
+
+За да използвате Nette Cache с интерфейса PSR-16, можете да използвате `PsrCacheAdapter`. Той позволява безпроблемна интеграция между Nette Cache и всеки код или библиотека, които очакват съвместим с PSR-16 кеш.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Сега можете да използвате `$psrCache` като кеш за PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // съхранява стойността за 1 час
+$value = $psrCache->get('key', 'default');
+```
+
+Адаптерът поддържа всички методи, дефинирани в PSR-16, включително `getMultiple()`, `setMultiple()` и `deleteMultiple()`.
+
+
 Изходно кеширане .[#toc-output-caching]
 =======================================
 
@@ -455,4 +474,17 @@ services:
 | `cache.storage` | [api:Nette\Caching\Storage] | хранилище
 
 
+Изключване на кеша .[#toc-turning-off-cache]
+============================================
+
+Един от начините да изключите кеширането в приложението е да зададете съхранение на [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Тази настройка не влияе на кеширането на шаблоните в Latte или контейнера DI, тъй като тези библиотеки не използват услугите на nette/caching и управляват кеша си самостоятелно. Освен това [не е необходимо |nette:troubleshooting#how-to-disable-cache-during-development] техният кеш да [бъде изключен |nette:troubleshooting#how-to-disable-cache-during-development] в режим на разработка.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/cs/@home.texy b/caching/cs/@home.texy
index 8ccf9abb56..899fa8719c 100644
--- a/caching/cs/@home.texy
+++ b/caching/cs/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Použití s PSR-16 .{data-version:3.3.1}
+======================================
+
+Pro použití Nette Cache s rozhraním PSR-16 můžete využít adaptér `PsrCacheAdapter`. Umožňuje bezešvou integraci mezi Nette Cache a jakýmkoli kódem nebo knihovnou, která očekává PSR-16 kompatibilní cache.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Nyní můžete používat `$psrCache` jako PSR-16 cache:
+
+```php
+$psrCache->set('key', 'value', 3600); // uloží hodnotu na 1 hodinu
+$value = $psrCache->get('key', 'default');
+```
+
+Adaptér podporuje všechny metody definované v PSR-16, včetně `getMultiple()`, `setMultiple()`, a `deleteMultiple()`.
+
+
 Cachování výstupu
 =================
 
@@ -455,4 +474,17 @@ Tyto služby se přidávají do DI kontejneru:
 | `cache.storage`  |  [api:Nette\Caching\Storage]           |  úložiště
 
 
+Vypnutí cache
+=============
+
+Jednou z možností, jak vypnout cache v aplikaci, je nastavit jako úložiště [DevNullStorage|#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Toto nastavení nemá vliv na kešování šablon v Latte nebo DI kontejeru, protože tyto knihovny nevyužívají služeb nette/caching a spravují si cache samostatně. Jejich cache ostatně [není potřeba |nette:troubleshooting#jak-vypnout-cache-behem-vyvoje] ve vývojářském režimu vypínat.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/de/@home.texy b/caching/de/@home.texy
index b69531fee2..85473b01aa 100644
--- a/caching/de/@home.texy
+++ b/caching/de/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Verwendung mit PSR-16 .[#toc-using-with-psr-16]
+===============================================
+
+Um Nette Cache mit der PSR-16-Schnittstelle zu verwenden, können Sie die `PsrCacheAdapter` verwenden. Sie ermöglicht eine nahtlose Integration zwischen Nette Cache und jedem Code oder jeder Bibliothek, die einen PSR-16-kompatiblen Cache erwartet.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Jetzt können Sie `$psrCache` als PSR-16-Cache verwenden:
+
+```php
+$psrCache->set('key', 'value', 3600); // speichert den Wert für 1 Stunde
+$value = $psrCache->get('key', 'default');
+```
+
+Der Adapter unterstützt alle in PSR-16 definierten Methoden, einschließlich `getMultiple()`, `setMultiple()` und `deleteMultiple()`.
+
+
 Zwischenspeicherung der Ausgabe .[#toc-output-caching]
 ======================================================
 
@@ -455,4 +474,17 @@ Diese Dienste werden dem DI-Container hinzugefügt:
 | `cache.storage` | [api:Nette\Caching\Storage] | repository
 
 
+Cache ausschalten .[#toc-turning-off-cache]
+===========================================
+
+Eine Möglichkeit, die Zwischenspeicherung in der Anwendung zu deaktivieren, besteht darin, den Speicher auf [DevNullStorage |#DevNullStorage] zu setzen:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Diese Einstellung wirkt sich nicht auf die Zwischenspeicherung von Vorlagen in Latte oder dem DI-Container aus, da diese Bibliotheken nicht die Dienste von nette/caching nutzen und ihren Cache unabhängig verwalten. Außerdem [muss |nette:troubleshooting#how-to-disable-cache-during-development] ihr Cache im Entwicklungsmodus [nicht abgeschaltet werden |nette:troubleshooting#how-to-disable-cache-during-development].
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/el/@home.texy b/caching/el/@home.texy
index 309a4273d8..aabc12cb7b 100644
--- a/caching/el/@home.texy
+++ b/caching/el/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Χρήση με PSR-16 .[#toc-using-with-psr-16]
+=========================================
+
+Για να χρησιμοποιήσετε τη Nette Cache με τη διασύνδεση PSR-16, μπορείτε να χρησιμοποιήσετε το `PsrCacheAdapter`. Επιτρέπει την απρόσκοπτη ενσωμάτωση μεταξύ της Nette Cache και οποιουδήποτε κώδικα ή βιβλιοθήκης που αναμένει μια κρυφή μνήμη συμβατή με PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Τώρα μπορείτε να χρησιμοποιήσετε το `$psrCache` ως κρυφή μνήμη PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // αποθηκεύει την τιμή για 1 ώρα
+$value = $psrCache->get('key', 'default');
+```
+
+Ο προσαρμογέας υποστηρίζει όλες τις μεθόδους που ορίζονται στο PSR-16, συμπεριλαμβανομένων των `getMultiple()`, `setMultiple()` και `deleteMultiple()`.
+
+
 Προσωρινή αποθήκευση εξόδου .[#toc-output-caching]
 ==================================================
 
@@ -455,4 +474,17 @@ services:
 | `cache.storage` | [api:Nette\Caching\Storage] | repository
 
 
+Απενεργοποίηση της κρυφής μνήμης .[#toc-turning-off-cache]
+==========================================================
+
+Ένας από τους τρόπους για να απενεργοποιήσετε την προσωρινή αποθήκευση στην εφαρμογή είναι να ορίσετε τον αποθηκευτικό χώρο σε [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Αυτή η ρύθμιση δεν επηρεάζει την προσωρινή αποθήκευση των προτύπων στο Latte ή στο DI container, καθώς αυτές οι βιβλιοθήκες δεν χρησιμοποιούν τις υπηρεσίες της nette/caching και διαχειρίζονται την προσωρινή τους μνήμη ανεξάρτητα. Επιπλέον, η κρυφή μνήμη τους [δεν χρειάζεται να απ |nette:troubleshooting#how-to-disable-cache-during-development] ενεργοποιηθεί στη λειτουργία ανάπτυξης.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/en/@home.texy b/caching/en/@home.texy
index b8cb141247..c0e9561b5d 100644
--- a/caching/en/@home.texy
+++ b/caching/en/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Using with PSR-16 .{data-version:3.3.1}
+=======================================
+
+To use Nette Cache with the PSR-16 interface, you can utilize the `PsrCacheAdapter`. It allows seamless integration between Nette Cache and any code or library that expects a PSR-16 compatible cache.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Now you can use `$psrCache` as a PSR-16 cache:
+
+```php
+$psrCache->set('key', 'value', 3600); // stores the value for 1 hour
+$value = $psrCache->get('key', 'default');
+```
+
+The adapter supports all methods defined in PSR-16, including `getMultiple()`, `setMultiple()`, and `deleteMultiple()`.
+
+
 Output Caching
 ==============
 
@@ -455,4 +474,17 @@ These services are added to the DI container:
 | `cache.storage` | [api:Nette\Caching\Storage] | repository
 
 
+Turning Off Cache
+=================
+
+One of the ways to turn off caching in the application is to set the storage to [DevNullStorage|#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+This setting does not affect the caching of templates in Latte or the DI container, as these libraries do not use the services of nette/caching and manage their cache independently. Moreover, their cache [does not need to be turned off |nette:troubleshooting#how-to-disable-cache-during-development] in development mode.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/es/@home.texy b/caching/es/@home.texy
index 531dadfdec..5b4618d1b7 100644
--- a/caching/es/@home.texy
+++ b/caching/es/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Uso con PSR-16 .[#toc-using-with-psr-16]
+========================================
+
+Para utilizar Nette Cache con la interfaz PSR-16, puede utilizar el `PsrCacheAdapter`. Permite una integración perfecta entre Nette Cache y cualquier código o librería que espere una caché compatible con PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Ahora puedes utilizar `$psrCache` como caché PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // almacena el valor durante 1 hora
+$value = $psrCache->get('key', 'default');
+```
+
+El adaptador admite todos los métodos definidos en PSR-16, incluidos `getMultiple()`, `setMultiple()` y `deleteMultiple()`.
+
+
 Caché de salida .[#toc-output-caching]
 ======================================
 
@@ -455,4 +474,17 @@ Estos servicios se añaden al contenedor DI:
 | `cache.storage` | [api:Nette\Caching\Storage] | Repositorio
 
 
+Cómo desactivar la caché .[#toc-turning-off-cache]
+==================================================
+
+Una de las formas de desactivar el almacenamiento en caché en la aplicación es establecer el almacenamiento a [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Esta configuración no afecta al almacenamiento en caché de las plantillas en Latte o el contenedor DI, ya que estas bibliotecas no utilizan los servicios de nette/caching y gestionan su caché de forma independiente. Además, [no es necesario desactivar |nette:troubleshooting#how-to-disable-cache-during-development] su caché en el modo de desarrollo.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/fr/@home.texy b/caching/fr/@home.texy
index 0a470bcc93..af09b8957a 100644
--- a/caching/fr/@home.texy
+++ b/caching/fr/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Utilisation avec PSR-16 .[#toc-using-with-psr-16]
+=================================================
+
+Pour utiliser Nette Cache avec l'interface PSR-16, vous pouvez utiliser le site `PsrCacheAdapter`. Il permet une intégration transparente entre Nette Cache et tout code ou bibliothèque qui attend un cache compatible PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Vous pouvez désormais utiliser `$psrCache` comme cache PSR-16 :
+
+```php
+$psrCache->set('key', 'value', 3600); // mémorise la valeur pour 1 heure
+$value = $psrCache->get('key', 'default');
+```
+
+L'adaptateur supporte toutes les méthodes définies dans PSR-16, y compris `getMultiple()`, `setMultiple()`, et `deleteMultiple()`.
+
+
 Mise en cache de la sortie .[#toc-output-caching]
 =================================================
 
@@ -455,4 +474,17 @@ Ces services sont ajoutés au conteneur DI :
 | `cache.storage` | [api:Nette\Caching\Storage] | repository
 
 
+Désactiver le cache .[#toc-turning-off-cache]
+=============================================
+
+L'une des façons de désactiver la mise en cache dans l'application est de définir le stockage sur [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Ce paramètre n'affecte pas la mise en cache des modèles dans Latte ou le conteneur DI, car ces bibliothèques n'utilisent pas les services de nette/caching et gèrent leur cache de manière indépendante. De plus, leur cache n ['a pas besoin d'être désactivé |nette:troubleshooting#how-to-disable-cache-during-development] en mode développement.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/hu/@home.texy b/caching/hu/@home.texy
index 35a2b69b1a..0ea9d77546 100644
--- a/caching/hu/@home.texy
+++ b/caching/hu/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+PSR-16 használatával .[#toc-using-with-psr-16]
+==============================================
+
+A Nette Cache PSR-16 interfésszel való használatához használhatja a `PsrCacheAdapter`. Ez lehetővé teszi a Nette Cache és bármely olyan kód vagy könyvtár közötti zökkenőmentes integrációt, amely PSR-16 kompatibilis gyorsítótárat vár el.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Most már használhatja a `$psrCache` oldalt PSR-16 gyorsítótárként:
+
+```php
+$psrCache->set('key', 'value', 3600); // 1 órán át tárolja az értéket
+$value = $psrCache->get('key', 'default');
+```
+
+Az adapter támogatja a PSR-16-ban definiált összes módszert, beleértve a `getMultiple()`, `setMultiple()` és `deleteMultiple()` módszereket.
+
+
 Kimeneti gyorsítótárazás .[#toc-output-caching]
 ===============================================
 
@@ -455,4 +474,17 @@ Ezek a szolgáltatások hozzáadódnak a DI konténerhez:
 | `cache.storage` | [api:Nette\Caching\Storage] | repository
 
 
+Cache kikapcsolása .[#toc-turning-off-cache]
+============================================
+
+A gyorsítótár kikapcsolásának egyik módja az alkalmazásban a tároló [DevNullStorage |#DevNullStorage] értékre állítása:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Ez a beállítás nem befolyásolja a Latte vagy a DI konténer sablonjainak gyorsítótárazását, mivel ezek a könyvtárak nem használják a nette/caching szolgáltatásait, és önállóan kezelik a gyorsítótárukat. Ráadásul a gyorsítótárukat [nem kell kikapcsolni |nette:troubleshooting#how-to-disable-cache-during-development] fejlesztési módban.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/it/@home.texy b/caching/it/@home.texy
index a2ffac4a4e..4d4354fe6d 100644
--- a/caching/it/@home.texy
+++ b/caching/it/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Utilizzo con PSR-16 .[#toc-using-with-psr-16]
+=============================================
+
+Per utilizzare Nette Cache con l'interfaccia PSR-16, è possibile utilizzare il programma `PsrCacheAdapter`. Esso consente una perfetta integrazione tra Nette Cache e qualsiasi codice o libreria che preveda una cache compatibile con PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Ora è possibile utilizzare `$psrCache` come cache PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // memorizza il valore per 1 ora
+$value = $psrCache->get('key', 'default');
+```
+
+L'adattatore supporta tutti i metodi definiti in PSR-16, compresi `getMultiple()`, `setMultiple()` e `deleteMultiple()`.
+
+
 Caching dell'output .[#toc-output-caching]
 ==========================================
 
@@ -455,4 +474,17 @@ Questi servizi vengono aggiunti al contenitore DI:
 | `cache.storage` | [api:Nette\Caching\Storage] | repository
 
 
+Disattivare la cache .[#toc-turning-off-cache]
+==============================================
+
+Uno dei modi per disattivare la cache nell'applicazione è impostare lo storage su [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Questa impostazione non influisce sulla cache dei modelli in Latte o nel contenitore DI, poiché queste librerie non utilizzano i servizi di nette/caching e gestiscono la loro cache in modo indipendente. Inoltre, la loro cache [non deve essere disattivata |nette:troubleshooting#how-to-disable-cache-during-development] in modalità di sviluppo.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/pl/@home.texy b/caching/pl/@home.texy
index dcce5e86e5..e5b686e755 100644
--- a/caching/pl/@home.texy
+++ b/caching/pl/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Używanie z PSR-16 .[#toc-using-with-psr-16]
+===========================================
+
+Aby używać Nette Cache z interfejsem PSR-16, można skorzystać z `PsrCacheAdapter`. Pozwala to na płynną integrację Nette Cache z dowolnym kodem lub biblioteką, która oczekuje pamięci podręcznej kompatybilnej z PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Teraz można używać `$psrCache` jako pamięci podręcznej PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // przechowuje wartość przez 1 godzinę
+$value = $psrCache->get('key', 'default');
+```
+
+Adapter obsługuje wszystkie metody zdefiniowane w PSR-16, w tym `getMultiple()`, `setMultiple()` i `deleteMultiple()`.
+
+
 Buforowanie wyjścia .[#toc-output-caching]
 ==========================================
 
@@ -455,4 +474,17 @@ Usługi te są dodawane do kontenera DI:
 | `cache.storage` | [api:Nette\Caching\Storage] | repozytorium
 
 
+Wyłączanie pamięci podręcznej .[#toc-turning-off-cache]
+=======================================================
+
+Jednym ze sposobów wyłączenia buforowania w aplikacji jest ustawienie pamięci masowej na [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Ustawienie to nie wpływa na buforowanie szablonów w Latte lub kontenerze DI, ponieważ biblioteki te nie korzystają z usług nette/caching i zarządzają swoją pamięcią podręczną niezależnie. Co więcej, ich pamięć podręczna nie musi być [wyłączona |nette:troubleshooting#how-to-disable-cache-during-development] w trybie deweloperskim.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/pt/@home.texy b/caching/pt/@home.texy
index 7e1585db49..4b202ae575 100644
--- a/caching/pt/@home.texy
+++ b/caching/pt/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Uso com o PSR-16 .[#toc-using-with-psr-16]
+==========================================
+
+Para usar o Nette Cache com a interface PSR-16, você pode utilizar o site `PsrCacheAdapter`. Ele permite uma integração perfeita entre o Nette Cache e qualquer código ou biblioteca que espere um cache compatível com PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Agora você pode usar o `$psrCache` como um cache PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // armazena o valor por 1 hora
+$value = $psrCache->get('key', 'default');
+```
+
+O adaptador suporta todos os métodos definidos no PSR-16, incluindo `getMultiple()`, `setMultiple()` e `deleteMultiple()`.
+
+
 Caching de saída .[#toc-output-caching]
 =======================================
 
@@ -455,4 +474,17 @@ Esses serviços são adicionados ao contêiner DI:
 | `cache.storage` | [api:Nette\Caching\Storage] | repositório
 
 
+Desativação do cache .[#toc-turning-off-cache]
+==============================================
+
+Uma das maneiras de desativar o cache no aplicativo é definir o armazenamento como [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Essa configuração não afeta o armazenamento em cache dos modelos no Latte ou no contêiner DI, pois essas bibliotecas não usam os serviços do nette/caching e gerenciam seu cache de forma independente. Além disso, seu cache [não precisa ser desativ |nette:troubleshooting#how-to-disable-cache-during-development] ado no modo de desenvolvimento.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/ro/@home.texy b/caching/ro/@home.texy
index 179a0e2532..438712e0f3 100644
--- a/caching/ro/@home.texy
+++ b/caching/ro/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Utilizarea cu PSR-16 .[#toc-using-with-psr-16]
+==============================================
+
+Pentru a utiliza Nette Cache cu interfața PSR-16, puteți utiliza `PsrCacheAdapter`. Aceasta permite integrarea perfectă între Nette Cache și orice cod sau bibliotecă care așteaptă o cache compatibilă cu PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Acum puteți utiliza `$psrCache` ca o cache PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // stochează valoarea pentru 1 oră
+$value = $psrCache->get('key', 'default');
+```
+
+Adaptorul acceptă toate metodele definite în PSR-16, inclusiv `getMultiple()`, `setMultiple()`, și `deleteMultiple()`.
+
+
 Stocarea în memoria cache de ieșire .[#toc-output-caching]
 ==========================================================
 
@@ -455,4 +474,17 @@ Nume | Tip | Descriere
  `cache.storage` | [api:Nette\Caching\Storage] | | repository
 
 
+Dezactivarea memoriei cache .[#toc-turning-off-cache]
+=====================================================
+
+Una dintre modalitățile de dezactivare a memoriei cache în aplicație este să setați stocarea la [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Această setare nu afectează memoria cache a șabloanelor din Latte sau din containerul DI, deoarece aceste biblioteci nu utilizează serviciile nette/caching și își gestionează memoria cache în mod independent. În plus, memoria cache a acestora [nu trebuie dezactivată |nette:troubleshooting#how-to-disable-cache-during-development] în modul de dezvoltare.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/ru/@home.texy b/caching/ru/@home.texy
index 79f33dd961..b6014f6083 100644
--- a/caching/ru/@home.texy
+++ b/caching/ru/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Использование с PSR-16 .[#toc-using-with-psr-16]
+================================================
+
+Чтобы использовать Nette Cache с интерфейсом PSR-16, вы можете воспользоваться сайтом `PsrCacheAdapter`. Он позволяет легко интегрировать Nette Cache с любым кодом или библиотекой, которая ожидает наличия кэша, совместимого с PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Теперь вы можете использовать `$psrCache` в качестве кэша PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // сохраняет значение в течение 1 часа
+$value = $psrCache->get('key', 'default');
+```
+
+Адаптер поддерживает все методы, определенные в PSR-16, включая `getMultiple()`, `setMultiple()` и `deleteMultiple()`.
+
+
 Кэширование вывода .[#toc-output-caching]
 =========================================
 
@@ -455,4 +474,17 @@ services:
 | `cache.storage` | [api:Nette\Caching\Storage] | репозиторий
 
 
+Отключение кэша .[#toc-turning-off-cache]
+=========================================
+
+Одним из способов отключения кэширования в приложении является установка для хранилища значения [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Данная настройка не влияет на кэширование шаблонов в Latte или контейнере DI, так как эти библиотеки не используют сервисы nette/caching и управляют своим кэшем самостоятельно. Более того, их кэш [не нужно отключать |nette:troubleshooting#how-to-disable-cache-during-development] в режиме разработки.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/sl/@home.texy b/caching/sl/@home.texy
index 494f73a22a..49db83179c 100644
--- a/caching/sl/@home.texy
+++ b/caching/sl/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Uporaba s PSR-16 .[#toc-using-with-psr-16]
+==========================================
+
+Za uporabo predpomnilnika Nette Cache z vmesnikom PSR-16 lahko uporabite `PsrCacheAdapter`. Ta omogoča nemoteno integracijo med predpomnilnikom Nette Cache in katero koli kodo ali knjižnico, ki pričakuje predpomnilnik, združljiv s PSR-16.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Zdaj lahko `$psrCache` uporabljate kot predpomnilnik PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // shrani vrednost za 1 uro
+$value = $psrCache->get('key', 'default');
+```
+
+Adapter podpira vse metode, opredeljene v PSR-16, vključno s `getMultiple()`, `setMultiple()` in `deleteMultiple()`.
+
+
 Izhodno predpomnjenje .[#toc-output-caching]
 ============================================
 
@@ -455,4 +474,17 @@ Te storitve so dodane vsebniku DI:
 | `cache.storage` | [api:Nette\Caching\Storage] | repozitorij
 
 
+Izklop predpomnilnika .[#toc-turning-off-cache]
+===============================================
+
+Eden od načinov za izklop predpomnilnika v aplikaciji je nastavitev shrambe na [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Ta nastavitev ne vpliva na predpomnjenje predlog v Latte ali vsebniku DI, saj ti knjižnici ne uporabljata storitev nette/caching in upravljata svoj predpomnilnik neodvisno. Poleg tega njihovega predpomnilnika v razvojnem načinu [ni treba izklopiti |nette:troubleshooting#how-to-disable-cache-during-development].
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/tr/@home.texy b/caching/tr/@home.texy
index 8ef3ab0725..00849f169d 100644
--- a/caching/tr/@home.texy
+++ b/caching/tr/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+PSR-16 ile kullanma .[#toc-using-with-psr-16]
+=============================================
+
+Nette Cache'i PSR-16 arayüzü ile kullanmak için `PsrCacheAdapter` adresinden yararlanabilirsiniz. Nette Cache ile PSR-16 uyumlu bir önbellek bekleyen herhangi bir kod veya kütüphane arasında sorunsuz entegrasyon sağlar.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Artık `$psrCache` adresini PSR-16 önbelleği olarak kullanabilirsiniz:
+
+```php
+$psrCache->set('key', 'value', 3600); // değeri 1 saat boyunca saklar
+$value = $psrCache->get('key', 'default');
+```
+
+Bağdaştırıcı, `getMultiple()`, `setMultiple()` ve `deleteMultiple()` dahil olmak üzere PSR-16'da tanımlanan tüm yöntemleri destekler.
+
+
 Çıktı Önbelleğe Alma .[#toc-output-caching]
 ===========================================
 
@@ -455,4 +474,17 @@ Bu hizmetler DI konteynerine eklenir:
 | `cache.storage` | [api:Nette\Caching\Storage] | depo
 
 
+Önbelleği Kapatma .[#toc-turning-off-cache]
+===========================================
+
+Uygulamada önbelleğe almayı kapatmanın yollarından biri depolamayı [DevNullStorage |#DevNullStorage] olarak ayarlamaktır:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Bu ayar, Latte veya DI konteynerindeki şablonların önbelleğe alınmasını etkilemez, çünkü bu kütüphaneler nette/caching hizmetlerini kullanmaz ve önbelleklerini bağımsız olarak yönetir. Ayrıca, geliştirme modunda önbelleklerinin [kapatılmasına gerek yoktur |nette:troubleshooting#how-to-disable-cache-during-development].
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/caching/uk/@home.texy b/caching/uk/@home.texy
index 6e32f166ce..af0846f79d 100644
--- a/caching/uk/@home.texy
+++ b/caching/uk/@home.texy
@@ -266,6 +266,25 @@ $values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
 ```
 
 
+Використання з PSR-16 .[#toc-using-with-psr-16]
+===============================================
+
+Щоб використовувати Nette Cache з інтерфейсом PSR-16, ви можете скористатися `PsrCacheAdapter`. Він дозволяє легко інтегрувати Nette Cache з будь-яким кодом або бібліотекою, що очікує використання PSR-16-сумісного кешу.
+
+```php
+$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
+```
+
+Тепер ви можете використовувати `$psrCache` як кеш PSR-16:
+
+```php
+$psrCache->set('key', 'value', 3600); // зберігає значення протягом 1 години
+$value = $psrCache->get('key', 'default');
+```
+
+Адаптер підтримує всі методи, визначені в PSR-16, включаючи `getMultiple()`, `setMultiple()` і `deleteMultiple()`.
+
+
 Кешування виведення .[#toc-output-caching]
 ==========================================
 
@@ -455,4 +474,17 @@ services:
 | `cache.storage` | [api:Nette\Caching\Storage] | репозиторій
 
 
+Вимкнення кешу .[#toc-turning-off-cache]
+========================================
+
+Один із способів вимкнути кешування в додатку - встановити для сховища значення [DevNullStorage |#DevNullStorage]:
+
+```neon
+services:
+	cache.storage: Nette\Caching\Storages\DevNullStorage
+```
+
+Це налаштування не впливає на кешування шаблонів у Latte або контейнері DI, оскільки ці бібліотеки не використовують сервіси nette/caching і керують своїм кешем самостійно. Крім того, їх кеш [не потрібно |nette:troubleshooting#how-to-disable-cache-during-development] вимикати в режимі розробки.
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/component-model/bg/@home.texy b/component-model/bg/@home.texy
index 133570acc4..824df10749 100644
--- a/component-model/bg/@home.texy
+++ b/component-model/bg/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Връща компонент. Опитът за извикване на недефиниран дъщерен компонент води до извикване на factory [createComponent($name |api:Nette\ComponentModel\Container::createComponent()]). Методът `createComponent($name)` извиква метода `createComponent<component name>` в текущия компонент и предава името на компонента като параметър. След това създаденият компонент се предава на текущия компонент като негов дъщерен компонент. Наричаме тези фабрики за компоненти, като те могат да бъдат реализирани в класове, наследени от `Container`.
 
 
-Итерация над подчинени компоненти .[#toc-iterating-over-children]
------------------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Връща преките наследници като масив. Ключовете съдържат имената на тези компоненти. Забележка: във версия 3.0.x методът връщаше итератор вместо масив, като първият му параметър определяше дали да се итерира през компонентите в дълбочина, а вторият представляваше филтър на типа. Тези параметри са отпаднали.
 
-Методът [getComponents($deep = false, $type = null |api:Nette\ComponentModel\Container::getComponents()] ) се използва за итерация. Първият параметър определя дали компонентите да се итерират в дълбочина (или рекурсивно). Ако се използва `true`, се итерират не само всички негови дъщерни компоненти, но и всички деца на неговите дъщерни компоненти и т.н. Вторият параметър служи за допълнителен филтър по клас или интерфейс.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Връща цялата йерархия от компоненти, включително всички вложени дъщерни компоненти, като индексиран масив. Търсенето се извършва първо в дълбочина.
 
 
 Мониторинг на предците .[#toc-monitoring-of-ancestors]
diff --git a/component-model/cs/@home.texy b/component-model/cs/@home.texy
index 28e3d11fe5..1a80e31100 100644
--- a/component-model/cs/@home.texy
+++ b/component-model/cs/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Vrací komponentu. Při pokusu o získání nedefinovaného potomka je zavolána továrna `createComponent($name)`. Metoda `createComponent($name)` zavolá v aktuální komponentě metodu `createComponent<název komponenty>` a jako parametr jí předá název komponenty. Vytvořená komponenta je poté přidána do aktuální komponenty jako její potomek. Těmto metodám říkáme továrny na komponenty a mohou je implementovat potomci třídy `Container`.
 
 
-Iterování nad potomky
----------------------
+getComponents(): array .[method]
+--------------------------------
+Vrací přímé potomky jako pole. Klíče obsahují názvy těchto komponent. Poznámka: ve verzi 3.0.x metoda namísto pole vracela iterátor a její první parametr určoval, zda se mají komponenty procházet do hloubky, a druhý představoval typový filtr. Tyto parametry jsou deprecated.
 
-K iterování slouží metoda [getComponents($deep = false, $type = null)|api:Nette\ComponentModel\Container::getComponents()]. První parametr určuje, zda se mají komponenty procházet do hloubky (neboli rekurzivně). S hodnotou `true` tedy nejen projde všechny komponenty, jichž je rodičem, ale také potomky svých potomků atd. Druhý parametr slouží jako volitelný filtr podle tříd nebo rozhraní.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Získá celou hierarchii komponent včetně všech vnořených podřízených komponent jako indexované pole. Prohledávání jde nejprve do hloubky.
 
 
 Monitorování předků
diff --git a/component-model/de/@home.texy b/component-model/de/@home.texy
index 55372b2be6..01bbd76959 100644
--- a/component-model/de/@home.texy
+++ b/component-model/de/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Gibt eine Komponente zurück. Der Versuch, ein undefiniertes Kind aufzurufen, führt zum Aufruf der Fabrik [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Die Methode `createComponent($name)` ruft die Methode `createComponent<component name>` in der aktuellen Komponente auf und übergibt den Namen der Komponente als Parameter. Die erstellte Komponente wird dann an die aktuelle Komponente als ihr Kind übergeben. Wir nennen diese Komponentenfabriken, sie können in von `Container` geerbten Klassen implementiert werden.
 
 
-Iteration über Kinder .[#toc-iterating-over-children]
------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Gibt direkte Nachkommen als Array zurück. Die Schlüssel enthalten die Namen dieser Komponenten. Hinweis: In Version 3.0.x gab die Methode einen Iterator statt eines Arrays zurück. Der erste Parameter gab an, ob durch die Komponenten in der Tiefe iteriert werden sollte, und der zweite Parameter stellte einen Typfilter dar. Diese Parameter sind veraltet.
 
-Die Methode [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] wird zur Iteration verwendet. Der erste Parameter gibt an, ob die Komponenten in der Tiefe (oder rekursiv) durchlaufen werden sollen. Bei `true` werden nicht nur alle untergeordneten Komponenten durchlaufen, sondern auch alle untergeordneten Komponenten der untergeordneten Komponenten, usw. Der zweite Parameter dient als optionaler Filter nach Klasse oder Schnittstelle.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Gibt die gesamte Hierarchie der Komponenten, einschließlich aller verschachtelten untergeordneten Komponenten, als indiziertes Array zurück. Die Suche geht zunächst in die Tiefe.
 
 
 Überwachung der Vorfahren .[#toc-monitoring-of-ancestors]
diff --git a/component-model/el/@home.texy b/component-model/el/@home.texy
index d26b6d5527..7a347e617f 100644
--- a/component-model/el/@home.texy
+++ b/component-model/el/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Επιστρέφει ένα συστατικό. Η απόπειρα κλήσης απροσδιόριστου παιδιού προκαλεί κλήση του εργοστασίου [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Η μέθοδος `createComponent($name)` καλεί τη μέθοδο `createComponent<component name>` στο τρέχον συστατικό και περνά το όνομα του συστατικού ως παράμετρο. Το συστατικό που δημιουργήθηκε περνάει στη συνέχεια στο τρέχον συστατικό ως παιδί του. Ονομάζουμε αυτά τα εργοστάσια συστατικών, μπορούν να υλοποιηθούν σε κλάσεις που κληρονομούνται από το `Container`.
 
 
-Επανάληψη σε παιδιά .[#toc-iterating-over-children]
----------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Επιστρέφει τους άμεσους απογόνους ως πίνακα. Τα κλειδιά περιέχουν τα ονόματα αυτών των στοιχείων. Σημείωση: στην έκδοση 3.0.x, η μέθοδος επέστρεφε έναν επαναλήπτη αντί για έναν πίνακα, και η πρώτη παράμετρος όριζε αν θα επαναλαμβάνονταν τα συστατικά σε βάθος και η δεύτερη αντιπροσώπευε ένα φίλτρο τύπου. Αυτές οι παράμετροι έχουν καταργηθεί.
 
-Η μέθοδος [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] χρησιμοποιείται για την επανάληψη. Η πρώτη παράμετρος καθορίζει αν θα διατρέξει τα συστατικά σε βάθος (ή αναδρομικά). Με την `true`, δεν επαναλαμβάνει μόνο όλα τα παιδιά της, αλλά και όλα τα παιδιά των παιδιών της, κ.λπ. Η δεύτερη παράμετρος εξυπηρετεί ως προαιρετικό φίλτρο ανά κλάση ή διεπαφή.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Επιστρέφει ολόκληρη την ιεραρχία των στοιχείων, συμπεριλαμβανομένων όλων των φωλιασμένων θυγατρικών στοιχείων ως πίνακα με ευρετήριο. Η αναζήτηση γίνεται πρώτα σε βάθος.
 
 
 Παρακολούθηση των προγόνων .[#toc-monitoring-of-ancestors]
diff --git a/component-model/en/@home.texy b/component-model/en/@home.texy
index 3ae5c4a808..1fa81fe327 100644
--- a/component-model/en/@home.texy
+++ b/component-model/en/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Returns a component. Attempt to call undefined child causes invoking of factory [createComponent($name)|api:Nette\ComponentModel\Container::createComponent()]. Method `createComponent($name)` invokes method `createComponent<component name>` in current component and it passes name of the component as a parameter. Created component is then passed to current component as its child. We call theese component factories, they can be implemented in classes inherited from `Container`.
 
 
-Iterating over Children
------------------------
+getComponents(): array .[method]
+--------------------------------
+Returns direct descendants as an array. The keys contain the names of these components. Note: in version 3.0.x, the method returned an iterator instead of an array, and its first parameter specified whether to iterate through the components in depth, and the second represented a type filter. These parameters are deprecated.
 
-The [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] method is used for iteration. The first parameter specifies whether to traverse the components in depth (or recursively). With `true`, it not only iterates all its children, but also all children of its children, etc. Second parameter serves as an optional filter by class or interface.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Returns the entire hierarchy of components, including all nested child components as indexed array. The search goes in depth first.
 
 
 Monitoring of Ancestors
diff --git a/component-model/es/@home.texy b/component-model/es/@home.texy
index 8e315b6f16..1c66c6b1ee 100644
--- a/component-model/es/@home.texy
+++ b/component-model/es/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Devuelve un componente. El intento de llamar a un hijo no definido provoca la invocación de la fábrica [createComponent($nombre) |api:Nette\ComponentModel\Container::createComponent()]. El método `createComponent($name)` invoca el método `createComponent<component name>` en el componente actual y pasa el nombre del componente como parámetro. El componente creado se pasa al componente actual como hijo. Llamamos a estas fábricas de componentes, pueden ser implementadas en clases heredadas de `Container`.
 
 
-Iterando sobre hijos .[#toc-iterating-over-children]
-----------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Devuelve los descendientes directos como una matriz. Las claves contienen los nombres de estos componentes. Nota: en la versión 3.0.x, el método devolvía un iterador en lugar de un array, y su primer parámetro especificaba si iterar a través de los componentes en profundidad, y el segundo representaba un filtro de tipo. Estos parámetros están obsoletos.
 
-El método [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] se utiliza para la iteración. El primer parámetro especifica si se recorren los componentes en profundidad (o recursivamente). Con `true`, no sólo itera todos sus hijos, sino también todos los hijos de sus hijos, etc. El segundo parámetro sirve como filtro opcional por clase o interfaz.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Devuelve toda la jerarquía de componentes, incluidos todos los componentes hijos anidados como matriz indexada. La búsqueda va primero en profundidad.
 
 
 Supervisión de antepasados .[#toc-monitoring-of-ancestors]
diff --git a/component-model/fr/@home.texy b/component-model/fr/@home.texy
index 2b03e9e9cb..7cd636b62a 100644
--- a/component-model/fr/@home.texy
+++ b/component-model/fr/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Renvoie un composant. La tentative d'appeler un enfant non défini entraîne l'invocation de la fabrique [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. La méthode `createComponent($name)` invoque la méthode `createComponent<component name>` dans le composant courant et passe le nom du composant comme paramètre. Le composant créé est ensuite transmis au composant courant en tant que son enfant. Nous appelons ces usines de composants, elles peuvent être implémentées dans des classes héritées de `Container`.
 
 
-Itération sur les enfants .[#toc-iterating-over-children]
----------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Renvoie les descendants directs sous la forme d'un tableau. Les clés contiennent les noms de ces composants. Note : dans la version 3.0.x, la méthode renvoyait un itérateur au lieu d'un tableau, et son premier paramètre spécifiait s'il fallait itérer à travers les composants en profondeur, et le second représentait un filtre de type. Ces paramètres sont obsolètes.
 
-La méthode [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] est utilisée pour l'itération. Le premier paramètre indique s'il faut parcourir les composants en profondeur (ou de manière récursive). Avec `true`, l'itération porte non seulement sur tous ses enfants, mais aussi sur tous les enfants de ses enfants, etc. Le deuxième paramètre sert de filtre optionnel par classe ou interface.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Renvoie toute la hiérarchie des composants, y compris tous les composants enfants imbriqués, sous la forme d'un tableau indexé. La recherche se fait d'abord en profondeur.
 
 
 Surveillance des ancêtres .[#toc-monitoring-of-ancestors]
diff --git a/component-model/hu/@home.texy b/component-model/hu/@home.texy
index 6614800ff1..3ece462081 100644
--- a/component-model/hu/@home.texy
+++ b/component-model/hu/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Visszaad egy komponenst. A nem definiált gyermek hívásának kísérlete a factory [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()] meghívását okozza. A `createComponent($name)` metódus meghívja a metódust `createComponent<component name>` az aktuális komponensben, és paraméterként átadja a komponens nevét. A létrehozott komponens ezután átadásra kerül az aktuális komponensnek, mint annak gyermeke. Ezeket a komponens gyáraknak nevezzük, a `Container`-tól örökölt osztályokban implementálhatók.
 
 
-Iterálás a gyermekeken .[#toc-iterating-over-children]
-------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Közvetlen leszármazottakat ad vissza tömbként. A kulcsok ezen komponensek nevét tartalmazzák. Megjegyzés: a 3.0.x verzióban a módszer tömb helyett egy iterátort adott vissza, és az első paramétere megadta, hogy a komponenseket mélységben iterálja-e, a második pedig egy típusszűrőt jelentett. Ezek a paraméterek elavultak.
 
-Az iterációhoz a [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] metódust használjuk. Az első paraméter megadja, hogy a komponensek mélységben (vagy rekurzívan) legyenek-e végigjárva. A `true` esetén nem csak az összes gyermekét iterálja, hanem a gyermekeinek összes gyermekét is, stb. A második paraméter kiszolgál, mint opcionális szűrő osztály vagy interfész szerint.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Visszaadja a komponensek teljes hierarchiáját, beleértve az összes beágyazott gyermekkomponenst indexelt tömbként. A keresés először a mélységben történik.
 
 
 Az ősök figyelése .[#toc-monitoring-of-ancestors]
diff --git a/component-model/it/@home.texy b/component-model/it/@home.texy
index aec7bd942c..32ef2a8213 100644
--- a/component-model/it/@home.texy
+++ b/component-model/it/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Restituisce un componente. Il tentativo di chiamare un figlio non definito causa l'invocazione del factory [createComponent($nome) |api:Nette\ComponentModel\Container::createComponent()]. Il metodo `createComponent($name)` invoca il metodo `createComponent<component name>` nel componente corrente e passa il nome del componente come parametro. Il componente creato viene quindi passato al componente corrente come suo figlio. Questi factory di componenti possono essere implementati in classi ereditate da `Container`.
 
 
-Iterazione sui figli .[#toc-iterating-over-children]
-----------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Restituisce i discendenti diretti come array. Le chiavi contengono i nomi dei componenti. Nota: nella versione 3.0.x, il metodo restituiva un iteratore invece di un array e il primo parametro specificava se iterare i componenti in profondità e il secondo rappresentava un filtro di tipo. Questi parametri sono deprecati.
 
-Il metodo [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] è usato per l'iterazione. Il primo parametro specifica se si deve attraversare i componenti in profondità (o in modo ricorsivo). Con `true`, non solo vengono iterati tutti i suoi figli, ma anche tutti i figli dei suoi figli, ecc. Il secondo parametro serve come filtro opzionale per classe o interfaccia.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Restituisce l'intera gerarchia di componenti, compresi tutti i componenti figli annidati, come array indicizzato. La ricerca va prima in profondità.
 
 
 Monitoraggio degli antenati .[#toc-monitoring-of-ancestors]
diff --git a/component-model/meta.json b/component-model/meta.json
index b4b89b8c38..245d650e59 100644
--- a/component-model/meta.json
+++ b/component-model/meta.json
@@ -1,5 +1,5 @@
 {
-	"version": "4.0",
+	"version": "3.x",
 	"repo": "nette/component-model",
 	"composer": "nette/component-model"
 }
diff --git a/component-model/pl/@home.texy b/component-model/pl/@home.texy
index 54dab24b99..7cb67547b1 100644
--- a/component-model/pl/@home.texy
+++ b/component-model/pl/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Zwraca element. Podczas próby uzyskania niezdefiniowanego dziecka wywoływana jest fabryka `createComponent($name)`. Metoda `createComponent($name)` wywołuje metodę w bieżącym komponencie `createComponent<název komponenty>` i przekazuje nazwę komponentu jako parametr. Utworzony komponent jest następnie dodawany do bieżącego komponentu jako jego dziecko. Metody te nazywane są fabrykami komponentów i mogą być implementowane przez potomków klasy `Container`.
 
 
-Iterowanie po potomkach .[#toc-iterovani-nad-potomky]
------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Zwraca bezpośrednich potomków jako tablicę. Klucze zawierają nazwy tych komponentów. Uwaga: w wersji 3.0.x metoda zwracała iterator zamiast tablicy, a jej pierwszy parametr określał, czy iterować przez komponenty w głąb, a drugi reprezentował filtr typu. Te parametry są przestarzałe.
 
-Do iteracji służy metoda [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()]. Pierwszy parametr określa, czy przeglądać elementy w głębi (lub rekurencyjnie). Tak więc, z wartością `true`, nie tylko przemierza wszystkie komponenty, których jest rodzicem, ale także dzieci swoich dzieci, itd. Drugi parametr służy jako opcjonalny filtr według klasy lub interfejsu.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Zwraca całą hierarchię komponentów, w tym wszystkie zagnieżdżone komponenty podrzędne, jako indeksowaną tablicę. Wyszukiwanie odbywa się najpierw w głąb.
 
 
 Monitorowanie przodków .[#toc-monitoring-of-ancestors]
diff --git a/component-model/pt/@home.texy b/component-model/pt/@home.texy
index 5782d43f3c..3aeb6d2e47 100644
--- a/component-model/pt/@home.texy
+++ b/component-model/pt/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Devolve um componente. Tentativa de chamar de criança indefinida causa invocação de fábrica [criarComponente($nome) |api:Nette\ComponentModel\Container::createComponent()]. Método `createComponent($name)` invoca método `createComponent<component name>` no componente atual e ele passa o nome do componente como parâmetro. O componente criado é então passado para o componente atual como seu filho. Chamamos essas fábricas de componentes, elas podem ser implementadas em classes herdadas de `Container`.
 
 
-Iterando sobre as crianças .[#toc-iterating-over-children]
-----------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Retorna os descendentes diretos como uma matriz. As chaves contêm os nomes desses componentes. Observação: na versão 3.0.x, o método retornava um iterador em vez de uma matriz, e seu primeiro parâmetro especificava se deveria iterar pelos componentes em profundidade, e o segundo representava um filtro de tipo. Esses parâmetros estão obsoletos.
 
-O método [getComponents($deep = falso, $type = nulo) |api:Nette\ComponentModel\Container::getComponents()] é usado para iteração. O primeiro parâmetro especifica se os componentes devem ser percorridos em profundidade (ou recursivamente). Com `true`, ele não só itera todos os seus filhos, mas também todos os filhos de seus filhos, etc. Segundo parâmetro servidores como um filtro opcional por classe ou interface.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Retorna toda a hierarquia de componentes, inclusive todos os componentes filhos aninhados, como uma matriz indexada. A pesquisa é feita primeiro em profundidade.
 
 
 Monitoramento de Ancestrais .[#toc-monitoring-of-ancestors]
diff --git a/component-model/ro/@home.texy b/component-model/ro/@home.texy
index e2f31f4fa1..c028879630 100644
--- a/component-model/ro/@home.texy
+++ b/component-model/ro/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Returnează o componentă. Încercarea de a apela un copil nedefinit determină invocarea fabricii [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Metoda `createComponent($name)` invocă metoda `createComponent<component name>` în componenta curentă și transmite numele componentei ca parametru. Componenta creată este apoi transmisă componentei curente ca fiind copilul său. Numim aceste fabrici de componente, ele pot fi implementate în clase moștenite de la `Container`.
 
 
-Iterarea peste copii .[#toc-iterating-over-children]
-----------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Returnează descendenții direcți sub formă de matrice. Cheile conțin numele acestor componente. Notă: în versiunea 3.0.x, metoda returnează un iterator în loc de un tablou, iar primul parametru specifica dacă trebuie să se parcurgă componentele în profunzime, iar al doilea reprezenta un filtru de tip. Acești parametri sunt depreciați.
 
-Metoda [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] este utilizată pentru iterație. Primul parametru specifică dacă se parcurge componentele în profunzime (sau recursiv). Cu `true`, nu numai că se iteră toți copiii săi, ci și toți copiii copiilor săi, etc. Al doilea parametru servește ca filtru opțional în funcție de clasă sau interfață.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Returnează întreaga ierarhie de componente, inclusiv toate componentele copil imbricate, sub formă de matrice indexată. Căutarea se face mai întâi în profunzime.
 
 
 Monitorizarea strămoșilor .[#toc-monitoring-of-ancestors]
diff --git a/component-model/ru/@home.texy b/component-model/ru/@home.texy
index 1e7b97e436..94c2dd3ec8 100644
--- a/component-model/ru/@home.texy
+++ b/component-model/ru/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Возвращает компонент. Попытка вызова неопределенного дочернего компонента приводит к вызову фабрики [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Метод `createComponent($name)` вызывает метод `createComponent<component name>` в текущем компоненте и передает имя компонента в качестве параметра. Созданный компонент затем передается текущему компоненту как его дочерний компонент. Мы называем эти фабрики компонентов, они могут быть реализованы в классах, унаследованных от `Container`.
 
 
-Итерация над дочерними компонентами .[#toc-iterating-over-children]
--------------------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Возвращает прямых потомков в виде массива. Ключи содержат имена этих компонентов. Примечание: в версии 3.0.x метод возвращал итератор вместо массива, а его первый параметр указывал, нужно ли выполнять глубокий итерационный просмотр компонентов, а второй представлял собой фильтр типов. Эти параметры устарели.
 
-Метод [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] используется для итерации. Первый параметр определяет, следует ли обходить компоненты в глубину (или рекурсивно). При использовании `true` итерируется не только все его дочерние компоненты, но и все дочерние компоненты его дочерних компонентов и т.д. Второй параметр служит дополнительным фильтром по классу или интерфейсу.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Возвращает всю иерархию компонентов, включая все вложенные дочерние компоненты, в виде индексированного массива. Поиск идет сначала в глубину.
 
 
 Мониторинг предков .[#toc-monitoring-of-ancestors]
diff --git a/component-model/sl/@home.texy b/component-model/sl/@home.texy
index 6577d3b5b4..56fb7db0ae 100644
--- a/component-model/sl/@home.texy
+++ b/component-model/sl/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Vrne komponento. Poskus klica nedefiniranega otroka povzroči klic tovarne [createComponent($name |api:Nette\ComponentModel\Container::createComponent()]). Metoda `createComponent($name)` prikliče metodo `createComponent<component name>` v trenutni komponenti in ji kot parameter posreduje ime komponente. Ustvarjena komponenta se nato posreduje trenutni komponenti kot njen otrok. Te tovarne komponent imenujemo tovarne komponent, ki jih lahko implementiramo v razredih, podedovanih iz `Container`.
 
 
-Iteriranje nad otroki .[#toc-iterating-over-children]
------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Vrne neposredne potomce kot polje. Ključi vsebujejo imena teh komponent. Opomba: v različici 3.0.x je metoda namesto polja vrnila iterator, njen prvi parameter pa je določal, ali naj se komponente iterira po globini, drugi pa je predstavljal filter tipa. Ta parametra sta zastarela.
 
-Metoda [getComponents($deep = false, $type = null |api:Nette\ComponentModel\Container::getComponents()] ) se uporablja za iteracijo. Prvi parameter določa, ali naj se komponente preletijo po globini (ali rekurzivno). Pri `true` se ne iterira le po vseh njegovih otrocih, temveč tudi po vseh otrocih njegovih otrok itd. Drugi parameter služi kot izbirni filter po razredu ali vmesniku.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Vrne celotno hierarhijo komponent, vključno z vsemi ugnezdenimi podrejenimi komponentami, kot indeksirano polje. Iskanje gre najprej v globino.
 
 
 Spremljanje prednikov .[#toc-monitoring-of-ancestors]
diff --git a/component-model/tr/@home.texy b/component-model/tr/@home.texy
index 799cbbd8e9..c8bfafb8d7 100644
--- a/component-model/tr/@home.texy
+++ b/component-model/tr/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Bir bileşen döndürür. Tanımsız alt öğeyi çağırma girişimi, [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()] fabrikasının çağrılmasına neden olur. Yöntem `createComponent($name)` yöntemi çağırır `createComponent<component name>` ve bileşenin adını bir parametre olarak geçirir. Oluşturulan bileşen daha sonra mevcut bileşene çocuğu olarak aktarılır. Bunlara bileşen fabrikaları diyoruz, `Container` adresinden miras alınan sınıflarda uygulanabilirler.
 
 
-Çocuklar üzerinde yineleme .[#toc-iterating-over-children]
-----------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Doğrudan torunları bir dizi olarak döndürür. Anahtarlar bu bileşenlerin adlarını içerir. Not: 3.0.x sürümünde, yöntem bir dizi yerine bir yineleyici döndürüyordu ve ilk parametresi bileşenler arasında derinlemesine yineleme yapılıp yapılmayacağını belirtiyordu, ikincisi ise bir tür filtresini temsil ediyordu. Bu parametreler kullanımdan kaldırılmıştır.
 
-[getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] yöntemi yineleme için kullanılır. İlk parametre, bileşenlerin derinlemesine (veya özyinelemeli olarak) dolaşılıp dolaşılmayacağını belirtir. `true` ile, yalnızca tüm çocuklarını değil, aynı zamanda çocuklarının tüm çocuklarını vb. yineler. İkinci parametre, sınıf veya arayüze göre isteğe bağlı bir filtre olarak sunucular.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+İç içe geçmiş tüm alt bileşenler de dahil olmak üzere tüm bileşen hiyerarşisini dizinlenmiş dizi olarak döndürür. Arama önce derinlemesine yapılır.
 
 
 Ataların İzlenmesi .[#toc-monitoring-of-ancestors]
diff --git a/component-model/uk/@home.texy b/component-model/uk/@home.texy
index 0a5621f301..4d69dd5ba6 100644
--- a/component-model/uk/@home.texy
+++ b/component-model/uk/@home.texy
@@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method]
 Повертає компонент. Спроба викликати невизначений дочірній компонент призводить до виклику фабричного [createComponent($name |api:Nette\ComponentModel\Container::createComponent()]). Метод `createComponent($name)` викликає метод `createComponent<component name>` в поточному компоненті і передає йому ім'я компонента як параметр. Створений компонент потім передається поточному компоненту як його дочірній компонент. Ми називаємо ці фабрики компонентів фабриками, вони можуть бути реалізовані в класах, успадкованих від `Container`.
 
 
-Ітерація над дочірніми компонентами .[#toc-iterating-over-children]
--------------------------------------------------------------------
+getComponents(): array .[method]
+--------------------------------
+Повертає прямих нащадків у вигляді масиву. Ключі містять імена цих компонентів. Примітка: у версії 3.0.x метод повертав ітератор замість масиву, і його перший параметр вказував, чи потрібно перебирати компоненти вглиб, а другий представляв собою фільтр типу. Ці параметри застаріли.
 
-Для ітерації використовується метод [getComponents($deep = false, $type = null |api:Nette\ComponentModel\Container::getComponents()] ). Перший параметр вказує, чи потрібно обходити компоненти вглиб (або рекурсивно). У випадку з `true` ітерація відбувається не лише по всіх дочірніх компонентах, але й по всіх дочірніх компонентах і т.д. Другий параметр слугує додатковим фільтром за класом або інтерфейсом.
 
-```php
-foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) {
-	if (!$control->getRules()->validate()) {
-		// ...
-	}
-}
-```
+getComponentTree(): array .[method]{data-version:3.1.0}
+-------------------------------------------------------
+Повертає всю ієрархію компонентів, включаючи всі вкладені дочірні компоненти у вигляді індексованого масиву. Спочатку пошук йде вглиб.
 
 
 Моніторинг предків .[#toc-monitoring-of-ancestors]
diff --git a/database/bg/configuration.texy b/database/bg/configuration.texy
index c52899ea11..ea28bef4cb 100644
--- a/database/bg/configuration.texy
+++ b/database/bg/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:         # (string)
 
 		# само за MySQL: set SET NAMES
-		charset:         # (string) по подразбиране е 'utf8mb4' ('utf8' преди v5.5.3)
+		charset:         # (string) по подразбиране е 'utf8mb4'
+
+		# само за MySQL: преобразува TINYINT(1) в bool
+		convertBoolean: # (bool) по подразбиране е false
+
+		# връща колони с дати като неизменни обекти (от версия 3.2.1)
+		newDateTime:  # (bool) по подразбиране е false
 
 		# само за Oracle и SQLite: formatDate
 		formatDateTime:  # (string) по подразбиране е 'U'
diff --git a/database/bg/core.texy b/database/bg/core.texy
index 3f1ed5af5c..c65427e121 100644
--- a/database/bg/core.texy
+++ b/database/bg/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Както можете да видите, методът `transaction()` връща стойността на обратната връзка.
 
 Функцията Transaction() също може да бъде вложена, което опростява прилагането на независими хранилища.
+
+
+Отражение .[#toc-reflection]
+============================
+
+Nette Database предоставя инструменти за интроспекция на структурата на базата данни чрез класа [api:Nette\Database\Reflection]. Този клас ви позволява да извличате информация за таблици, колони, индекси и външни ключове. Можете да използвате отразяването, за да генерирате схеми, да създавате гъвкави приложения, които работят с бази данни, или да изграждате общи инструменти за бази данни.
+
+Можете да получите обект за отразяване от инстанция за връзка с база данни:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Работа с таблици .[#toc-working-with-tables]
+--------------------------------------------
+
+С помощта на отразяването можете да правите итерации по всички таблици в базата данни:
+
+```php
+// Избройте имената на всички таблици
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Проверете дали дадена таблица съществува
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Извличане на определена таблица
+$table = $reflection->getTable('users');
+```
+
+
+Информация за колоната .[#toc-column-information]
+-------------------------------------------------
+
+За всяка таблица можете да получите подробна информация за нейните колони:
+
+```php
+// Итерация над всички колони
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Извличане на конкретна колона
+$idColumn = $table->getColumn('id');
+```
+
+
+Индекси и първични ключове .[#toc-indexes-and-primary-keys]
+-----------------------------------------------------------
+
+Отражението предоставя информация за индексите и първичните ключове:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Списък на всички индекси
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Извличане на първичния ключ
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Чужди ключове .[#toc-foreign-keys]
+----------------------------------
+
+Можете също така да получите информация за чуждите ключове:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/bg/explorer.texy b/database/bg/explorer.texy
index 28fc39699a..c19b98d0e6 100644
--- a/database/bg/explorer.texy
+++ b/database/bg/explorer.texy
@@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))
 | `$table->group($columns)` | set GROUP BY
 | `$table->having($having)` | set HAVING
 
-Можете да използвате Fluent, например `$table->where(...)->order(...)->limit(...)`. Няколко условия `where` или `whereOr` се свързват с помощта на оператора `AND`.
+Можем да използваме т.нар. [флуентен интерфейс |nette:introduction-to-object-oriented-programming#fluent-interfaces], например `$table->where(...)->order(...)->limit(...)`. Няколко условия `where` или `whereOr` се свързват чрез оператора `AND`.
 
 
 където() .[#toc-where]
@@ -338,7 +338,7 @@ Database Explorer е интелигентен и ще премахне пара
 | `$row = $table->get($id)` | извличане на един низ с id $id от таблица
 | `$row = $table->fetch()` | извличане на следващия низ от резултата
 | `$array = $table->fetchPairs($key, $value)` | Изберете всички стойности като асоциативен масив
-| `$array = $table->fetchPairs($key)` | получаване на всички записи в асоциативен масив
+| `$array = $table->fetchPairs($value)` | получаване на всички записи в асоциативен масив
 | `count($table)` | Получаване на броя на низовете в набора от резултати
 
 
diff --git a/database/cs/@left-menu.texy b/database/cs/@left-menu.texy
index 039cedfdf8..56600faa08 100644
--- a/database/cs/@left-menu.texy
+++ b/database/cs/@left-menu.texy
@@ -3,3 +3,4 @@ Databáze
 - [Core]
 - [Explorer]
 - [Konfigurace |configuration]
+- [Upgrade |upgrading]
diff --git a/database/cs/configuration.texy b/database/cs/configuration.texy
index d412ba565a..021ee3cd11 100644
--- a/database/cs/configuration.texy
+++ b/database/cs/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# pouze MySQL: nastaví SET NAMES
-		charset:      # (string) výchozí je 'utf8mb4' ('utf8' před verzí 5.5.3)
+		charset:      # (string) výchozí je 'utf8mb4'
+
+		# pouze MySQL: převádí TINYINT(1) na bool
+		convertBoolean:  # (bool) výchozí je false
+
+		# vrací sloupce s datem jako immutable objekty (od verze 3.2.1)
+		newDateTime:  # (bool) výchozí je false
 
 		# pouze Oracle a SQLite: formát pro ukládání data
 		formatDateTime: # (string) výchozí je 'U'
diff --git a/database/cs/core.texy b/database/cs/core.texy
index 02c3104e43..23623a760c 100644
--- a/database/cs/core.texy
+++ b/database/cs/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Jak vidíte, metoda `transaction()` vrací návratovou hodnotu callbacku.
 
 Volání `transaction()` může být i zanořeno, což zjednodušuje implementaci nezávislých repozitářů.
+
+
+Reflexe .{data-version:3.2.1}
+=============================
+
+Nette Database poskytuje nástroje pro introspekci databázové struktury pomocí třídy [api:Nette\Database\Reflection]. Ta umožňuje získávat informace o tabulkách, sloupcích, indexech a cizích klíčích. Reflexi můžete využít ke generování schémat, vytváření flexibilních aplikací pracujících s databází nebo obecných databázových nástrojů.
+
+Objekt reflexe získáme z instance připojení k databázi:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Práce s tabulkami
+-----------------
+
+Pomocí reflexe můžeme procházet všechny tabulky v databázi:
+
+```php
+// Výpis názvů všech tabulek
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Ověření existence tabulky
+if ($reflection->hasTable('users')) {
+    echo "Tabulka users existuje";
+}
+
+// Získání konkrétní tabulky
+$table = $reflection->getTable('users');
+```
+
+
+Informace o sloupcích
+---------------------
+
+Pro každou tabulku můžeme získat detailní informace o jejích sloupcích:
+
+```php
+// Procházení všech sloupců
+foreach ($table->columns as $column) {
+    echo "Sloupec: " . $column->name . "\n";
+    echo "Typ: " . $column->nativeType . "\n";
+    echo "Může být NULL: " . ($column->nullable ? 'Ano' : 'Ne') . "\n";
+    echo "Výchozí hodnota: " . ($column->default ?? 'Není') . "\n";
+    echo "Je primární klíč: " . ($column->primary ? 'Ano' : 'Ne') . "\n";
+    echo "Je auto-increment: " . ($column->autoIncrement ? 'Ano' : 'Ne') . "\n";
+}
+
+// Získání konkrétního sloupce
+$idColumn = $table->getColumn('id');
+```
+
+
+Indexy a primární klíče
+-----------------------
+
+Reflection poskytuje informace o indexech a primárních klíčích:
+
+```php
+$vypisNazvySloupcu = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Výpis všech indexů
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Nepojmenovaný') . "\n";
+    echo "Sloupce: " . $vypisNazvySloupcu($index->columns) . "\n";
+    echo "Je unikátní: " . ($index->unique ? 'Ano' : 'Ne') . "\n";
+    echo "Je primární klíč: " . ($index->primary ? 'Ano' : 'Ne') . "\n";
+}
+
+// Získání primárního klíče
+if ($table->primaryKey) {
+    echo "Primární klíč: " . $vypisNazvySloupcu($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Cizí klíče
+----------
+
+Můžeme také získat informace o cizích klíčích:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Cizí klíč: " . ($fk->name ?? 'Nepojmenovaný') . "\n";
+    echo "Lokální sloupce: " . $vypisNazvySloupcu($fk->localColumns) . "\n";
+    echo "Odkazuje na tabulku: {$fk->foreignTable->name}\n";
+    echo "Odkazuje na sloupce: " . $vypisNazvySloupcu($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/cs/explorer.texy b/database/cs/explorer.texy
index 1ed2cf95a5..d1f397fd5a 100644
--- a/database/cs/explorer.texy
+++ b/database/cs/explorer.texy
@@ -92,7 +92,7 @@ Podívejme se na možnosti filtrování a omezování výběru pomocí třídy [
 | `$table->group($columns)` | Nastaví GROUP BY
 | `$table->having($having)` | Nastaví HAVING
 
-Můžeme použít tzv. fluent interface, například `$table->where(...)->order(...)->limit(...)`.  Vícenásobné `where` nebo `whereOr` podmínky je spojeny operátorem `AND`.
+Můžeme použít tzv. [fluent interface|nette:introduction-to-object-oriented-programming#fluent-interfaces], například `$table->where(...)->order(...)->limit(...)`.  Vícenásobné `where` nebo `whereOr` podmínky je spojeny operátorem `AND`.
 
 
 where()
@@ -338,7 +338,8 @@ Database Explorer umí chytře escapovat parametry a identifikátory. Pro správ
 | `$row = $table->get($id)` | Vrátí jeden řádek s ID $id
 | `$row = $table->fetch()` | Vrátí další řádek výsledku
 | `$array = $table->fetchPairs($key, $value)` | Vrátí všechny výsledky jako asociativní pole
-| `$array = $table->fetchPairs($key)` | Vrátí všechny řádky jako asociativní pole
+| `$array = $table->fetchPairs($value)` | Vrátí všechny řádky jako asociativní pole
+| `$array = $table->fetchPairs($callable)` | Callback vrací `[$value]` nebo `[$key, $value]`
 | `count($table)` | Vrátí počet řádků výsledku
 
 
diff --git a/database/cs/upgrading.texy b/database/cs/upgrading.texy
new file mode 100644
index 0000000000..20bb26d94d
--- /dev/null
+++ b/database/cs/upgrading.texy
@@ -0,0 +1,14 @@
+Upgrade
+*******
+
+
+Přechod z verze 3.1 na 3.2
+==========================
+
+Minimální požadovaná verze PHP je 8.1.
+
+Kód byl pečlivě vyladěn pro PHP 8.1. Byly doplněny všechny nové typehinty u metod a properties. Změny jsou jen drobné:
+
+- MySQL: nulové datum `0000-00-00` vrací jako `null`
+- MySQL: decimal bez desetinných míst vrací jako int místo float
+- typ `time` vrací jako DateTime s datumem `1. 1. 0001` místo aktuálního data
diff --git a/database/de/configuration.texy b/database/de/configuration.texy
index a134448e32..cf3baac899 100644
--- a/database/de/configuration.texy
+++ b/database/de/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# nur MySQL: setzt SET NAMES
-		charset:      # (string) Standardwert ist 'utf8mb4' ('utf8' vor v5.5.3)
+		charset:      # (string) Standardwert ist 'utf8mb4'
+
+		# nur MySQL: wandelt TINYINT(1) in bool um
+		convertBoolean: # (bool) standardmäßig false
+
+		# Gibt Datumsspalten als unveränderliche Objekte zurück (seit Version 3.2.1)
+		newDateTime:  # (bool) standardmäßig false
 
 		# nur Oracle und SQLite: Datumsformat
 		formatDateTime: # (string) Standardwert ist 'U'
diff --git a/database/de/core.texy b/database/de/core.texy
index 75b7f21349..ae71c85c57 100644
--- a/database/de/core.texy
+++ b/database/de/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Wie Sie sehen können, gibt die Methode `transaction()` den Rückgabewert des Callbacks zurück.
 
 Die Transaktion() kann auch verschachtelt werden, was die Implementierung unabhängiger Repositories vereinfacht.
+
+
+Reflexion .[#toc-reflection]
+============================
+
+Nette Database bietet mit der Klasse [api:Nette\Database\Reflection] Werkzeuge für die Introspektion der Datenbankstruktur. Mit dieser Klasse können Sie Informationen über Tabellen, Spalten, Indizes und Fremdschlüssel abrufen. Sie können Reflection verwenden, um Schemata zu generieren, flexible Anwendungen zu erstellen, die mit Datenbanken arbeiten, oder allgemeine Datenbank-Tools zu entwickeln.
+
+Sie können ein Reflection-Objekt von einer Datenbankverbindungsinstanz abrufen:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Arbeiten mit Tabellen .[#toc-working-with-tables]
+-------------------------------------------------
+
+Mit Hilfe von Reflection können Sie über alle Tabellen in der Datenbank iterieren:
+
+```php
+// Auflisten der Namen aller Tabellen
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Prüfen, ob eine Tabelle existiert
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Abrufen einer bestimmten Tabelle
+$table = $reflection->getTable('users');
+```
+
+
+Informationen zur Säule .[#toc-column-information]
+--------------------------------------------------
+
+Für jede Tabelle können Sie detaillierte Informationen über ihre Spalten erhalten:
+
+```php
+// Iterieren über alle Spalten
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Eine bestimmte Spalte abrufen
+$idColumn = $table->getColumn('id');
+```
+
+
+Indizes und Primärschlüssel .[#toc-indexes-and-primary-keys]
+------------------------------------------------------------
+
+Reflection bietet Informationen zu Indizes und Primärschlüsseln:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Alle Indizes auflisten
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Abrufen des Primärschlüssels
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Ausländische Schlüssel .[#toc-foreign-keys]
+-------------------------------------------
+
+Sie können auch Informationen über Fremdschlüssel erhalten:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/de/explorer.texy b/database/de/explorer.texy
index f1adf4fb40..10784b7089 100644
--- a/database/de/explorer.texy
+++ b/database/de/explorer.texy
@@ -92,7 +92,7 @@ Siehe Möglichkeiten zum Filtern und Einschränken von Zeilen [api:Nette\Databas
 | `$table->group($columns)` | GROUP BY einstellen
 | `$table->having($having)` | HAVING einstellen
 
-Es kann eine fließende Schnittstelle verwendet werden, z. B. `$table->where(...)->order(...)->limit(...)`. Mehrere `where` oder `whereOr` Bedingungen werden mit dem Operator `AND` verbunden.
+Wir können eine sogenannte [fließende Schnittstelle |nette:introduction-to-object-oriented-programming#fluent-interfaces] verwenden, zum Beispiel `$table->where(...)->order(...)->limit(...)`. Mehrere `where` oder `whereOr` Bedingungen werden mit dem Operator `AND` verknüpft.
 
 
 wo() .[#toc-where]
@@ -338,7 +338,7 @@ Abrufen von Daten .[#toc-fetching-data]
 | `$row = $table->get($id)` | Einzelne Zeile mit ID $id aus Tabelle holen
 | `$row = $table->fetch()` | Holt die nächste Zeile aus dem Ergebnis
 | `$array = $table->fetchPairs($key, $value)` | Holt alle Werte in ein assoziatives Array
-| `$array = $table->fetchPairs($key)` | Holt alle Zeilen in ein assoziatives Array
+| `$array = $table->fetchPairs($value)` | Holt alle Zeilen in ein assoziatives Array
 | `count($table)` | Anzahl der Zeilen in der Ergebnismenge ermitteln
 
 
diff --git a/database/el/configuration.texy b/database/el/configuration.texy
index e3f7f2992d..ff1516d944 100644
--- a/database/el/configuration.texy
+++ b/database/el/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# μόνο MySQL: ορίζει SET NAMES
-		charset:      # (string) προεπιλογή 'utf8mb4' ('utf8' πριν την έκδοση v5.5.3)
+		charset:      # (string) προεπιλογή 'utf8mb4'
+
+		# μόνο MySQL: μετατρέπει το TINYINT(1) σε bool
+		convertBoolean: # (bool) προεπιλογή σε false
+
+		# επιστρέφει τις στήλες ημερομηνίας ως αμετάβλητα αντικείμενα (από την έκδοση 3.2.1)
+		newDateTime:  # (bool) με προεπιλογή false
 
 		# μόνο Oracle και SQLite: μορφή ημερομηνίας
 		formatDateTime: # (string) προεπιλογή 'U'
diff --git a/database/el/core.texy b/database/el/core.texy
index 8087562d37..b1f0de4d02 100644
--- a/database/el/core.texy
+++ b/database/el/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Όπως μπορείτε να δείτε, η μέθοδος `transaction()` επιστρέφει την τιμή επιστροφής του callback.
 
 Η transaction() μπορεί επίσης να είναι εμφωλευμένη, γεγονός που απλοποιεί την υλοποίηση ανεξάρτητων αποθετηρίων.
+
+
+Αντανάκλαση .[#toc-reflection]
+==============================
+
+Η Nette Database παρέχει εργαλεία για την ενδοσκόπηση της δομής της βάσης δεδομένων μέσω της κλάσης [api:Nette\Database\Reflection]. Αυτή η κλάση σας επιτρέπει να ανακτάτε πληροφορίες σχετικά με πίνακες, στήλες, δείκτες και ξένα κλειδιά. Μπορείτε να χρησιμοποιήσετε την αντανάκλαση για να δημιουργήσετε σχήματα, να δημιουργήσετε ευέλικτες εφαρμογές που δουλεύουν με βάσεις δεδομένων ή να δημιουργήσετε γενικά εργαλεία βάσεων δεδομένων.
+
+Μπορείτε να λάβετε ένα αντικείμενο αντανάκλασης από μια περίπτωση σύνδεσης με βάση δεδομένων:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Εργασία με πίνακες .[#toc-working-with-tables]
+----------------------------------------------
+
+Χρησιμοποιώντας την αντανάκλαση, μπορείτε να κάνετε επανάληψη σε όλους τους πίνακες της βάσης δεδομένων:
+
+```php
+// Αναφέρετε τα ονόματα όλων των πινάκων
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Έλεγχος αν υπάρχει πίνακας
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Ανάκτηση ενός συγκεκριμένου πίνακα
+$table = $reflection->getTable('users');
+```
+
+
+Πληροφορίες στήλης .[#toc-column-information]
+---------------------------------------------
+
+Για κάθε πίνακα, μπορείτε να λάβετε λεπτομερείς πληροφορίες για τις στήλες του:
+
+```php
+// Επανάληψη σε όλες τις στήλες
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Ανάκτηση μιας συγκεκριμένης στήλης
+$idColumn = $table->getColumn('id');
+```
+
+
+Δείκτες και πρωτεύοντα κλειδιά .[#toc-indexes-and-primary-keys]
+---------------------------------------------------------------
+
+Η αντανάκλαση παρέχει πληροφορίες σχετικά με τους δείκτες και τα πρωτεύοντα κλειδιά:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Κατάλογος όλων των ευρετηρίων
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Ανάκτηση του πρωτεύοντος κλειδιού
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Ξένα κλειδιά .[#toc-foreign-keys]
+---------------------------------
+
+Μπορείτε επίσης να λάβετε πληροφορίες σχετικά με τα ξένα κλειδιά:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/el/explorer.texy b/database/el/explorer.texy
index 8b1cace70a..b0dc43b07f 100644
--- a/database/el/explorer.texy
+++ b/database/el/explorer.texy
@@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))
 | `$table->group($columns)` | Ορισμός GROUP BY
 | `$table->having($having)` | Ορισμός HAVING
 
-Μπορεί να χρησιμοποιηθεί διεπαφή Fluent, για παράδειγμα `$table->where(...)->order(...)->limit(...)`. Πολλαπλές συνθήκες `where` ή `whereOr` συνδέονται με τον τελεστή `AND`.
+Μπορούμε να χρησιμοποιήσουμε μια λεγόμενη [ρευστή διεπαφή |nette:introduction-to-object-oriented-programming#fluent-interfaces], για παράδειγμα `$table->where(...)->order(...)->limit(...)`. Πολλαπλές συνθήκες `where` ή `whereOr` συνδέονται με τον τελεστή `AND`.
 
 
 where() .[#toc-where]
@@ -338,7 +338,7 @@ $authors->where(':book:book_tags.tag.name', 'PHP')
 | `$row = $table->get($id)` | Λήψη μεμονωμένης γραμμής με αναγνωριστικό $id από τον πίνακα
 | `$row = $table->fetch()` | Λήψη της επόμενης γραμμής από το αποτέλεσμα
 | `$array = $table->fetchPairs($key, $value)` | Λήψη όλων των τιμών σε συσχετιστικό πίνακα
-| `$array = $table->fetchPairs($key)` | Λήψη όλων των γραμμών σε συσχετιστικό πίνακα
+| `$array = $table->fetchPairs($value)` | Λήψη όλων των γραμμών σε συσχετιστικό πίνακα
 | `count($table)` | Λήψη αριθμού γραμμών στο σύνολο αποτελεσμάτων
 
 
diff --git a/database/en/@left-menu.texy b/database/en/@left-menu.texy
index 3a2cf9ca88..c019745dd4 100644
--- a/database/en/@left-menu.texy
+++ b/database/en/@left-menu.texy
@@ -3,3 +3,4 @@ Database
 - [Core]
 - [Explorer]
 - [Configuration]
+- [Upgrading]
diff --git a/database/en/configuration.texy b/database/en/configuration.texy
index 130f91101b..23f06962d6 100644
--- a/database/en/configuration.texy
+++ b/database/en/configuration.texy
@@ -45,11 +45,17 @@ database:
 		# PHP database driver class
 		driverClass:  # (string)
 
-		# only MySQL: sets sql_mode
+		# MySQL only: sets sql_mode
 		sqlmode:      # (string)
 
-		# only MySQL: sets SET NAMES
-		charset:      # (string) defaults to 'utf8mb4' ('utf8' before v5.5.3)
+		# MySQL only: sets SET NAMES
+		charset:      # (string) defaults to 'utf8mb4'
+
+		# MySQL only: converts TINYINT(1) to bool
+		convertBoolean: # (bool) defaults to false
+
+		# returns date columns as immutable objects (since version 3.2.1)
+		newDateTime:  # (bool) defaults to false
 
 		# only Oracle and SQLite: date format
 		formatDateTime: # (string) defaults to 'U'
diff --git a/database/en/core.texy b/database/en/core.texy
index d950f13509..1b48ece063 100644
--- a/database/en/core.texy
+++ b/database/en/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 As you can see, the `transaction()` method returns the return value of the callback.
 
 The transaction() can also be nested, which simplifies the implementation of independent repositories.
+
+
+Reflection .{data-version:3.2.1}
+================================
+
+Nette Database provides tools for introspecting database structure through the [api:Nette\Database\Reflection] class. This class allows you to retrieve information about tables, columns, indexes, and foreign keys. You can use reflection to generate schemas, create flexible applications that work with databases, or build general database tools.
+
+You can obtain a reflection object from a database connection instance:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Working with Tables
+-------------------
+
+Using reflection, you can iterate over all tables in the database:
+
+```php
+// List the names of all tables
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Check if a table exists
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Retrieve a specific table
+$table = $reflection->getTable('users');
+```
+
+
+Column Information
+------------------
+
+For each table, you can get detailed information about its columns:
+
+```php
+// Iterate over all columns
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes' : 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes' : 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes' : 'No') . "\n";
+}
+
+// Retrieve a specific column
+$idColumn = $table->getColumn('id');
+```
+
+
+Indexes and Primary Keys
+------------------------
+
+Reflection provides information about indexes and primary keys:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// List all indexes
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes' : 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes' : 'No') . "\n";
+}
+
+// Retrieve the primary key
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Foreign Keys
+------------
+
+You can also get information about foreign keys:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/en/explorer.texy b/database/en/explorer.texy
index 77e8f5a91c..383f0f82e4 100644
--- a/database/en/explorer.texy
+++ b/database/en/explorer.texy
@@ -92,7 +92,7 @@ See possibilities how to filter and restrict rows [api:Nette\Database\Table\Sele
 | `$table->group($columns)` | Set GROUP BY
 | `$table->having($having)` | Set HAVING
 
-Fluent interface can be used, for example `$table->where(...)->order(...)->limit(...)`. Multiple `where` or `whereOr` conditions are connected with the `AND` operator.
+We can use a so-called [fluent interface |nette:introduction-to-object-oriented-programming#fluent-interfaces], for example `$table->where(...)->order(...)->limit(...)`. Multiple `where` or `whereOr` conditions are linked by the `AND` operator.
 
 
 where()
@@ -338,7 +338,7 @@ Fetching Data
 | `$row = $table->get($id)` | Get single row with ID $id from table
 | `$row = $table->fetch()` | Get next row from the result
 | `$array = $table->fetchPairs($key, $value)` | Fetch all values to associative array
-| `$array = $table->fetchPairs($key)` | Fetch all rows to associative array
+| `$array = $table->fetchPairs($value)` | Fetch all rows to associative array
 | `count($table)` | Get number of rows in result set
 
 
diff --git a/database/en/upgrading.texy b/database/en/upgrading.texy
new file mode 100644
index 0000000000..cd6a4776a9
--- /dev/null
+++ b/database/en/upgrading.texy
@@ -0,0 +1,14 @@
+Upgrading
+*********
+
+
+Migrating from 3.1 to 3.2
+=========================
+
+The minimum required PHP version is 8.1.
+
+The code has been carefully tuned for PHP 8.1. All new typehints for methods and properties have been added. The changes are minor:
+
+- MySQL: a zero date `0000-00-00` is returned as `null`
+- MySQL: a decimal without decimal places is returned as int instead of float
+- The `time` type is returned as DateTime with the date `1. 1. 0001` instead of the current date
diff --git a/database/es/configuration.texy b/database/es/configuration.texy
index e9f6cc8109..db55b6863c 100644
--- a/database/es/configuration.texy
+++ b/database/es/configuration.texy
@@ -45,13 +45,19 @@ database:
 		# PHP database driver class
 		driverClass:  # (string)
 
-		# only MySQL: sets sql_mode
+		# sólo MySQL: sets sql_mode
 		sqlmode:      # (string)
 
-		# only MySQL: sets SET NAMES
-		charset:      # (string) defaults to 'utf8mb4' ('utf8' before v5.5.3)
+		# sólo MySQL: sets SET NAMES
+		charset:      # (string) defaults to 'utf8mb4'
 
-		# only Oracle and SQLite: date format
+		# sólo MySQL: convierte TINYINT(1) a bool
+		convertBoolean: # (bool) por defecto false
+
+		# devuelve columnas de fecha como objetos inmutables (desde la versión 3.2.1)
+		newDateTime:  # (bool) por defecto false
+
+		# sólo Oracle and SQLite: date format
 		formatDateTime: # (string) defaults to 'U'
 ```
 
diff --git a/database/es/core.texy b/database/es/core.texy
index 9944ca9332..2db4eceb66 100644
--- a/database/es/core.texy
+++ b/database/es/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Como puede ver, el método `transaction()` devuelve el valor de retorno de la llamada de retorno.
 
 La transacción() también se puede anidar, lo que simplifica la implementación de repositorios independientes.
+
+
+Reflexión .[#toc-reflection]
+============================
+
+Nette Database proporciona herramientas para la introspección de la estructura de la base de datos a través de la clase [api:Nette\Database\Reflection]. Esta clase permite recuperar información sobre tablas, columnas, índices y claves externas. Puedes utilizar reflection para generar esquemas, crear aplicaciones flexibles que trabajen con bases de datos o construir herramientas generales de bases de datos.
+
+Puede obtener un objeto reflection a partir de una instancia de conexión a una base de datos:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Trabajar con tablas .[#toc-working-with-tables]
+-----------------------------------------------
+
+Usando reflection, puedes iterar sobre todas las tablas de la base de datos:
+
+```php
+// Listar los nombres de todas las tablas
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Comprobar si existe una tabla
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Recuperar una tabla específica
+$table = $reflection->getTable('users');
+```
+
+
+Información sobre columnas .[#toc-column-information]
+-----------------------------------------------------
+
+Para cada tabla, puede obtener información detallada sobre sus columnas:
+
+```php
+// Iterar sobre todas las columnas
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Recuperar una columna específica
+$idColumn = $table->getColumn('id');
+```
+
+
+Índices y claves primarias .[#toc-indexes-and-primary-keys]
+-----------------------------------------------------------
+
+Reflection proporciona información sobre índices y claves primarias:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Listar todos los índices
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Recuperar la clave primaria
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Claves extranjeras .[#toc-foreign-keys]
+---------------------------------------
+
+También puede obtener información sobre claves foráneas:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/es/explorer.texy b/database/es/explorer.texy
index 444c32521d..00adca3494 100644
--- a/database/es/explorer.texy
+++ b/database/es/explorer.texy
@@ -92,7 +92,7 @@ Ver posibilidades cómo filtrar y restringir filas [api:Nette\Database\Table\Sel
 | `$table->group($columns)` Establecer GROUP BY
 | `$table->having($having)` Establecer HAVING
 
-Se puede utilizar una interfaz fluida, por ejemplo `$table->where(...)->order(...)->limit(...)`. Las condiciones múltiples `where` o `whereOr` se conectan con el operador `AND`.
+Podemos utilizar una [interfaz fluida |nette:introduction-to-object-oriented-programming#fluent-interfaces], por ejemplo `$table->where(...)->order(...)->limit(...)`. Varias condiciones `where` o `whereOr` se enlazan mediante el operador `AND`.
 
 
 donde() .[#toc-where]
@@ -338,7 +338,7 @@ Obtención de datos .[#toc-fetching-data]
 | `$row = $table->get($id)` Obtener una fila con ID $id de la tabla
 | `$row = $table->fetch()` Obtener la siguiente fila del resultado
 | `$array = $table->fetchPairs($key, $value)` Obtener todos los valores de la matriz asociativa
-| `$array = $table->fetchPairs($key)` Obtener todas las filas de la matriz asociativa
+| `$array = $table->fetchPairs($value)` Obtener todas las filas de la matriz asociativa
 | `count($table)` Obtener el número de filas del conjunto de resultados
 
 
diff --git a/database/fr/configuration.texy b/database/fr/configuration.texy
index 8dcaa2bd84..727c33a531 100644
--- a/database/fr/configuration.texy
+++ b/database/fr/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# uniquement MySQL: sets SET NAMES
-		charset:      # (string) par défaut 'utf8mb4' ('utf8' avant v5.5.3)
+		charset:      # (string) par défaut 'utf8mb4'
+
+		# uniquement MySQL : convertit TINYINT(1) en bool
+		convertBoolean : # (bool) valeur par défaut : false
+
+		# renvoie les colonnes de date sous forme d'objets immuables (depuis la version 3.2.1)
+		newDateTime :  # (bool) valeur par défaut : false
 
 		# uniquement Oracle et SQLite: format de date
 		formatDateTime: # (string) vaut par défaut 'U'.
diff --git a/database/fr/core.texy b/database/fr/core.texy
index 2703fcc41d..cee8eb3219 100644
--- a/database/fr/core.texy
+++ b/database/fr/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Comme vous pouvez le voir, la méthode `transaction()` renvoie la valeur de retour de la callback.
 
 La transaction() peut également être imbriquée, ce qui simplifie la mise en œuvre de référentiels indépendants.
+
+
+Réflexion .[#toc-reflection]
+============================
+
+Nette Database fournit des outils d'introspection de la structure de la base de données par le biais de la classe [api:Nette\Database\Reflection]. Cette classe vous permet de récupérer des informations sur les tables, les colonnes, les index et les clés étrangères. Vous pouvez utiliser la réflexion pour générer des schémas, créer des applications flexibles qui fonctionnent avec des bases de données ou construire des outils généraux pour les bases de données.
+
+Vous pouvez obtenir un objet de réflexion à partir d'une instance de connexion à la base de données :
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Travailler avec des tableaux .[#toc-working-with-tables]
+--------------------------------------------------------
+
+En utilisant la réflexion, vous pouvez itérer sur toutes les tables de la base de données :
+
+```php
+// Liste des noms de toutes les tables
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Vérifier si une table existe
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Récupérer une table spécifique
+$table = $reflection->getTable('users');
+```
+
+
+Informations sur les colonnes .[#toc-column-information]
+--------------------------------------------------------
+
+Pour chaque table, vous pouvez obtenir des informations détaillées sur ses colonnes :
+
+```php
+// Itérer sur toutes les colonnes
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Récupérer une colonne spécifique
+$idColumn = $table->getColumn('id');
+```
+
+
+Index et clés primaires .[#toc-indexes-and-primary-keys]
+--------------------------------------------------------
+
+La réflexion fournit des informations sur les index et les clés primaires :
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Liste de tous les index
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Récupérer la clé primaire
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Clés étrangères .[#toc-foreign-keys]
+------------------------------------
+
+Vous pouvez également obtenir des informations sur les clés étrangères :
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/fr/explorer.texy b/database/fr/explorer.texy
index 7d4796d7f8..3ceb3d9bb2 100644
--- a/database/fr/explorer.texy
+++ b/database/fr/explorer.texy
@@ -92,7 +92,7 @@ Voir les possibilités de filtrer et de restreindre les lignes [api:Nette\Databa
 | `$table->group($columns)` | Définir GROUP BY
 | `$table->having($having)` | Définir HAVING
 
-Une interface fluide peut être utilisée, par exemple `$table->where(...)->order(...)->limit(...)`. Les conditions multiples de `where` ou `whereOr` sont connectées avec l'opérateur `AND`.
+Nous pouvons utiliser ce que l'on appelle une [interface fluide |nette:introduction-to-object-oriented-programming#fluent-interfaces], par exemple `$table->where(...)->order(...)->limit(...)`. Plusieurs conditions `where` ou `whereOr` sont liées par l'opérateur `AND`.
 
 
 où() .[#toc-where]
@@ -338,7 +338,7 @@ Récupération des données .[#toc-fetching-data]
 | `$row = $table->get($id)` | Récupérer une seule ligne avec l'ID $id dans le tableau.
 | `$row = $table->fetch()` | Récupérer la ligne suivante dans le résultat
 | `$array = $table->fetchPairs($key, $value)` | Récupérer toutes les valeurs dans un tableau associatif
-| `$array = $table->fetchPairs($key)` | Récupère toutes les lignes dans un tableau associatif
+| `$array = $table->fetchPairs($value)` | Récupère toutes les lignes dans un tableau associatif
 | `count($table)` | Obtenir le nombre de lignes dans le jeu de résultats
 
 
diff --git a/database/hu/configuration.texy b/database/hu/configuration.texy
index 6af7c620aa..ad28e6f1ed 100644
--- a/database/hu/configuration.texy
+++ b/database/hu/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# csak MySQL: sets SET NAMES
-		charset:      # (string) alapértelmezés szerint 'utf8mb4' ('utf8' a v5.5.3 előtt)
+		charset:      # (string) alapértelmezés szerint 'utf8mb4'
+
+		# csak MySQL: TINYINT(1) bool-ra konvertálja
+		convertBoolean: # (bool) alapértelmezett értéke false
+
+		# a dátum oszlopokat megváltoztathatatlan objektumként adja vissza (3.2.1 verzió óta)
+		newDateTime:  # (bool) alapértelmezett értéke false
 
 		# csak Oracle és SQLite: dátumformátum
 		formatDateTime: # (string) alapértelmezett értéke 'U'
diff --git a/database/hu/core.texy b/database/hu/core.texy
index 6c303bbcff..5ae0d48220 100644
--- a/database/hu/core.texy
+++ b/database/hu/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Mint látható, a `transaction()` metódus a callback visszatérési értékét adja vissza.
 
 A tranzakció() is beágyazható, ami egyszerűsíti a független tárolók megvalósítását.
+
+
+Reflection .[#toc-reflection]
+=============================
+
+A Nette Database a [api:Nette\Database\Reflection] osztályon keresztül eszközöket biztosít az adatbázis szerkezetének áttekintéséhez. Ez az osztály lehetővé teszi a táblákról, oszlopokról, indexekről és idegen kulcsokról szóló információk lekérdezését. A reflexiót használhatja sémák létrehozására, adatbázisokkal dolgozó rugalmas alkalmazások létrehozására vagy általános adatbázis-eszközök készítésére.
+
+A reflection objektumot egy adatbázis-kapcsolati példányból szerezheti meg:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Munka táblázatokkal .[#toc-working-with-tables]
+-----------------------------------------------
+
+A tükrözés segítségével az adatbázis összes tábláján végig tudsz menni:
+
+```php
+// Az összes táblázat nevének felsorolása
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Ellenőrizze, hogy létezik-e táblázat
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Egy adott táblázat lekérdezése
+$table = $reflection->getTable('users');
+```
+
+
+Oszlop információk .[#toc-column-information]
+---------------------------------------------
+
+Az egyes táblák oszlopairól részletes információkat kaphat:
+
+```php
+// Ismétlés az összes oszlopon
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Egy adott oszlop kinyerése
+$idColumn = $table->getColumn('id');
+```
+
+
+Indexek és elsődleges kulcsok .[#toc-indexes-and-primary-keys]
+--------------------------------------------------------------
+
+A Reflection az indexekről és az elsődleges kulcsokról nyújt információt:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Az összes index felsorolása
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Az elsődleges kulcs kinyerése
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Idegen kulcsok .[#toc-foreign-keys]
+-----------------------------------
+
+Az idegen kulcsokról is tájékozódhat:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/hu/explorer.texy b/database/hu/explorer.texy
index 55b2296755..cab2efd2d7 100644
--- a/database/hu/explorer.texy
+++ b/database/hu/explorer.texy
@@ -92,7 +92,7 @@ Lásd a sorok szűrésének és korlátozásának lehetőségeit [api:Nette\Data
 | `$table->group($columns)` | GROUP BY beállítása
 | `$table->having($having)` | HAVING beállítása
 
-Fluent interfész használható, például `$table->where(...)->order(...)->limit(...)`. Több `where` vagy `whereOr` feltétel a `AND` operátorral kapcsolódik.
+Használhatunk egy úgynevezett [folyékony felületet |nette:introduction-to-object-oriented-programming#fluent-interfaces], például a `$table->where(...)->order(...)->limit(...)`. Több `where` vagy `whereOr` feltételt a `AND` operátorral kapcsolunk össze.
 
 
 where() .[#toc-where]
@@ -338,7 +338,7 @@ Adatok lekérése .[#toc-fetching-data]
 | `$row = $table->get($id)` | Egyetlen sor kinyerése $id azonosítóval a táblázatból
 | `$row = $table->fetch()` | Következő sor kinyerése az eredményből.
 | `$array = $table->fetchPairs($key, $value)` | Az összes érték beemelése asszociatív tömbbe.
-| `$array = $table->fetchPairs($key)` | Minden sor lekérése asszociatív tömbbe.
+| `$array = $table->fetchPairs($value)` | Minden sor lekérése asszociatív tömbbe.
 | `count($table)` | Az eredményhalmaz sorainak számának kinyerése
 
 
diff --git a/database/it/configuration.texy b/database/it/configuration.texy
index 55e0e4ad9c..eef1be2113 100644
--- a/database/it/configuration.texy
+++ b/database/it/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# solo MySQL: imposta SET NAMES
-		charset:      # (string) predefinito a 'utf8mb4' ('utf8' prima della v5.5.3)
+		charset:      # (string) predefinito a 'utf8mb4'
+
+		# solo MySQL: converte TINYINT(1) in bool
+		convertBoolean: # (bool) predefinito a false
+
+		# restituisce le colonne di data come oggetti immutabili (dalla versione 3.2.1)
+		newDateTime:  # (bool) predefinito a false
 
 		# solo Oracle e SQLite: formato data
 		formatDateTime: # (string) predefinito a "U".
diff --git a/database/it/core.texy b/database/it/core.texy
index 562e9d941f..113a6f97a5 100644
--- a/database/it/core.texy
+++ b/database/it/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Come si può vedere, il metodo `transaction()` restituisce il valore di ritorno della callback.
 
 Il metodo transaction() può anche essere annidato, il che semplifica l'implementazione di repository indipendenti.
+
+
+Riflessione .[#toc-reflection]
+==============================
+
+Nette Database offre strumenti per l'introspezione della struttura del database attraverso la classe [api:Nette\Database\Reflection]. Questa classe consente di recuperare informazioni su tabelle, colonne, indici e chiavi esterne. È possibile utilizzare la riflessione per generare schemi, creare applicazioni flessibili che lavorano con i database o costruire strumenti generali per i database.
+
+È possibile ottenere un oggetto reflection da un'istanza di connessione al database:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Lavorare con le tabelle .[#toc-working-with-tables]
+---------------------------------------------------
+
+Utilizzando la riflessione, è possibile iterare su tutte le tabelle del database:
+
+```php
+// Elencare i nomi di tutte le tabelle
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Controllare se una tabella esiste
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Recuperare una tabella specifica
+$table = $reflection->getTable('users');
+```
+
+
+Informazioni sulla colonna .[#toc-column-information]
+-----------------------------------------------------
+
+Per ogni tabella è possibile ottenere informazioni dettagliate sulle sue colonne:
+
+```php
+// Iterare su tutte le colonne
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Recuperare una colonna specifica
+$idColumn = $table->getColumn('id');
+```
+
+
+Indici e chiavi primarie .[#toc-indexes-and-primary-keys]
+---------------------------------------------------------
+
+La riflessione fornisce informazioni su indici e chiavi primarie:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Elencare tutti gli indici
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Recuperare la chiave primaria
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Chiavi straniere .[#toc-foreign-keys]
+-------------------------------------
+
+È inoltre possibile ottenere informazioni sulle chiavi esterne:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/it/explorer.texy b/database/it/explorer.texy
index c462381ac0..431a45ae78 100644
--- a/database/it/explorer.texy
+++ b/database/it/explorer.texy
@@ -92,7 +92,7 @@ Vedere le possibilità di filtrare e limitare le righe [api:Nette\Database\Table
 | `$table->group($columns)` | Impostare GROUP BY
 | `$table->having($having)` | Imposta HAVING
 
-È possibile utilizzare l'interfaccia Fluent, ad esempio `$table->where(...)->order(...)->limit(...)`. Le condizioni multiple `where` o `whereOr` sono collegate con l'operatore `AND`.
+Possiamo utilizzare una cosiddetta [interfaccia fluente |nette:introduction-to-object-oriented-programming#fluent-interfaces], ad esempio `$table->where(...)->order(...)->limit(...)`. Più condizioni `where` o `whereOr` sono collegate dall'operatore `AND`.
 
 
 dove() .[#toc-where]
@@ -338,7 +338,7 @@ Recuperare i dati .[#toc-fetching-data]
 | `$row = $table->get($id)` | Ottenere una singola riga con ID $id dalla tabella
 | `$row = $table->fetch()` | Ottenere la riga successiva dal risultato
 | `$array = $table->fetchPairs($key, $value)` | Recuperare tutti i valori in un array associativo
-| `$array = $table->fetchPairs($key)` | Recupera tutte le righe nell'array associativo
+| `$array = $table->fetchPairs($value)` | Recupera tutte le righe nell'array associativo
 | `count($table)` | Ottenere il numero di righe nell'insieme dei risultati
 
 
diff --git a/database/pl/configuration.texy b/database/pl/configuration.texy
index 9dfe2cf200..f75ca3e36d 100644
--- a/database/pl/configuration.texy
+++ b/database/pl/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# Tylko MySQL: ustawia SET NAMES
-		charset:      # (string) default is 'utf8mb4' ('utf8' before 5.5.3)
+		charset:      # (string) default is 'utf8mb4'
+
+		# Tylko MySQL: konwertuje TINYINT(1) na bool
+		convertBoolean: # (bool) domyślnie false
+
+		# zwraca kolumny daty jako niezmienne obiekty (od wersji 3.2.1)
+		newDateTime:  # (bool) domyślnie false
 
 		# Tylko Oracle i SQLite: format przechowywania danych
 		formatDateTime: # (string) domyślnie 'U'
diff --git a/database/pl/core.texy b/database/pl/core.texy
index 706713ee75..b6caa291a0 100644
--- a/database/pl/core.texy
+++ b/database/pl/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Jak widać, metoda `transaction()` zwraca wartość zwrotną wywołania zwrotnego.
 
 Callback `transaction()` może być również zagnieżdżony, co upraszcza implementację niezależnych repozytoriów.
+
+
+Refleksja .[#toc-reflection]
+============================
+
+Nette Database zapewnia narzędzia do introspekcji struktury bazy danych poprzez klasę [api:Nette\Database\Reflection]. Klasa ta umożliwia pobieranie informacji o tabelach, kolumnach, indeksach i kluczach obcych. Refleksji można używać do generowania schematów, tworzenia elastycznych aplikacji współpracujących z bazami danych lub tworzenia ogólnych narzędzi bazodanowych.
+
+Obiekt refleksji można uzyskać z instancji połączenia z bazą danych:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Praca z tabelami .[#toc-working-with-tables]
+--------------------------------------------
+
+Używając refleksji, można iterować po wszystkich tabelach w bazie danych:
+
+```php
+// Lista nazw wszystkich tabel
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Sprawdzenie, czy tabela istnieje
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Pobieranie określonej tabeli
+$table = $reflection->getTable('users');
+```
+
+
+Informacje o kolumnie .[#toc-column-information]
+------------------------------------------------
+
+Dla każdej tabeli można uzyskać szczegółowe informacje o jej kolumnach:
+
+```php
+// Iteracja po wszystkich kolumnach
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Pobieranie określonej kolumny
+$idColumn = $table->getColumn('id');
+```
+
+
+Indeksy i klucze podstawowe .[#toc-indexes-and-primary-keys]
+------------------------------------------------------------
+
+Refleksja dostarcza informacji na temat indeksów i kluczy głównych:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Lista wszystkich indeksów
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Pobieranie klucza głównego
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Klucze obce .[#toc-foreign-keys]
+--------------------------------
+
+Można również uzyskać informacje na temat kluczy obcych:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/pl/explorer.texy b/database/pl/explorer.texy
index e479bb49aa..e3295102d7 100644
--- a/database/pl/explorer.texy
+++ b/database/pl/explorer.texy
@@ -92,7 +92,7 @@ Przyjrzyjmy się opcjom filtrowania i ograniczania selekcji przy użyciu klasy [
 | `$table->group($columns)` | Set GROUP BY
 | `$table->having($having)` | Set HAVING
 
-Możemy użyć tzw. interfejsu fluent, na przykład `$table->where(...)->order(...)->limit(...)`. Wiele warunków `where` lub `whereOr` łączy się za pomocą operatora `AND`.
+Możemy użyć tak zwanego [płynnego interfejsu |nette:introduction-to-object-oriented-programming#fluent-interfaces], na przykład `$table->where(...)->order(...)->limit(...)`. Wiele warunków `where` lub `whereOr` jest połączonych operatorem `AND`.
 
 
 gdzie() .[#toc-where]
@@ -338,7 +338,7 @@ Dane do odczytu .[#toc-fetching-data]
 | `$row = $table->get($id)` | Zwraca jeden wiersz o ID $id
 | `$row = $table->fetch()` | Zwraca następny wiersz wyniku.
 | `$array = $table->fetchPairs($key, $value)` | Zwraca wszystkie wyniki jako tablicę asocjacyjną
-| `$array = $table->fetchPairs($key)` | Zwraca wszystkie wiersze jako tablicę asocjacyjną
+| `$array = $table->fetchPairs($value)` | Zwraca wszystkie wiersze jako tablicę asocjacyjną
 | `count($table)` | Zwraca liczbę wierszy w wyniku.
 
 
diff --git a/database/pt/configuration.texy b/database/pt/configuration.texy
index 08bead4f03..4ed03b56c0 100644
--- a/database/pt/configuration.texy
+++ b/database/pt/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# somente MySQL: define o SET NAMES
-		charset:      # (string) padrão para 'utf8mb4' ('utf8' antes da v5.5.3)
+		charset:      # (string) padrão para 'utf8mb4'
+
+		# somente MySQL: converte TINYINT(1) em bool
+		convertBoolean: # (bool) tem como padrão false
+
+		# retorna colunas de data como objetos imutáveis (desde a versão 3.2.1)
+		newDateTime:  # (bool) tem como padrão false
 
 		# somente Oracle e SQLite: formato de data
 		formatDateTime: # (string) padrão para 'U'
diff --git a/database/pt/core.texy b/database/pt/core.texy
index a3a5df1e0a..d4f6314ea0 100644
--- a/database/pt/core.texy
+++ b/database/pt/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Como você pode ver, o método `transaction()` retorna o valor de retorno da ligação de retorno.
 
 A transação() também pode ser aninhada, o que simplifica a implementação de repositórios independentes.
+
+
+Reflexão .[#toc-reflection]
+===========================
+
+O Nette Database fornece ferramentas para introspecção da estrutura do banco de dados por meio da classe [api:Nette\Database\Reflection]. Essa classe permite que você recupere informações sobre tabelas, colunas, índices e chaves estrangeiras. Você pode usar a reflexão para gerar esquemas, criar aplicativos flexíveis que funcionem com bancos de dados ou criar ferramentas gerais de banco de dados.
+
+É possível obter um objeto de reflexão de uma instância de conexão de banco de dados:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Trabalhando com tabelas .[#toc-working-with-tables]
+---------------------------------------------------
+
+Usando a reflexão, você pode iterar sobre todas as tabelas do banco de dados:
+
+```php
+// Listar os nomes de todas as tabelas
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Verificar se uma tabela existe
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Recuperar uma tabela específica
+$table = $reflection->getTable('users');
+```
+
+
+Informações sobre a coluna .[#toc-column-information]
+-----------------------------------------------------
+
+Para cada tabela, você pode obter informações detalhadas sobre suas colunas:
+
+```php
+// Iterar por todas as colunas
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Recuperar uma coluna específica
+$idColumn = $table->getColumn('id');
+```
+
+
+Índices e chaves primárias .[#toc-indexes-and-primary-keys]
+-----------------------------------------------------------
+
+A reflexão fornece informações sobre índices e chaves primárias:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Listar todos os índices
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Recuperar a chave primária
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Chaves estrangeiras .[#toc-foreign-keys]
+----------------------------------------
+
+Você também pode obter informações sobre chaves estrangeiras:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/pt/explorer.texy b/database/pt/explorer.texy
index 7e6205c677..43ff1303b7 100644
--- a/database/pt/explorer.texy
+++ b/database/pt/explorer.texy
@@ -92,7 +92,7 @@ Veja as possibilidades de filtragem e restrição de linhas [api:Nette\Database\
 | `$table->group($columns)` | Set GROUP BY
 | `$table->having($having)` | Set HAVING
 
-A interface fluente pode ser utilizada, por exemplo `$table->where(...)->order(...)->limit(...)`. Múltiplas condições `where` ou `whereOr` são conectadas com o operador `AND`.
+Podemos usar a chamada [interface fluente |nette:introduction-to-object-oriented-programming#fluent-interfaces], por exemplo, `$table->where(...)->order(...)->limit(...)`. Várias condições `where` ou `whereOr` são vinculadas pelo operador `AND`.
 
 
 onde() .[#toc-where]
@@ -338,7 +338,7 @@ Obtenção de dados .[#toc-fetching-data]
 | `$row = $table->get($id)` | Obtenha uma única linha com ID $id da tabela
 | `$row = $table->fetch()` | Obtenha a próxima fileira do resultado
 | `$array = $table->fetchPairs($key, $value)` | Buscar todos os valores para a matriz associativa
-| `$array = $table->fetchPairs($key)` | Traga todas as filas para a matriz associativa
+| `$array = $table->fetchPairs($value)` | Traga todas as filas para a matriz associativa
 | `count($table)` | Obter o número de filas no conjunto de resultados
 
 
diff --git a/database/ro/configuration.texy b/database/ro/configuration.texy
index 5995843a6e..6d86d3d4eb 100644
--- a/database/ro/configuration.texy
+++ b/database/ro/configuration.texy
@@ -51,6 +51,12 @@ database:
 		# numai MySQL: stabilește SET NAMES
 		charset:      # (șir de caractere) implicit la "utf8mb4" ("utf8" înainte de v5.5.3)
 
+		# numai MySQL: convertește TINYINT(1) în bool
+		convertBoolean: # (bool) implicit la false
+
+		# returnează coloanele de date ca obiecte imuabile (începând cu versiunea 3.2.1)
+		newDateTime:  # (bool) valoarea implicită este false
+
 		# numai Oracle și SQLite: formatul datei
 		formatDateTime: # (șir de caractere) implicit la "U".
 ```
diff --git a/database/ro/core.texy b/database/ro/core.texy
index 4314a3fe2d..4f6a811159 100644
--- a/database/ro/core.texy
+++ b/database/ro/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 După cum puteți vedea, metoda `transaction()` returnează valoarea de returnare a callback-ului.
 
 Tranzacția() poate fi, de asemenea, imbricata, ceea ce simplifică implementarea de depozite independente.
+
+
+Reflecție .[#toc-reflection]
+============================
+
+Nette Database oferă instrumente pentru introspecția structurii bazei de date prin clasa [api:Nette\Database\Reflection]. Această clasă vă permite să obțineți informații despre tabele, coloane, indexuri și chei străine. Puteți utiliza reflecția pentru a genera scheme, pentru a crea aplicații flexibile care lucrează cu baze de date sau pentru a construi instrumente generale pentru baze de date.
+
+Puteți obține un obiect reflection dintr-o instanță de conexiune la o bază de date:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Lucrul cu tabelele .[#toc-working-with-tables]
+----------------------------------------------
+
+Folosind reflexia, puteți itera peste toate tabelele din baza de date:
+
+```php
+// Lista numele tuturor tabelelor
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Verificați dacă un tabel există
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Preluarea unui anumit tabel
+$table = $reflection->getTable('users');
+```
+
+
+Informații despre coloană .[#toc-column-information]
+----------------------------------------------------
+
+Pentru fiecare tabel, puteți obține informații detaliate despre coloanele sale:
+
+```php
+// Iterați peste toate coloanele
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Preluarea unei anumite coloane
+$idColumn = $table->getColumn('id');
+```
+
+
+Indexuri și chei primare .[#toc-indexes-and-primary-keys]
+---------------------------------------------------------
+
+Reflecția oferă informații despre indici și chei primare:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Lista tuturor indicilor
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Recuperarea cheii primare
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Chei străine .[#toc-foreign-keys]
+---------------------------------
+
+De asemenea, puteți obține informații despre cheile străine:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/ro/explorer.texy b/database/ro/explorer.texy
index ab5ffa2031..5756461c41 100644
--- a/database/ro/explorer.texy
+++ b/database/ro/explorer.texy
@@ -92,7 +92,7 @@ Vedeți posibilitățile de filtrare și restricționare a rândurilor [api:Nett
 | `$table->group($columns)` | Setează GROUP BY
 | `$table->having($having)` | Setează HAVING
 
-Se poate utiliza o interfață fluidă, de exemplu `$table->where(...)->order(...)->limit(...)`. Mai multe condiții `where` sau `whereOr` sunt conectate cu ajutorul operatorului `AND`.
+Putem folosi o așa-numită [interfață fluentă |nette:introduction-to-object-oriented-programming#fluent-interfaces], de exemplu `$table->where(...)->order(...)->limit(...)`. Mai multe condiții `where` sau `whereOr` sunt legate între ele prin intermediul operatorului `AND`.
 
 
 unde() .[#toc-where]
@@ -338,7 +338,7 @@ Preluarea datelor .[#toc-fetching-data]
 | `$row = $table->get($id)` | Obține un singur rând cu ID $id din tabel
 | `$row = $table->fetch()` | Obține următorul rând din rezultat
 | `$array = $table->fetchPairs($key, $value)` | Preluarea tuturor valorilor în matricea asociativă
-| `$array = $table->fetchPairs($key)` | Preluarea tuturor rândurilor în matricea asociativă
+| `$array = $table->fetchPairs($value)` | Preluarea tuturor rândurilor în matricea asociativă
 | `count($table)` | Obține numărul de rânduri din setul de rezultate
 
 
diff --git a/database/ru/configuration.texy b/database/ru/configuration.texy
index 31740c9a68..15be644a34 100644
--- a/database/ru/configuration.texy
+++ b/database/ru/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# только для MySQL: устанавливает SET NAMES
-		charset:      # (string) по умолчанию 'utf8mb4' ('utf8' до v5.5.3)
+		charset:      # (string) по умолчанию 'utf8mb4'
+
+		# Только для MySQL: преобразует TINYINT(1) в bool
+		convertBoolean: # (bool) по умолчанию false
+
+		# возвращает столбцы даты как неизменяемые объекты (с версии 3.2.1)
+		newDateTime:  # (bool) по умолчанию false
 
 		# только для Oracle и SQLite: формат даті
 		formatDateTime: # (string) по умолчанию 'U'
diff --git a/database/ru/core.texy b/database/ru/core.texy
index 50d46cab53..53b198198f 100644
--- a/database/ru/core.texy
+++ b/database/ru/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Как видите, метод `transaction()` возвращает возвращаемое значение обратного вызова.
 
 Транзакция() также может быть вложенной, что упрощает реализацию независимых хранилищ.
+
+
+Отражение .[#toc-reflection]
+============================
+
+Nette Database предоставляет инструменты для изучения структуры базы данных с помощью класса [api:Nette\Database\Reflection]. Этот класс позволяет получать информацию о таблицах, столбцах, индексах и внешних ключах. Вы можете использовать отражение для генерации схем, создания гибких приложений, работающих с базами данных, или создания общих инструментов для работы с базами данных.
+
+Объект отражения можно получить из экземпляра соединения с базой данных:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Работа с таблицами .[#toc-working-with-tables]
+----------------------------------------------
+
+Используя отражение, вы можете выполнить итерацию по всем таблицам в базе данных:
+
+```php
+// Список имен всех таблиц
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Проверить, существует ли таблица
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Получить определенную таблицу
+$table = $reflection->getTable('users');
+```
+
+
+Информация о колоннах .[#toc-column-information]
+------------------------------------------------
+
+Для каждой таблицы можно получить подробную информацию о ее столбцах:
+
+```php
+// Итерация по всем столбцам
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Получение определенного столбца
+$idColumn = $table->getColumn('id');
+```
+
+
+Индексы и первичные ключи .[#toc-indexes-and-primary-keys]
+----------------------------------------------------------
+
+Отражение предоставляет информацию об индексах и первичных ключах:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Список всех индексов
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Получение первичного ключа
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Иностранные ключи .[#toc-foreign-keys]
+--------------------------------------
+
+Вы также можете получить информацию о внешних ключах:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/ru/explorer.texy b/database/ru/explorer.texy
index a3f91ad8f7..cad0b7b939 100644
--- a/database/ru/explorer.texy
+++ b/database/ru/explorer.texy
@@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))
 | `$table->group($columns)` | Устанавливаем GROUP BY
 | `$table->having($having)` | Устанавливаем HAVING
 
-Можно использовать текучий интерфейс (Fluent), например `$table->where(...)->order(...)->limit(...)`. Несколько условий `where` или `whereOr` соединяются с помощью оператора `AND`.
+Мы можем использовать так называемый [флюентный интерфейс |nette:introduction-to-object-oriented-programming#fluent-interfaces], например `$table->where(...)->order(...)->limit(...)`. Несколько условий `where` или `whereOr` связываются оператором `AND`.
 
 
 where()
@@ -338,7 +338,7 @@ Database Explorer умен и избавится от параметров и и
 | `$row = $table->get($id)` | Получаем одну строку с идентификатором $id из таблицы
 | `$row = $table->fetch()` | Получаем следующую строку из результата
 | `$array = $table->fetchPairs($key, $value)` | Выборка всех значений в виде ассоциативного массива
-| `$array = $table->fetchPairs($key)` | Выборка всех строк в виде ассоциативного массива
+| `$array = $table->fetchPairs($value)` | Выборка всех строк в виде ассоциативного массива
 | `count($table)` | Получаем количество строк в результирующем наборе
 
 
diff --git a/database/sl/configuration.texy b/database/sl/configuration.texy
index e0fa43ed33..8d17819357 100644
--- a/database/sl/configuration.texy
+++ b/database/sl/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (niz)
 
 		# samo MySQL: nastavi SET NAMES
-		charset:      # (niz) privzeta vrednost je 'utf8mb4' ('utf8' pred v5.5.3)
+		charset:      # (niz) privzeta vrednost je 'utf8mb4'
+
+		# samo MySQL: pretvori TINYINT(1) v bool
+		convertBoolean: # (bool) privzeto false
+
+		# vrne stolpce datumov kot nespremenljive predmete (od različice 3.2.1)
+		newDateTime:  # (bool) privzeto false
 
 		# samo Oracle in SQLite: format datuma
 		formatDateTime: # (niz) privzeta vrednost je 'U'
diff --git a/database/sl/core.texy b/database/sl/core.texy
index 1f65ebf455..300d2fe391 100644
--- a/database/sl/core.texy
+++ b/database/sl/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Kot lahko vidite, metoda `transaction()` vrne povratno vrednost povratnega klica.
 
 Metoda transaction() je lahko tudi vgnezdena, kar poenostavi izvajanje neodvisnih skladišč.
+
+
+Razmislek .[#toc-reflection]
+============================
+
+Podatkovna baza Nette zagotavlja orodja za introspekcijo strukture podatkovne baze prek razreda [api:Nette\Database\Reflection]. Ta razred omogoča pridobivanje informacij o tabelah, stolpcih, indeksih in tujih ključih. Refleksijo lahko uporabite za izdelavo shem, ustvarjanje prilagodljivih aplikacij, ki delajo s podatkovnimi zbirkami, ali za izdelavo splošnih orodij za podatkovne zbirke.
+
+Objekt refleksije lahko pridobite iz primerka povezave s podatkovno bazo:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Delo s tabelami .[#toc-working-with-tables]
+-------------------------------------------
+
+Z uporabo refleksije lahko iterirate po vseh tabelah v zbirki podatkov:
+
+```php
+// Seznam imen vseh tabel
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Preverite, ali tabela obstaja
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// iskanje določene tabele
+$table = $reflection->getTable('users');
+```
+
+
+Informacije o stolpcih .[#toc-column-information]
+-------------------------------------------------
+
+Za vsako tabelo lahko dobite podrobne informacije o njenih stolpcih:
+
+```php
+// Iterirajte po vseh stolpcih
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Pridobite določen stolpec
+$idColumn = $table->getColumn('id');
+```
+
+
+Indeksi in primarni ključi .[#toc-indexes-and-primary-keys]
+-----------------------------------------------------------
+
+Odsev zagotavlja informacije o indeksih in primarnih ključih:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Seznam vseh indeksov
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Pridobite primarni ključ
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Tuji ključi .[#toc-foreign-keys]
+--------------------------------
+
+Pridobite lahko tudi informacije o tujih ključih:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/sl/explorer.texy b/database/sl/explorer.texy
index 0763f4711c..0c3eb3a793 100644
--- a/database/sl/explorer.texy
+++ b/database/sl/explorer.texy
@@ -92,7 +92,7 @@ Oglejte si možnosti za filtriranje in omejevanje vrstic [api:Nette\Database\Tab
 | `$table->group($columns)` | Nastavitev GROUP BY
 | `$table->having($having)` | Nastavitev HAVING
 
-Uporabi se lahko vmesnik Fluent, na primer `$table->where(...)->order(...)->limit(...)`. Več pogojev `where` ali `whereOr` je povezanih z operatorjem `AND`.
+Uporabimo lahko tako imenovani [tekoči vmesnik |nette:introduction-to-object-oriented-programming#fluent-interfaces], na primer `$table->where(...)->order(...)->limit(...)`. Več pogojev `where` ali `whereOr` povežemo z operatorjem `AND`.
 
 
 kjer() .[#toc-where]
@@ -338,7 +338,7 @@ Pridobivanje podatkov .[#toc-fetching-data]
 | `$row = $table->get($id)` | Pridobi posamezno vrstico z ID $id iz tabele
 | `$row = $table->fetch()` | Pridobi naslednjo vrstico iz rezultata
 | `$array = $table->fetchPairs($key, $value)` | Prevzem vseh vrednosti v asociativno polje
-| `$array = $table->fetchPairs($key)` | Prevzem vseh vrstic v asociativno polje
+| `$array = $table->fetchPairs($value)` | Prevzem vseh vrstic v asociativno polje
 | `count($table)` | Pridobi število vrstic v nizu rezultatov
 
 
diff --git a/database/tr/configuration.texy b/database/tr/configuration.texy
index c8ca0e54fb..ccfb815289 100644
--- a/database/tr/configuration.texy
+++ b/database/tr/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# sadece MySQL: SET NAMES setleri
-		charset:      # (string) varsayılan olarak 'utf8mb4' ('utf8' v5.5.3'ten önce)
+		charset:      # (string) varsayılan olarak 'utf8mb4'
+
+		# sadece MySQL: TINYINT(1)'i bool'a dönüştürür
+		convertBoolean: # (bool) varsayılan değer false
+
+		# tarih sütunlarını değişmez nesneler olarak döndürür (3.2.1 sürümünden beri)
+		newDateTime:  # (bool) varsayılan değer false
 
 		# sadece Oracle ve SQLite: tarih biçimi
 		formatDateTime: # (string) varsayılan değer 'U'
diff --git a/database/tr/core.texy b/database/tr/core.texy
index 5532d29906..5ebcb92626 100644
--- a/database/tr/core.texy
+++ b/database/tr/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Gördüğünüz gibi, `transaction()` yöntemi geri aramanın dönüş değerini döndürür.
 
 transaction() da iç içe geçebilir, bu da bağımsız depoların uygulanmasını basitleştirir.
+
+
+Yansıma .[#toc-reflection]
+==========================
+
+Nette Database, [api:Nette\Database\Reflection] sınıfı aracılığıyla veritabanı yapısını incelemek için araçlar sağlar. Bu sınıf tablolar, sütunlar, dizinler ve yabancı anahtarlar hakkında bilgi almanızı sağlar. Yansımayı şemalar oluşturmak, veritabanlarıyla çalışan esnek uygulamalar oluşturmak veya genel veritabanı araçları oluşturmak için kullanabilirsiniz.
+
+Bir veritabanı bağlantı örneğinden bir yansıma nesnesi elde edebilirsiniz:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Tablolarla Çalışma .[#toc-working-with-tables]
+----------------------------------------------
+
+Yansımayı kullanarak, veritabanındaki tüm tablolar üzerinde yineleme yapabilirsiniz:
+
+```php
+// Tüm tabloların adlarını listeleyin
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Bir tablonun var olup olmadığını kontrol edin
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Belirli bir tabloyu alma
+$table = $reflection->getTable('users');
+```
+
+
+Kolon Bilgileri .[#toc-column-information]
+------------------------------------------
+
+Her tablo için sütunları hakkında ayrıntılı bilgi alabilirsiniz:
+
+```php
+// Tüm sütunlar üzerinde yinele
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Belirli bir sütunu alma
+$idColumn = $table->getColumn('id');
+```
+
+
+Dizinler ve Birincil Anahtarlar .[#toc-indexes-and-primary-keys]
+----------------------------------------------------------------
+
+Reflection, dizinler ve birincil anahtarlar hakkında bilgi sağlar:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Tüm dizinleri listele
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Birincil anahtarı al
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Yabancı Anahtarlar .[#toc-foreign-keys]
+---------------------------------------
+
+Yabancı anahtarlar hakkında da bilgi alabilirsiniz:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/tr/explorer.texy b/database/tr/explorer.texy
index cda960249c..76194e4f1b 100644
--- a/database/tr/explorer.texy
+++ b/database/tr/explorer.texy
@@ -92,7 +92,7 @@ Satırların nasıl filtreleneceği ve kısıtlanacağı ile ilgili olasılıkla
 | `$table->group($columns)` | GROUP BY ayarla
 | `$table->having($having)` | Set HAVING
 
-Fluent arayüzü kullanılabilir, örneğin `$table->where(...)->order(...)->limit(...)`. Birden fazla `where` veya `whereOr` koşulu `AND` operatörü ile bağlanır.
+[Akıcı arayüz |nette:introduction-to-object-oriented-programming#fluent-interfaces] olarak adlandırılan bir [arayüz |nette:introduction-to-object-oriented-programming#fluent-interfaces] kullanabiliriz, örneğin `$table->where(...)->order(...)->limit(...)`. Birden fazla `where` veya `whereOr` koşulu `AND` operatörü ile birbirine bağlanır.
 
 
 nerede() .[#toc-where]
@@ -338,7 +338,7 @@ Veri Getirme .[#toc-fetching-data]
 | `$row = $table->get($id)` | Tablodan $id kimliğine sahip tek bir satır al
 | `$row = $table->fetch()` | Sonuçtan bir sonraki satırı al
 | `$array = $table->fetchPairs($key, $value)` | Tüm değerleri ilişkisel diziye getir
-| `$array = $table->fetchPairs($key)` | Tüm satırları ilişkisel diziye getir
+| `$array = $table->fetchPairs($value)` | Tüm satırları ilişkisel diziye getir
 | `count($table)` | Sonuç kümesindeki satır sayısını al
 
 
diff --git a/database/uk/configuration.texy b/database/uk/configuration.texy
index a8be808cc7..833988c987 100644
--- a/database/uk/configuration.texy
+++ b/database/uk/configuration.texy
@@ -49,7 +49,13 @@ database:
 		sqlmode:      # (string)
 
 		# тільки для MySQL: встановлює SET NAMES
-		charset:      # (string) за замовчуванням 'utf8mb4' ('utf8' до v5.5.3)
+		charset:      # (string) за замовчуванням 'utf8mb4'
+
+		# тільки MySQL: перетворює TINYINT(1) в bool
+		convertBoolean: # (bool) за замовчуванням дорівнює false
+
+		# повертає стовпці дати як незмінні об'єкти (починаючи з версії 3.2.1)
+		newDateTime:  # (bool) за замовчуванням дорівнює false
 
 		# тільки для Oracle і SQLite: формат даті
 		formatDateTime: # (string) за замовчуванням 'U'
diff --git a/database/uk/core.texy b/database/uk/core.texy
index fb2022e9f7..f0e898c5c5 100644
--- a/database/uk/core.texy
+++ b/database/uk/core.texy
@@ -348,3 +348,95 @@ $id = $database->transaction(function ($database) {
 Як бачите, метод `transaction()` повертає значення зворотного виклику, що повертається.
 
 Транзакція() також може бути вкладеною, що спрощує реалізацію незалежних сховищ.
+
+
+Рефлексія .[#toc-reflection]
+============================
+
+Nette Database надає інструменти для самоаналізу структури бази даних за допомогою класу [api:Nette\Database\Reflection]. Цей клас дозволяє отримувати інформацію про таблиці, стовпці, індекси та зовнішні ключі. Ви можете використовувати рефлексію для генерації схем, створення гнучких додатків, які працюють з базами даних, або створення загальних інструментів для роботи з базами даних.
+
+Ви можете отримати об'єкт рефлексії з екземпляра підключення до бази даних:
+
+```php
+$reflection = $database->getReflection();
+```
+
+
+Робота з таблицями .[#toc-working-with-tables]
+----------------------------------------------
+
+Використовуючи рефлексію, ви можете ітераційно переглядати всі таблиці в базі даних:
+
+```php
+// Перерахувати назви всіх таблиць
+foreach ($reflection->tables as $tableName => $table) {
+    echo $tableName . "\n";
+}
+
+// Перевірити, чи існує таблиця
+if ($reflection->hasTable('users')) {
+    echo "The 'users' table exists";
+}
+
+// Отримати конкретну таблицю
+$table = $reflection->getTable('users');
+```
+
+
+Інформація про колонку .[#toc-column-information]
+-------------------------------------------------
+
+Для кожної таблиці ви можете отримати детальну інформацію про її стовпці:
+
+```php
+// Ітерація по всіх стовпцях
+foreach ($table->columns as $column) {
+    echo "Column: " . $column->name . "\n";
+    echo "Type: " . $column->nativeType . "\n";
+    echo "Nullable: " . ($column->nullable ? 'Yes': 'No') . "\n";
+    echo "Default value: " . ($column->default ?? 'None') . "\n";
+    echo "Primary key: " . ($column->primary ? 'Yes': 'No') . "\n";
+    echo "Auto-increment: " . ($column->autoIncrement ? 'Yes': 'No') . "\n";
+}
+
+// Отримати певний стовпець
+$idColumn = $table->getColumn('id');
+```
+
+
+Індекси та первинні ключі .[#toc-indexes-and-primary-keys]
+----------------------------------------------------------
+
+Reflection надає інформацію про індекси та первинні ключі:
+
+```php
+$listColumnNames = fn(array $columns) => implode(', ', array_map(fn($col) => $col->name, $columns));
+
+// Перерахувати всі індекси
+foreach ($table->indexes as $index) {
+    echo "Index: " . ($index->name ?? 'Unnamed') . "\n";
+    echo "Columns: " . $listColumnNames($index->columns) . "\n";
+    echo "Unique: " . ($index->unique ? 'Yes': 'No') . "\n";
+    echo "Primary key: " . ($index->primary ? 'Yes': 'No') . "\n";
+}
+
+// Отримати первинний ключ
+if ($table->primaryKey) {
+    echo "Primary key: " . $listColumnNames($table->primaryKey->columns) . "\n";
+}
+```
+
+
+Зовнішні ключі .[#toc-foreign-keys]
+-----------------------------------
+
+Ви також можете отримати інформацію про зовнішні ключі:
+
+```php
+foreach ($table->foreignKeys as $fk) {
+    echo "Foreign key: " . ($fk->name ?? 'Unnamed') . "\n";
+    echo "Local columns: " . $listColumnNames($fk->localColumns) . "\n";
+    echo "References table: {$fk->foreignTable->name}\n";
+    echo "References columns: " . $listColumnNames($fk->foreignColumns) . "\n";
+}
+```
diff --git a/database/uk/explorer.texy b/database/uk/explorer.texy
index 8c04ec8f5d..c95cc9b0c8 100644
--- a/database/uk/explorer.texy
+++ b/database/uk/explorer.texy
@@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))
 | `$table->group($columns)` | Встановлюємо GROUP BY
 | `$table->having($having)` | Встановлюємо HAVING
 
-Можна використовувати поточний інтерфейс (Fluent), наприклад `$table->where(...)->order(...)->limit(...)`. Кілька умов `where` або `whereOr` з'єднуються за допомогою оператора `AND`.
+Ми можемо використовувати так званий вільний [інтерфейс |nette:introduction-to-object-oriented-programming#fluent-interfaces], наприклад `$table->where(...)->order(...)->limit(...)`. Кілька умов `where` або `whereOr` зв'язуються оператором `AND`.
 
 
 where() .[#toc-where]
@@ -338,7 +338,7 @@ Database Explorer розумний і позбудеться параметрі
 | `$row = $table->get($id)` | Отримуємо один рядок з ідентифікатором $id з таблиці
 | `$row = $table->fetch()` | Отримуємо наступний рядок із результату
 | `$array = $table->fetchPairs($key, $value)` | Вибірка всіх значень у вигляді асоціативного масиву
-| `$array = $table->fetchPairs($key)` | Вибірка всіх рядків у вигляді асоціативного масиву
+| `$array = $table->fetchPairs($value)` | Вибірка всіх рядків у вигляді асоціативного масиву
 | `count($table)` | Отримуємо кількість рядків у результуючому наборі
 
 
diff --git a/dependency-injection/bg/autowiring.texy b/dependency-injection/bg/autowiring.texy
index 3b826597cd..acefa451a3 100644
--- a/dependency-injection/bg/autowiring.texy
+++ b/dependency-injection/bg/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 След това контейнерът DI автоматично ще предаде масив от услуги, отговарящи на зададения тип. Това ще доведе до пропускане на услуги с деактивирано автоматично свързване.
 
-Ако не можете да контролирате формата за коментари на phpDoc, можете да подадете масив от услуги директно в конфигурацията, като използвате [`typed()` |services#Special-Functions].
+Типът в коментара може да бъде и под формата `array<int, Class>` или `list<Class>`. Ако не можете да контролирате формата на phpDoc коментара, можете да подадете масив от услуги директно в конфигурацията, като използвате [`typed()` |services#Special Functions].
 
 
 Скаларни аргументи .[#toc-scalar-arguments]
diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy
index d90b41c6b4..a1bfa25820 100644
--- a/dependency-injection/bg/configuration.texy
+++ b/dependency-injection/bg/configuration.texy
@@ -67,7 +67,7 @@ parameters:
 ```neon
 decorator:
 	# За всички услуги, които са екземпляри на този клас или интерфейс
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # извикване на този метод
 			- $absoluteUrls = true # и задаване на променлива
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Ако не използвате масива `$container->parameters`, можете да деактивирате експортирането на параметри. Като алтернатива можете да експортирате само тези тагове, чрез които получавате услуги, като използвате метода `$container->findByTag(...)`.
+Ако не използвате масива `$container->getParameters()`, можете да деактивирате експортирането на параметри. Като алтернатива можете да експортирате само тези тагове, чрез които получавате услуги, като използвате метода `$container->findByTag(...)`.
 Ако изобщо не извиквате този метод, можете да деактивирате напълно експортирането на тагове, като посочите `false`.
 
 Можете значително да намалите метаданните за автоматичното свързване, като посочите класовете, които използвате, като параметър в метода `$container->getByType()`.
@@ -191,20 +191,15 @@ return [
 
 ```neon
 търсене:
-	# избирате собствени имена на раздели
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Обикновено обаче не искаме да добавяме всички класове и интерфейси, затова можем да ги филтрираме:
 
 ```neon
 търсене:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# филтриране по име на файл (string|string[])
 		files:
@@ -220,7 +215,7 @@ return [
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+файлове: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/bg/extensions.texy b/dependency-injection/bg/extensions.texy
index ce13c90c1b..9e1a004644 100644
--- a/dependency-injection/bg/extensions.texy
+++ b/dependency-injection/bg/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $инициализация .[wiki-method]
 =============================
 
-Конфигураторът се извиква от кода за инициализация след [създаването на контейнер |application:bootstrap#index-php], който се създава чрез запис в обекта `$this->initialization` с помощта на [метода addBody() |php-generator:#method-and-function-body].
+Конфигураторът се извиква от кода за инициализация след [създаването на контейнер |application:bootstrap#index-php], който се създава чрез запис в обекта `$this->initialization` с помощта на [метода addBody() |php-generator:#method-and-function-bodies].
 
 Ще покажем пример за това как да стартирате сесия или услуги, които имат таг `run`, като използвате кода за инициализация:
 
diff --git a/dependency-injection/bg/factory.texy b/dependency-injection/bg/factory.texy
index d08862320c..b50ea73905 100644
--- a/dependency-injection/bg/factory.texy
+++ b/dependency-injection/bg/factory.texy
@@ -170,39 +170,45 @@ services:
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Така че вместо да предадем няколко генерирани фабрики и аксесори, ще предадем друга сложна фабрика, която може да прави повече.
 
-Алтернативно, вместо няколко метода, можем да използваме параметрите `create()` и `get()`:
+Вместо това можете да използвате `get()` с параметър вместо няколко метода:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Тогава `MultiFactory::createArticle()` прави същото като `MultiFactoryAlt::create('article')`. Алтернативният запис обаче има недостатъка, че не е ясно кои стойности поддържа `$name` и не е логически възможно да се разграничат различните стойности на връщане за различните `$name` в интерфейса.
+В този случай `MultiFactory::getArticle()` прави същото, което и `MultiFactoryAlt::get('article')`. Алтернативният синтаксис обаче има няколко недостатъка. Не е ясно кои стойности на `$name` се поддържат, а типът на връщане не може да бъде посочен в интерфейса, когато се използват няколко различни стойности на `$name`.
 
 
 Определение за списък .[#toc-definition-with-a-list]
 ----------------------------------------------------
-И как да дефинираме множество фабрики в конфигурацията? Ще създадем три услуги за създаване/извличане и след това самата фабрика:
+Този начин може да се използва за дефиниране на множество фабрики в конфигурацията: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Или в дефиницията на фабриката можем да се позовем на съществуващи услуги с помощта на референция:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ services:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.context
 	)
diff --git a/dependency-injection/bg/faq.texy b/dependency-injection/bg/faq.texy
index 392c71c995..e09adb33a2 100644
--- a/dependency-injection/bg/faq.texy
+++ b/dependency-injection/bg/faq.texy
@@ -61,7 +61,7 @@ DI не оказва влияние върху производителност
 
 Защо композицията е за предпочитане пред наследяването? .[#toc-why-composition-is-preferred-over-inheritance]
 -------------------------------------------------------------------------------------------------------------
-За предпочитане е да се използва композиция, а не наследяване, тъй като тя служи за целите на повторната употреба на кода, без да е необходимо да се притеснявате за ефекта от промяната. По този начин се осигурява по-свободно свързване, при което не е необходимо да се притесняваме, че промяната на някакъв код ще доведе до промяна на друг зависим код. Типичен пример за това е ситуацията, наречена [ад на конструкторите |passing-dependencies#Constructor hell].
+За предпочитане е да се използва [композиция |nette:introduction-to-object-oriented-programming#composition] вместо [наследяване |nette:introduction-to-object-oriented-programming#inheritance], тъй като тя служи за повторно използване на кода, без да се налага да се притеснявате за последствията от промените. По този начин се осигурява по-хлабава връзка, при която не е необходимо да се притесняваме, че промяната на някакъв код ще доведе до необходимостта от промяна на друг зависим код. Типичен пример за това е ситуацията, наречена " [ад на конструкторите" |passing-dependencies#Constructor hell].
 
 
 Може ли Nette DI Container да се използва извън Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/bg/global-state.texy b/dependency-injection/bg/global-state.texy
index bbb5bbc5ba..410e2eb227 100644
--- a/dependency-injection/bg/global-state.texy
+++ b/dependency-injection/bg/global-state.texy
@@ -301,4 +301,4 @@ class Foo
 
 По време на този процес може да откриете, че трябва да разделите даден клас, защото той има повече от една отговорност. Не се притеснявайте за това; стремете се към принципа на една отговорност.
 
-*Искам да благодаря на Мишко Хевери, чиито статии като [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] са в основата на тази глава.*
+*Искам да благодаря на Мишко Хевери, чиито статии като [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] са в основата на тази глава.*
diff --git a/dependency-injection/bg/passing-dependencies.texy b/dependency-injection/bg/passing-dependencies.texy
index 079f493c12..8dbca62c01 100644
--- a/dependency-injection/bg/passing-dependencies.texy
+++ b/dependency-injection/bg/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Проблемът възниква, когато искаме да променим конструктора на класа `BaseClass`, например когато се добави нова зависимост. Тогава трябва да променим и всички конструктори на децата. Което превръща подобна модификация в ад.
 
-Как да предотвратим това? Решението е да се даде **приоритет на композицията пред наследяването**.
+Как да предотвратим това? Решението е да се даде предимство на [композицията пред наследяването** |faq#Why composition is preferred over inheritance].
 
-Така че нека да проектираме кода по различен начин. Ще избягваме абстрактните класове `Base*`. Вместо `MyClass` да получава някаква функционалност, наследявайки я от `BaseClass`, тя ще има тази функционалност, предадена като зависимост:
+Затова нека да проектираме кода по различен начин. Ще избягваме [абстрактните |nette:introduction-to-object-oriented-programming#abstract-classes] класове `Base*`. Вместо `MyClass` да получи някаква функционалност, наследявайки я от `BaseClass`, тя ще бъде предадена като зависимост:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ class MyClass
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ $obj->cache = $cache;
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/bg/services.texy b/dependency-injection/bg/services.texy
index 44bb7797e9..4092d43fdf 100644
--- a/dependency-injection/bg/services.texy
+++ b/dependency-injection/bg/services.texy
@@ -2,32 +2,32 @@
 *********************
 
 .[perex]
-Конфигурацията е мястото, където поставяме дефинициите на потребителските услуги. Това е направено в раздела `services`.
+Конфигурацията е мястото, където даваме указания на контейнера DI как да сглобява отделните услуги и как да ги свързва с други зависимости. Nette предоставя много ясен и елегантен начин за постигане на това.
 
-Например, така създаваме услуга с име `database`, която ще бъде инстанция на класа `PDO`:
+Разделът `services` в конфигурационния файл NEON е мястото, където дефинираме нашите потребителски услуги и техните конфигурации. Нека разгледаме прост пример за дефиниране на услуга с име `database`, която представлява инстанция на класа `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Наименованията на услугите се използват, за да можем да [се обръщаме към |#Referencing-Services] тях. Ако услугата не се споменава, не е необходимо да ѝ давате име. Затова просто използваме двоеточие вместо име:
+Тази конфигурация води до следния фабричен метод в [контейнера DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  # анонимный сервис
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Запис на един ред може да бъде разделен на няколко реда, за да се позволи добавянето на допълнителни клавиши, напр. за [настройка |#setup]. Псевдонимът на ключа `create:` е `factory:`.
+Имената на услугите ни позволяват да се позоваваме на тях в други части на конфигурационния файл, като използваме формата `@serviceName`. Ако няма нужда да даваме име на услугата, можем просто да използваме точка:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-След това извличаме услугата от контейнера DI, като използваме метода `getService()` по име или още по-добре - метода `getByType()` по тип:
+За да извлечем услуга от контейнера DI, можем да използваме метода `getService()` с името на услугата като параметър или метода `getByType()` с типа на услугата:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Създаване на услуга .[#toc-creating-a-service]
-==============================================
+Създаване на услуги .[#toc-service-creation]
+============================================
 
-В повечето случаи създаваме услуга, като просто създаваме инстанция на класа:
+Най-често създаваме услуга, като просто инстанцираме определен клас. Например:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Което ще създаде фабричен метод в [DI-контейнера |container]:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Алтернативно, ключът `arguments` може да се използва за предаване на [аргументи |#Arguments]:
+Ако трябва да разширим конфигурацията с допълнителни ключове, дефиницията може да се разшири на няколко реда:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-Статичен метод също може да създаде услуга:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Това е еквивалентно на код на PHP:
+Ключът `create` има псевдоним `factory`, като и двете версии са често срещани в практиката. Въпреки това препоръчваме да използвате `create`.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-Предполага се, че статичният метод `My\Database::create()` има определена връщана стойност, която контейнерът DI трябва да знае. Ако няма такъв, записваме типа в конфигурацията:
+Аргументите на конструктора или методът за създаване могат алтернативно да бъдат записани в ключа `arguments`:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Nette DI ви предоставя изключително мощни инструменти за изразяване, които ви позволяват да пишете почти всичко. Например за [препращане към |#Referencing-Services] друга услуга и извикване на нейния метод. За улеснение се използва `::` вместо `->`.
+Не е задължително услугите да се създават само чрез просто инстанциране на клас; те могат да се създават и в резултат на извикване на статични методи или методи на други услуги:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Това е еквивалентно на код на PHP:
+Обърнете внимание, че за опростяване вместо `->`, използваме `::`, вж. [изразните средства |#expression means]. Тези фабрични методи се генерират:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-Извикванията на методи могат да бъдат верижно свързани, както в PHP:
+Контейнерът DI трябва да знае типа на създадената услуга. Ако създаваме услуга с помощта на метод, който няма определен тип на връщане, трябва изрично да споменем този тип в конфигурацията:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Това е еквивалентно на код на PHP:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Аргументи .[#toc-arguments]
 ===========================
 
-Именуваните параметри могат да се използват и за предаване на аргументи:
+Предаването на аргументи към конструкторите и методите става по начин, много подобен на този в обикновения PHP:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test' # позиционен
-		username: root                    # named
-		password: secret                  # named
-	)
-```
-
-Използването на запетаи не е задължително, когато аргументите се разделят на няколко реда.
-
-Разбира се, можем да използваме и [други услуги |#Referencing-Services] или [параметри |configuration#Parameters] като аргументи:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-Съответства на кода на PHP:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Ако първият аргумент е [автоматично монтиран |autowiring] и искате да посочите втория аргумент, пропуснете първия, като използвате `_`, например `Foo(_, %appDir%)`. Или, още по-добре, предайте само втория аргумент като именуван параметър, например: `Foo(path: %appDir%)`.
-
-Nette DI и форматът NEON ви дават изключително мощно средство за изразяване, което ви позволява да напишете почти всичко. По този начин аргументът може да бъде новосъздаден обект, можете да извикате статични методи, методи от други услуги или дори глобални функции, като използвате специална нотация:
+За по-добра четимост можем да изписваме аргументите на отделни редове. В този формат използването на запетаи не е задължително:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)           # създаване на обект
-		DateTime::createFromFormat('Y-m-d')    # извикване на статичен метод
-		@anotherService                        # предаване на друга услуга
-		@http.request::getRemoteAddress()      # извикване на друг метод на услугата
-		::getenv(NetteMode)                    # извикване на глобална функция
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-Съответства на кода на PHP:
-
-```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('NetteMode')
-	);
-}
-```
-
-
-Специални функции .[#toc-special-functions]
--------------------------------------------
-
-Можете също така да използвате специални функции в аргументите, за да изравнявате или отричате стойности:
-
-- `not(%arg%)` отрицание
-- `bool(%arg%)` преобразуване на bool без загуби
-- `int(%arg%)` преобразуване на int без загуби
-- `float(%arg%)` преобразуване на плаващо състояние без загуби
-- `string(%arg%)` преобразуване на низове без загуби
+Можете също така да назовете аргументите, което ви позволява да не се притеснявате за реда им:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-Презаписването без загуби се различава от нормалното презаписване в PHP, например с помощта на `(int)`, по това, че хвърля изключение за нецифрови стойности.
-
-Като аргументи могат да бъдат подадени няколко услуги. Масив от всички услуги от определен тип (т.е. клас или интерфейс) може да бъде създаден чрез функцията `typed()`. Функцията ще пропусне услуги, при които автоматичното свързване е забранено, и могат да бъдат зададени няколко типа, разделени със запетая.
+Ако желаете да пропуснете някои аргументи и да използвате стойностите им по подразбиране или да вмъкнете услуга чрез [автоматично свързване |autowiring], използвайте долна черта:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-Можете също така да предадете масив от услуги автоматично, като използвате [автоматично свързване |autowiring#Collection-of-Services].
-
-Чрез функцията `tagged()` се създава масив от всички услуги с определен [етикет |#Tags]. Можете да посочите няколко тага, разделени със запетая.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Връзки към услуги .[#toc-referencing-services]
-==============================================
-
-Връзките към отделните услуги се използват със символа `@` и имени, например `@database`:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-Съответства на кода на PHP:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Дори към анонимни услуги може да се направи препратка чрез обратно извикване, като вместо името им се посочи техният тип (клас или интерфейс). Това обаче обикновено не е необходимо поради [автоматичното препращане |autowiring].
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # или @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Аргументите могат да бъдат услуги, параметри и много други, вижте [изразни средства |#expression means].
 
 
 Настройка .[#toc-setup]
 =======================
 
-В раздела `setup` са изброени методите, които ще бъдат извикани при създаването на услугата:
+В раздела `setup` дефинираме методите, които трябва да се извикат при създаването на услугата.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Съответства на кода на PHP:
+В PHP това би изглеждало така:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-Могат да се задават и свойства. Добавянето на елемент в масив също се поддържа и трябва да се запише в кавички, за да не противоречи на синтаксиса на NEON:
-
+В допълнение към извикването на методи, можете също така да предавате стойности на свойствата. Добавянето на елемент към масив също се поддържа, но трябва да го оградите в кавички, за да избегнете колизия със синтаксиса на NEON:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Съответства на кода на PHP:
+В PHP това ще се преведе като:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-В конфигурацията обаче могат да се извикват и статични методи или методи на други услуги. Ние им предаваме действителната услуга като `@self`:
-
+В настройката можете също така да извиквате статични методи или методи на други услуги. Ако трябва да предадете текущата услуга като аргумент, използвайте `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Съответства на кода на PHP:
+Обърнете внимание, че за опростяване вместо `->`, използваме `::`, вижте [изразните средства |#expression means]. Това генерира следния фабричен метод:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
-Автоматично обвързване .[#toc-autowiring]
-=========================================
+Средства за изразяване .[#toc-expression-means]
+===============================================
+
+Nette DI ни предоставя изключително богати възможности за изразяване, което ни позволява да изразим почти всичко. В конфигурационните файлове можем да използваме [параметри |configuration#parameters]:
+
+```neon
+# параметър
+%wwwDir%
+
+# стойност под ключ на параметър
+%mailer.user%
+
+# параметър в рамките на низ
+'%wwwDir%/images'
+```
+
+Можем също така да създаваме обекти, да извикваме методи и функции:
+
+```neon
+# създаване на обект
+DateTime()
+
+# извикване на статичен метод
+Collator::create(%locale%)
+
+# извикване на функция на PHP
+::getenv(DB_USER)
+```
+
+Услугите се наричат по име или по тип:
+
+```neon
+# услуга по име
+@database
+
+# услуга по тип
+@Nette\Database\Connection
+```
+
+Използвайте синтаксис на първокласни извиквания: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Използвайте константи:
+
+```neon
+# клас константа
+FilesystemIterator::SKIP_DOTS
+
+# глобална константа, получена чрез PHP функцията constant()
+::constant(PHP_VERSION)
+```
+
+Извикванията на методите могат да бъдат верижно свързани, точно както в PHP. За улеснение, вместо `->`, използваме `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Тези изрази могат да се използват навсякъде при [създаване на услуги |#Service Creation], в [аргументи |#Arguments], в секцията за [настройка |#setup] или в [параметри |configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Специални функции .[#toc-special-functions]
+-------------------------------------------
+
+В рамките на конфигурационните файлове можете да използвате тези специални функции:
+
+- `not()` за отричане на стойности
+- `bool()`, `int()`, `float()`, `string()` за привеждане на типове без загуби
+- `typed()` за генериране на масив от всички услуги от определен тип
+- `tagged()` за създаване на масив от всички услуги с даден етикет
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+В сравнение с конвенционалното типизиране в PHP, като например `(int)`, типизирането без загуби ще хвърля изключение за нецифрови стойности.
+
+Функцията `typed()` създава масив от всички услуги от определен тип (клас или интерфейс). Тя изключва услуги с изключено автоматично свързване. Могат да бъдат зададени няколко типа, разделени със запетаи.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+Можете също така автоматично да подадете масив от услуги от определен тип като аргумент, като използвате [автоподразбиране |autowiring#Collection of Services].
+
+Функцията `tagged()` създава масив от всички услуги с определен етикет. Могат да бъдат изброени няколко тага, разделени със запетаи.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
+Автоматично окабеляване .[#toc-autowiring]
+==========================================
 
-Ключът `autowired` може да се използва за изключване на услуга от автоматично свързване или за повлияване на нейното поведение. За повече информация вижте глава [Автоматично обвързване |autowiring].
+Ключът `autowired` ви позволява да променяте поведението на автоматичното свързване за определена услуга. За повече подробности вижте [главата за автоматичното свързване |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # foo е премахнат от автовръзката
+		autowired: false     # услугата foo е изключена от автоматичното свързване
 ```
 
 
 Етикети .[#toc-tags]
 ====================
 
-Информацията за потребителя може да бъде добавена към отделните услуги под формата на тагове:
+Етикетите се използват за добавяне на допълнителна информация към услугите. Можете да зададете един или повече тагове на услуга:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Етикетите също могат да бъдат значими:
+Таговете могат да носят и стойности:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Масив от услуги с дефинирани тагове може да бъде предаден като аргумент с помощта на функцията `tagged()`. Могат да бъдат зададени и няколко тага, разделени със запетая.
+За извличане на всички услуги с определени тагове можете да използвате функцията `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Имената на услугите могат да бъдат получени от контейнера DI чрез метода `findByTag()`:
+В контейнера DI можете да получите имената на всички услуги с определен таг, като използвате метода `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
 // $names е масив, съдържащ името на услугата и стойността на тага
-// например ['foo' => 'monolog.logger.event', ...]
+// напр. ['foo' => 'monolog.logger.event', ...]
 ```
 
 
-Режим на изпълнение .[#toc-inject-mode]
-=======================================
+Режим на инжектиране .[#toc-inject-mode]
+========================================
 
-Флагът `inject: true` се използва за активиране на прехвърлянето на зависимости чрез публични променливи с помощта на анотацията [inject |best-practices:inject-method-attribute#Inject Attributes] и методите [inject*() |best-practices:inject-method-attribute#inject Methods].
+Използването на флага `inject: true` активира предаването на зависимости чрез публични променливи с анотацията [inject |best-practices:inject-method-attribute#Inject Attributes] и методите [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -398,13 +391,13 @@ services:
 		inject: true
 ```
 
-По подразбиране `inject` е активиран само за предварително засяване.
+По подразбиране `inject` е активиран само за презентатори.
 
 
-Промяна на услугите .[#toc-modification-of-services]
-====================================================
+Промени в услугата .[#toc-service-modifications]
+================================================
 
-В контейнера DI има редица услуги, които са добавени от вграденото или [вашето разширение |#di-extension]. Дефинициите на тези услуги могат да се променят в конфигурацията. Например за услугата `application.application`, която по подразбиране е обектът `Nette\Application\Application`, можем да променим класа:
+Контейнерът DI съдържа много услуги, добавени чрез вградени или [потребителски разширения |#extensions]. Можете да променяте дефинициите на тези услуги директно в конфигурацията. Например, можете да промените класа на услугата `application.application`, която традиционно е `Nette\Application\Application`, на нещо друго:
 
 ```neon
 services:
@@ -415,7 +408,7 @@ services:
 
 Флагът `alteration` е информативен и показва, че просто модифицираме съществуваща услуга.
 
-Можем да добавим и `setup`:
+Можем също така да допълним настройката:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-При пренаписване на услугата можем да изтрием първоначалните аргументи, елементи на `setup` или тагове, за които е `reset`:
+Когато презаписвате услуга, може да искате да премахнете оригиналните аргументи, елементи на настройката или тагове, което е мястото, където `reset` е полезен:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Услуга, добавена от разширение, може също да бъде премахната от контейнера:
+Ако искате да премахнете услуга, добавена от разширение, можете да го направите по следния начин:
 
 ```neon
 services:
diff --git a/dependency-injection/cs/autowiring.texy b/dependency-injection/cs/autowiring.texy
index 3b2b4f8e0a..d1ae064b92 100644
--- a/dependency-injection/cs/autowiring.texy
+++ b/dependency-injection/cs/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 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].
+Typ v komentáři může být také ve tvaru `array<int, Class>` nebo `list<Class>`. 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].
 
 
 Skalární argumenty
diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy
index a42f461c3c..0ae0adcd06 100644
--- a/dependency-injection/cs/configuration.texy
+++ b/dependency-injection/cs/configuration.texy
@@ -67,7 +67,7 @@ Jak upravit hromadně všechny služby určitého typu? Třeba zavolat určitou
 ```neon
 decorator:
 	# u všech služeb, co jsou instancí této třídy nebo rozhraní
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # zavolej tuto metodu
 			- $absoluteUrls = true   # a nastav proměnnou
@@ -122,7 +122,7 @@ di:
 			- 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 nevyužíváte pole `$container->getParameters()`, 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()`.
@@ -191,20 +191,15 @@ Stačí uvést, ve kterých adresářích (a podadresářích) má třídy hleda
 
 ```neon
 search:
-	# názvy sekcí si volíte sami
-	formuláře:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	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
+	-	in: %appDir%/Forms
 
 		# filtrování podle názvu souboru (string|string[])
 		files:
@@ -220,7 +215,7 @@ Nebo můžeme vybírat třídy, které dědí či implementují alespoň jednu z
 
 ```neon
 search:
-	formuláře:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Lze definovat i vylučující pravidla, tj. masky názvu třídy nebo dědičné
 
 ```neon
 search:
-	formuláře:
+	-	in: %appDir%
 		exclude:
+			files: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Všem službám lze nastavit tagy:
 
 ```neon
 search:
-	formuláře:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/cs/container.texy b/dependency-injection/cs/container.texy
index 3583a27dad..0f861f22c6 100644
--- a/dependency-injection/cs/container.texy
+++ b/dependency-injection/cs/container.texy
@@ -41,7 +41,7 @@ $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ý:
+Kontejner má zatím zapsané všechny údaje natvrdo. Uděláme tedy další krok a přidáme parametry, aby byl kontejner skutečně užitečný:
 
 ```php
 class Container
diff --git a/dependency-injection/cs/factory.texy b/dependency-injection/cs/factory.texy
index 1398077e88..1775e166f9 100644
--- a/dependency-injection/cs/factory.texy
+++ b/dependency-injection/cs/factory.texy
@@ -71,6 +71,9 @@ class UserController
 }
 ```
 
+Poznámky:
+- při opakovaném volání create() se vytvoří vždy nová instance Article
+- instance objektů včetně závislostí se vytvářejí lazy-loading tj. až při volání create()
 
 Parametrizovaná továrna
 =======================
@@ -170,52 +173,58 @@ Naše továrny a accessory uměly zatím vždy vyrábět nebo vracet jen jeden o
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Takže místo toho, abych si předávali několik generovaných továren a accessorů, předáme jednu komplexnější továrnu, která toho umí víc.
 
-Alternativně lze místo několika metod použít `create()` a `get()` s parameterem:
+Alternativně lze místo několika metod použít `get()` s parameterem:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Pak platí, že `MultiFactory::createArticle()` dělá totéž jako `MultiFactoryAlt::create('article')`. Nicméně alternativní zápis má tu nevýhodu, že není zřejmé, jaké hodnoty `$name` jsou podporované a logicky také nelze v rozhraní odlišit různé návratové hodnoty pro různé `$name`.
+Pak platí, že `MultiFactory::getArticle()` má identickou funkci jako `MultiFactoryAlt::get('article')`. 
 
 
-Definice seznamem
------------------
-A jak definovat vícenásobnou továrnu v konfiguraci? Vytvoříme tři služby, které bude vytvářet/vracet, a potom samotnou továrnu:
+Pro správnou funkci vícenásobné továrny/accessoru je nutné ji definovat v konfiguraci. První možností je definovat seznam pojmenovaných argumentů konstruktoru továrny který reprezentuje vytvářené objekty - jméno definuje suffix metody create<Name>(), argument třídu z níž se vytváří objekt: .{data-version:3.2.0}
 
 ```neon
 services:
-	article: Article
-	- Model\Foo
-	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: Article                      # definuje createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # definuje getDb()
 	)
 ```
 
+Nebo se můžeme v definici továrny odkázat na existující služby pomocí jména služby:
 
-Definice pomocí tagů
---------------------
+```neon
+services:
+	article: Article
+	- PDO(%dsn%, %user%, %password%)
+	- MultiFactory(
+		article: @article    # definuje createArticle()
+		db: @\PDO            # definuje getDb()
+	)
+```
 
 Druhou možností je využít k definici [tagy|services#Tagy]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
-	- App\Model\DatabaseAccessor(
-		db1: @database.db1.explorer
-	)
+    -
+        create:  Article	 		     # definuje createArticle()
+            tags:
+                listener:  article
+    -
+        create: PDO(%dsn%, %user%, %password%)    # definuje getDb()
+            tags:
+                listener:  db
+
+    - MultiAccessor(tagged: listener)
 ```
diff --git a/dependency-injection/cs/faq.texy b/dependency-injection/cs/faq.texy
index 31f26903b0..7d5e4b199b 100644
--- a/dependency-injection/cs/faq.texy
+++ b/dependency-injection/cs/faq.texy
@@ -61,7 +61,7 @@ Pamatujte, že přechod na Dependency Injection je investice do kvality kódu a
 
 Proč se upřednostňuje kompozice před dědičností?
 ------------------------------------------------
-Je vhodnější používat kompozici místo dědičnosti, protože slouží k opětovnému použití kódu, aniž bychom se museli starat o důsledky změn. Poskytuje tedy volnější vazbu, kdy nemusíme mít obavy, že změna nějakého kódu způsobí potřebu změny jiného závislého kódu. Typickým příkladem je situace označovaná jako [constructor hell |passing-dependencies#Constructor hell].
+Je vhodnější používat [kompozici|nette:introduction-to-object-oriented-programming#kompozice] místo [dědičnosti|nette:introduction-to-object-oriented-programming#dedicnost], protože slouží k opětovnému použití kódu, aniž bychom se museli starat o důsledky změn. Poskytuje tedy volnější vazbu, kdy nemusíme mít obavy, že změna nějakého kódu způsobí potřebu změny jiného závislého kódu. Typickým příkladem je situace označovaná jako [constructor hell |passing-dependencies#Constructor hell].
 
 
 Lze použít Nette DI Container mimo Nette?
diff --git a/dependency-injection/cs/global-state.texy b/dependency-injection/cs/global-state.texy
index 41c15a1b8c..7bf4a5f329 100644
--- a/dependency-injection/cs/global-state.texy
+++ b/dependency-injection/cs/global-state.texy
@@ -301,4 +301,4 @@ Když promýšlíte návrh kódu, myslete na to, že každé `static $foo` před
 
 Během tohoto procesu možná zjistíte, že je třeba třídu rozdělit, protože má více než jednu odpovědnost. Nebojte se toho; usilujte o princip jedné odpovědnosti.
 
-*Rád bych poděkoval Miškovi Heverymu, jehož články, jako je [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], jsou základem této kapitoly.*
+*Rád bych poděkoval Miškovi Heverymu, jehož články, jako je [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], jsou základem této kapitoly.*
diff --git a/dependency-injection/cs/passing-dependencies.texy b/dependency-injection/cs/passing-dependencies.texy
index 433f999eb0..88d0cd63f7 100644
--- a/dependency-injection/cs/passing-dependencies.texy
+++ b/dependency-injection/cs/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Problém nastane v okamžiku, kdy budeme chtít změnit kontruktor třídy `BaseClass`, třeba když přibude nová závislost. Pak je totiž nutné upravit také všechny konstruktory potomků. Což z takové úpravy dělá peklo.
 
-Jak tomu předcházet? Řešením je **dávat přednost kompozici před dědičností.**
+Jak tomu předcházet? Řešením je **dávat přednost [kompozici před dědičností|faq#Proč se upřednostňuje kompozice před dědičností]**.
 
-Tedy navrhneme kód jinak. Budeme se vyhýbat abstraktním `Base*` třídám. Místo toho, aby `MyClass` získávala určitou funkčnost tím, že dědí od `BaseClass`, si tuto funkčnost nechá předat jako závislost:
+Tedy navrhneme kód jinak. Budeme se vyhýbat [abstraktním|nette:introduction-to-object-oriented-programming#abstraktni-tridy] `Base*` třídám. Místo toho, aby `MyClass` získávala určitou funkčnost tím, že dědí od `BaseClass`, si tuto funkčnost nechá předat jako závislost:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ Volání setteru definujeme v konfiguraci DI kontejneru v [klíči setup |servic
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Nastavení proměnné definujeme v konfiraci DI kontejneru v [sekci setup |servi
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy
index 52e3a357ea..1a6d98c136 100644
--- a/dependency-injection/cs/services.texy
+++ b/dependency-injection/cs/services.texy
@@ -2,32 +2,32 @@ Definování služeb
 *****************
 
 .[perex]
-Konfigurace je místem, kam umísťujeme definice vlastních služeb. Slouží k tomu sekce `services`.
+Konfigurace je místem, kde učíme DI kontejner, jak má sestavovat jednotlivé služby a jak je propojovat s dalšími závislostmi. Nette poskytuje velice přehledný a elegantní způsob, jak toho dosáhnout.
 
-Například takto vytvoříme službu pojmenovanou `database`, což bude instance třídy `PDO`:
+Sekce `services` v konfiguračním souboru formátu NEON je místem, kde definujeme vlastní služby a jejich konfigurace. Podívejme se na jednoduchý příklad definice služby pojmenované `database`, která reprezentuje instanci 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:
+Uvedená konfigurace vyústí v následující tovární metodu v [DI kontejneru|container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  #  anonymní služba
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-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:`.
+Názvy služeb nám umožňují odkazovat se na ně v dalších částech konfiguračního souboru, a to ve formátu `@nazevSluzby`. Pokud není potřeba službu pojmenovávat, můžeme jednoduše použít pouze odrážku:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Službu poté získáme z DI kontejneru metodou `getService()` podle názvu, nebo ještě lépe metodou `getByType()` podle typu:
+Pro získání služby z DI kontejneru můžeme využít metodu `getService()` s názvem služby jako parametrem, nebo metodu `getByType()` s typem služby:
 
 ```php
 $database = $container->getService('database');
@@ -38,233 +38,111 @@ $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:
+Většinou vytváříme službu jednoduše tím, že vytvoříme instanci určité třídy. Například:
 
 ```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`:
+Pokud potřebujeme konfiguraci rozšířit o další klíče, lze definici rozepsat do více řádků:
 
 ```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)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Odpovídá PHP kódu:
+Klíč `create` má alias `factory`, obě varianty jsou v praxi běžné. Nicméně doporučujeme používat `create`.
 
-```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:
+Argumenty konstruktoru nebo vytvářecí metody mohou být alternativně zapsány v klíči `arguments`:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-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á `::`
+Služby nemusí být vytvářeny jen prostým vytvořením instance třídy, mohou být také výsledkem volání statických metod nebo metod jiných služeb:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Odpovídá PHP kódu:
+Všimněte si, že pro jednoduchost se místo `->` používá `::`, viz [#výrazové prostředky]. Vygenerují se tyto tovární metody:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-Volání metod lze řetězit za sebe stejně jako v PHP:
+DI kontejner potřebuje znát typ vytvořené služby. Pokud vytváříme službu pomocí metody, která nemá specifikovaný návratový typ, musíme tento typ explicitně uvést v konfiguraci:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Odpovídá PHP kódu:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argumenty
 =========
 
-Pro předání argumentů lze používat i pojmenované parametry:
+Do konstruktoru a metod předáváme argumenty způsobem velmi podobným jako v samotném PHP:
 
 ```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'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-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:
+Pro lepší čitelnost můžeme argumenty rozepsat do samostatných řádků. V takovém případě je používání čárek volitelné:
 
 ```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(NetteMode)                  # volání globální funkce
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-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('NetteMode')
-	);
-}
-```
-
-
-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
+Argumenty můžete také pojmenovat a nemusíte se pak starat o jejich pořadí:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-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.
+Pokud chcete některé argumenty vynechat a použít jejich výchozí hodnotu nebo dosadit službu pomocí [autowiringu|autowiring], použijte podtržítko:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-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)
-```
+Jako argumenty lze předávat služby, používat parametry a mnohem více, viz [#výrazové prostředky].
 
 
 Setup
 =====
 
-V sekci setup uvádíme metody, které se mají zavolat při vytváření služby:
+V sekci `setup` definujeme metody, které se mají volat při vytváření služby.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Odpovídá PHP kódu:
+To by v PHP vypadalo takto:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-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:
-
+Kromě volání metod lze také předávat hodnoty do properties. 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:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Odpovídá PHP kódu:
+Což by v PHP kódu vypadalo následovně:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-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`:
-
+V setupu lze však volat i statické metody nebo metody jiných služeb. Pokud potřebujete předat jako argument aktuální službu, uveďte ji jako `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Odpovídá PHP kódu:
+Všimněte si, že pro jednoduchost se místo `->` používá `::`, viz [#výrazové prostředky]. Vygeneruje se taková tovární metoda:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,10 +210,127 @@ public function createServiceFoo(): Foo
 ```
 
 
+Výrazové prostředky
+===================
+
+Nette DI nám dává mimořádně bohaté výrazové prostředky, pomocí kterých můžeme zapsat téměř cokoliv. V konfiguračních souborech tak můžeme využívat [parametry|configuration#parametry]:
+
+```neon
+# parametr
+%wwwDir%
+
+# hodnota parametru pod klíčem
+%mailer.user%
+
+# parametr uvnitř řetězce
+'%wwwDir%/images'
+```
+
+Dále vytvářet objekty, volat metody a funkce:
+
+```neon
+# vytvoření objektu
+DateTime()
+
+# volání statické metody
+Collator::create(%locale%)
+
+# volání PHP funkce
+::getenv(DB_USER)
+```
+
+Odkazovat se na služby buď jejich jménem nebo pomocí typu:
+
+```neon
+# služba dle názvu
+@database
+
+# služba dle typu
+@Nette\Database\Connection
+```
+
+Používat first-class callable syntax: .{data-version:3.2.0}
+
+```neon
+# vytvoření callbacku, obdoba [@user, logout]
+@user::logout(...)
+```
+
+Používat konstanty:
+
+```neon
+# konstanta třídy
+FilesystemIterator::SKIP_DOTS
+
+# globální konstantu získáme PHP funkcí constant()
+::constant(PHP_VERSION)
+```
+
+Volání metod lze řetězit stejně jako v PHP. Jen pro jednoduchost se místo `->` používá `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Tyto výrazy můžete používat kdekoliv, při [vytváření služeb |#Vytvoření služby], v [argumentech |#Argumenty], v sekci [#setup] nebo [parametrech|configuration#parametry]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Speciální funkce
+----------------
+
+V konfiguračních souborech můžete používa tyto speciální funkce:
+
+- `not()` negace hodnoty
+- `bool()`, `int()`, `float()`, `string()` bezeztrátové přetypování na daný typ
+- `typed()` vytvoří pole všech služeb specifikovaného typu
+- `tagged()` vytvoření pole všech služeb s daným tagem
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+Oproti klasickému přetypování v PHP, jako je např. `(int)`, bezeztrátové přetypování vyhodí výjimku pro nečíselné hodnoty.
+
+Funkce `typed()` vytvoří pole všech služeb daného typu (třída nebo rozhraní). Vynechá služby, které mají vypnutý autowiring. Lze uvést i více typů oddělených čárkou.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+Pole služeb určitého typu můžete předávat jako argument také automaticky pomocí [autowiringu|autowiring#Pole služeb].
+
+Funkce `tagged()` pak vytváří pole všech služeb s určitým tagem. I zde můžete specifikovat více tagů oddělených čárkou.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
 Autowiring
 ==========
 
-Pomocí klíče autowired lze službu vyřadit z autowiringu nebo jeho chování ovlivnit. Více v [kapitole o autowiringu|autowiring].
+Klíč `autowired` umožňuje ovlivnit chování autowiringu pro konkrétní službu. Pro detaily viz [kapitola o autowiringu|autowiring].
 
 ```neon
 services:
@@ -350,7 +343,7 @@ services:
 Tagy
 ====
 
-Jednotlivým službám lze přidávat uživatelské informace v podobě tzv. tagů:
+Tagy slouží k přidání doplňujících informací k službám. Službě můžete přidat jeden nebo více tagů:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Tagy mohou mít i hodnotu:
+Tagy mohou také nést hodnoty:
 
 ```neon
 services:
@@ -370,14 +363,14 @@ services:
 			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.
+Aby jste získali všechny služby s určitými tagy, můžete použít funkci `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Názvy služeb lze získat z DI kontejneru metodou `findByTag()`:
+V DI kontejneru můžete získat názvy všech služeb s určitým tagem pomocí metody `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
@@ -398,13 +391,13 @@ services:
 		inject: true
 ```
 
-V základním nastavení je `inject` aktivováno pouze pro presentery.
+Ve výchozí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:
+DI kontejner obsahuje mnoho služeb, které byly přidány prostřednictvím vestavěného nebo [uživatelského rozšíření|#rozšíření]. Můžete upravit definice těchto služeb přímo v konfiguraci. Například můžete změnit třídu služby `application.application`, což je standardně `Nette\Application\Application`, na jinou:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Službu přidanou rozšířením lze také z kontejneru odstranit:
+Pokud chcete odstranit službu přidanou rozšířením, můžete to udělat takto:
 
 ```neon
 services:
diff --git a/dependency-injection/de/autowiring.texy b/dependency-injection/de/autowiring.texy
index b5af4bf042..9d10e2249d 100644
--- a/dependency-injection/de/autowiring.texy
+++ b/dependency-injection/de/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Der DI-Container übergibt dann automatisch ein Array von Diensten, die dem angegebenen Typ entsprechen. Er wird Dienste auslassen, bei denen die automatische Verdrahtung ausgeschaltet ist.
 
-Wenn Sie die Form des phpDoc-Kommentars nicht kontrollieren können, können Sie ein Array von Diensten direkt in der Konfiguration übergeben, indem Sie [`typed()` |services#Special Functions].
+Der Typ des Kommentars kann auch in der Form `array<int, Class>` oder `list<Class>`. Wenn Sie die Form des phpDoc-Kommentars nicht kontrollieren können, können Sie ein Array von Diensten direkt in der Konfiguration übergeben, indem Sie [`typed()` |services#Special Functions].
 
 
 Skalar-Argumente .[#toc-scalar-arguments]
diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy
index 897d0a2df3..81e37a18f5 100644
--- a/dependency-injection/de/configuration.texy
+++ b/dependency-injection/de/configuration.texy
@@ -67,7 +67,7 @@ Wie kann man alle Dienste eines bestimmten Typs als Ganzes bearbeiten? Müssen S
 ```neon
 decorator:
 	# für alle Dienste, die Instanzen dieser Klasse oder Schnittstelle sind
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # diese Methode aufrufen
 			- $absoluteUrls = true # und setze die Variable
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Wenn Sie das Array `$container->parameters` nicht verwenden, können Sie den Export der Parameter deaktivieren. Außerdem können Sie nur die Tags exportieren, über die Sie mit der Methode `$container->findByTag(...)` Dienste erhalten.
+Wenn Sie das Array `$container->getParameters()` nicht verwenden, können Sie den Export der Parameter deaktivieren. Außerdem können Sie nur die Tags exportieren, über die Sie mit der Methode `$container->findByTag(...)` Dienste erhalten.
 Wenn Sie die Methode gar nicht aufrufen, können Sie den Tag-Export mit `false` vollständig deaktivieren.
 
 Sie können die Metadaten für die [automatische Verdrahtung |autowiring] erheblich reduzieren, indem Sie die von Ihnen verwendeten Klassen als Parameter für die Methode `$container->getByType()` angeben.
@@ -191,20 +191,15 @@ Geben Sie einfach an, in welchen Verzeichnissen (und Unterverzeichnissen) nach d
 
 ```neon
 Suche:
-	# Sie wählen die Namen der Abschnitte selbst
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Normalerweise wollen wir jedoch nicht alle Klassen und Schnittstellen hinzufügen, so dass wir sie filtern können:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# Filtern nach Dateinamen (string|string[])
 		files:
@@ -220,7 +215,7 @@ Oder wir können Klassen auswählen, die mindestens eine der folgenden Klassen e
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Sie können auch negative Regeln definieren, z. B. Klassennamensmasken oder Vorf
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+Dateien: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Für hinzugefügte Dienste können Tags gesetzt werden:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/de/container.texy b/dependency-injection/de/container.texy
index 6befd33d9c..610d1f62e5 100644
--- a/dependency-injection/de/container.texy
+++ b/dependency-injection/de/container.texy
@@ -44,7 +44,7 @@ Wir fragen den Container einfach nach dem Objekt und müssen nicht mehr wissen,
 Bis jetzt hat der Container alles hart kodiert. Wir gehen also den nächsten Schritt und fügen Parameter hinzu, um den Container wirklich nützlich zu machen:
 
 ```php
-Klasse Container
+class Container
 {
 	public function __construct(
 		private array $parameters,
@@ -75,7 +75,7 @@ Aufmerksame Leser haben vielleicht ein Problem bemerkt. Jedes Mal, wenn ich ein
 Also fügen wir eine Methode `getService()` hinzu, die immer wieder die gleichen Instanzen zurückgibt:
 
 ```php
-Klasse Container
+class container
 {
 	private array $services = [];
 
@@ -103,7 +103,7 @@ Beim ersten Aufruf von z.B. `$container->getService('Database')` wird `createDat
 Wir ändern auch den Rest des Containers, um `getService()` zu verwenden:
 
 ```php
-Klasse Container
+class Container
 {
 	// ...
 
@@ -134,6 +134,6 @@ $controller = $container->getService('UserController');
 $database = $container->getService('Database');
 ```
 
-Wie Sie sehen können, ist es nicht schwer, ein DIC zu schreiben. Bemerkenswert ist, dass die Objekte selbst nicht wissen, dass sie von einem Container erstellt werden. Es ist also möglich, jedes beliebige Objekt in PHP auf diese Weise zu erstellen, ohne den Quellcode zu verändern.
+Wie Sie sehen können, ist es nicht schwer, einen DIC zu schreiben. Bemerkenswert ist, dass die Objekte selbst nicht wissen, dass sie von einem Container erstellt werden. Es ist also möglich, jedes beliebige Objekt in PHP auf diese Weise zu erstellen, ohne den Quellcode zu verändern.
 
 Die manuelle Erstellung und Pflege einer Containerklasse kann schnell zu einem Alptraum werden. Deshalb werden wir im nächsten Kapitel über [Nette DI Container |nette-container] sprechen, die sich fast automatisch erzeugen und aktualisieren können.
diff --git a/dependency-injection/de/extensions.texy b/dependency-injection/de/extensions.texy
index 9761299aa9..1652d8881c 100644
--- a/dependency-injection/de/extensions.texy
+++ b/dependency-injection/de/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $Initialisierung .[wiki-method]
 ===============================
 
-Der Configurator ruft den Initialisierungscode nach der [Erstellung des Containers |application:bootstrap#index.php] auf, der durch Schreiben in ein Objekt `$this->initialization` mit der [Methode addBody() |php-generator:#method-and-function-body] erzeugt wird.
+Der Configurator ruft den Initialisierungscode nach der [Erstellung des Containers |application:bootstrap#index.php] auf, der durch Schreiben in ein Objekt `$this->initialization` mit der [Methode addBody() |php-generator:#method-and-function-bodies] erzeugt wird.
 
 Wir werden ein Beispiel zeigen, wie man eine Session oder Dienste mit dem Tag `run` unter Verwendung des Initialisierungscodes startet:
 
diff --git a/dependency-injection/de/factory.texy b/dependency-injection/de/factory.texy
index e0381a449d..2ff999d106 100644
--- a/dependency-injection/de/factory.texy
+++ b/dependency-injection/de/factory.texy
@@ -170,39 +170,45 @@ Bisher konnten die Fabriken und Accessoren nur ein einziges Objekt erstellen ode
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Anstatt mehrere generierte Fabriken und Accessoren zu übergeben, können Sie nur eine komplexe Multifabrik übergeben.
 
-Alternativ können Sie auch `create()` und `get()` mit einem Parameter anstelle mehrerer Methoden verwenden:
+Alternativ können Sie auch `get()` mit einem Parameter anstelle von mehreren Methoden verwenden:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-In diesem Fall bewirkt `MultiFactory::createArticle()` das Gleiche wie `MultiFactoryAlt::create('article')`. Die alternative Syntax hat jedoch einige Nachteile. Es ist nicht klar, welche `$name` Werte unterstützt werden und der Rückgabetyp kann nicht in der Schnittstelle angegeben werden, wenn mehrere verschiedene `$name` Werte verwendet werden.
+In diesem Fall bewirkt `MultiFactory::getArticle()` dasselbe wie `MultiFactoryAlt::get('article')`. Die alternative Syntax hat jedoch einige Nachteile. Es ist nicht klar, welche `$name` Werte unterstützt werden, und der Rückgabetyp kann nicht in der Schnittstelle angegeben werden, wenn mehrere verschiedene `$name` Werte verwendet werden.
 
 
 Definition mit einer Liste .[#toc-definition-with-a-list]
 ---------------------------------------------------------
-Wie definieren Sie eine Multifabrik in Ihrer Konfiguration? Lassen Sie uns drei Dienste erstellen, die von der Multifabrik zurückgegeben werden, und die Multifabrik selbst:
+Auf diese Weise können Sie in der Konfiguration eine Mehrfachfabrik definieren: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Oder wir können in der Fabrikdefinition auf bestehende Dienste mit einer Referenz verweisen:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Eine weitere Möglichkeit, eine Multifabrik zu definieren, ist die Verwendung vo
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/de/faq.texy b/dependency-injection/de/faq.texy
index 0a4279f61e..088c073489 100644
--- a/dependency-injection/de/faq.texy
+++ b/dependency-injection/de/faq.texy
@@ -61,7 +61,7 @@ Denken Sie daran, dass der Wechsel zu Dependency Injection eine Investition in d
 
 Warum ist Komposition der Vererbung vorzuziehen? .[#toc-why-composition-is-preferred-over-inheritance]
 ------------------------------------------------------------------------------------------------------
-Die Komposition ist der Vererbung vorzuziehen, da sie die Wiederverwendbarkeit des Codes ermöglicht, ohne dass man sich um die Auswirkungen von Änderungen sorgen muss. Dadurch wird eine lockerere Kopplung erreicht, bei der wir uns keine Sorgen machen müssen, dass die Änderung eines Codes dazu führt, dass ein anderer abhängiger Code geändert werden muss. Ein typisches Beispiel ist die Situation, die als [Konstruktorhölle |passing-dependencies#Constructor hell] bezeichnet wird.
+Die [Komposition |nette:introduction-to-object-oriented-programming#composition] ist der [Vererbung |nette:introduction-to-object-oriented-programming#inheritance] vorzuziehen, da sie die Wiederverwendung von Code ermöglicht, ohne dass man sich über die Folgen von Änderungen Gedanken machen muss. Sie bietet also eine lockerere Kopplung, bei der wir uns keine Sorgen machen müssen, dass die Änderung eines Codes die Notwendigkeit mit sich bringt, anderen abhängigen Code zu ändern. Ein typisches Beispiel ist eine Situation, die als [Konstruktorhölle |passing-dependencies#Constructor hell] bezeichnet wird.
 
 
 Kann Nette DI Container auch außerhalb von Nette verwendet werden? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/de/global-state.texy b/dependency-injection/de/global-state.texy
index 4df2cdc0ec..488839bea8 100644
--- a/dependency-injection/de/global-state.texy
+++ b/dependency-injection/de/global-state.texy
@@ -301,4 +301,4 @@ Wenn Sie über den Entwurf von Code nachdenken, sollten Sie bedenken, dass jedes
 
 Während dieses Prozesses kann es vorkommen, dass Sie eine Klasse aufteilen müssen, weil sie mehr als eine Verantwortung hat. Machen Sie sich keine Gedanken darüber; streben Sie das Prinzip der einen Verantwortung an.
 
-*Ich möchte Miško Hevery danken, dessen Artikel wie [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] die Grundlage für dieses Kapitel bilden.*
+*Ich möchte Miško Hevery danken, dessen Artikel wie [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] die Grundlage für dieses Kapitel bilden.*
diff --git a/dependency-injection/de/passing-dependencies.texy b/dependency-injection/de/passing-dependencies.texy
index c5111a38be..0a1208ca75 100644
--- a/dependency-injection/de/passing-dependencies.texy
+++ b/dependency-injection/de/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Das Problem tritt auf, wenn wir den Konstruktor der Klasse `BaseClass` ändern wollen, zum Beispiel wenn eine neue Abhängigkeit hinzugefügt wird. Dann müssen wir auch alle Konstruktoren der Kinder ändern. Das macht eine solche Änderung zur Hölle.
 
-Wie lässt sich das verhindern? Die Lösung besteht darin, **Komposition gegenüber Vererbung** zu bevorzugen.
+Wie kann man dies verhindern? Die Lösung besteht darin, [**Zusammensetzung gegenüber Vererbung** |faq#Why composition is preferred over inheritance] zu bevorzugen.
 
-Lassen Sie uns also den Code anders gestalten. Wir werden abstrakte `Base*` Klassen vermeiden. Anstatt dass `MyClass` eine bestimmte Funktionalität durch Vererbung von `BaseClass` erhält, wird diese Funktionalität als Abhängigkeit übergeben:
+Lassen Sie uns also den Code anders gestalten. Wir werden [abstrakte |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` Klassen vermeiden. Anstatt dass `MyClass` einige Funktionen durch Vererbung von `BaseClass` erhält, wird diese Funktionalität als Abhängigkeit übergeben:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ Der Setter-Aufruf wird in der DI-Container-Konfiguration im [Abschnitt setup |se
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Die Einstellung der Variablen wird in der Konfiguration des DI-Containers im [Ab
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/de/services.texy b/dependency-injection/de/services.texy
index f4659b138d..a02717a802 100644
--- a/dependency-injection/de/services.texy
+++ b/dependency-injection/de/services.texy
@@ -2,32 +2,32 @@ Dienst-Definitionen
 *******************
 
 .[perex]
-In der Konfiguration werden die Definitionen der benutzerdefinierten Dienste abgelegt. Dies geschieht im Abschnitt `services`.
+Die Konfiguration ist der Ort, an dem wir den DI-Container anweisen, wie er die einzelnen Dienste zusammenstellen und mit anderen Abhängigkeiten verbinden soll. Nette bietet eine sehr klare und elegante Möglichkeit, dies zu erreichen.
 
-So erstellen wir zum Beispiel einen Dienst namens `database`, der eine Instanz der Klasse `PDO` sein wird:
+Der Abschnitt `services` in der NEON-Konfigurationsdatei ist der Ort, an dem wir unsere benutzerdefinierten Dienste und deren Konfigurationen definieren. Schauen wir uns ein einfaches Beispiel für die Definition eines Dienstes namens `database` an, der eine Instanz der Klasse `PDO` darstellt:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Die Benennung von Diensten dient dazu, dass wir auf sie [verweisen |#Referencing Services] können. Wenn ein Dienst nicht referenziert wird, ist es nicht notwendig, ihn zu benennen. Wir verwenden also einfach einen Aufzählungspunkt anstelle eines Namens:
+Diese Konfiguration führt zu der folgenden Fabrikmethode im [DI-Container |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # anonymer Dienst
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Ein einzeiliger Eintrag kann in mehrere Zeilen aufgeteilt werden, um weitere Schlüssel hinzuzufügen, wie z. B. [setup |#setup]. Der Alias für die Taste `create:` lautet `factory:`.
+Dienstnamen ermöglichen es uns, in anderen Teilen der Konfigurationsdatei auf sie zu verweisen, indem wir das Format `@serviceName` verwenden. Wenn es nicht notwendig ist, den Dienst zu benennen, können wir einfach einen Aufzählungspunkt verwenden:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Anschließend rufen wir den Dienst aus dem DI-Container mit der Methode `getService()` nach dem Namen oder besser noch mit der Methode `getByType()` nach dem Typ ab:
+Um einen Dienst aus dem DI-Container abzurufen, können wir die Methode `getService()` mit dem Dienstnamen als Parameter oder die Methode `getByType()` mit dem Diensttyp verwenden:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Erstellen eines Dienstes .[#toc-creating-a-service]
-===================================================
+Erstellung von Diensten .[#toc-service-creation]
+================================================
 
-Meistens erstellen wir einen Dienst, indem wir einfach eine Instanz einer Klasse erstellen:
+In den meisten Fällen wird ein Dienst einfach durch die Instanziierung einer bestimmten Klasse erstellt. Zum Beispiel:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Dadurch wird eine Fabrikmethode im [DI-Container |container] erzeugt:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Alternativ kann auch ein Schlüssel `arguments` verwendet werden, um [Argumente |#Arguments] zu übergeben:
+Wenn wir die Konfiguration um zusätzliche Schlüssel erweitern müssen, kann die Definition in mehrere Zeilen aufgeteilt werden:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-Eine statische Methode kann auch einen Dienst erstellen:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Entspricht dem PHP-Code:
+Der Schlüssel `create` hat einen Alias `factory`, beide Versionen sind in der Praxis üblich. Wir empfehlen jedoch die Verwendung von `create`.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-Bei einer statischen Methode `My\Database::create()` wird davon ausgegangen, dass sie einen definierten Rückgabewert hat, den der DI-Container kennen muss. Ist dies nicht der Fall, schreiben wir den Typ in die Konfiguration:
+Konstruktorargumente oder die Erstellungsmethode können alternativ in den Schlüssel `arguments` geschrieben werden:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Nette DI gibt Ihnen extrem leistungsfähige Ausdrucksmöglichkeiten, um fast alles zu schreiben. Zum Beispiel, um auf einen anderen Dienst zu [verweisen |#Referencing Services] und seine Methode aufzurufen. Der Einfachheit halber wird `::` anstelle von `->` verwendet.
+Dienste müssen nicht nur durch einfache Instanziierung einer Klasse erzeugt werden, sondern können auch durch den Aufruf statischer Methoden oder Methoden anderer Dienste entstehen:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Entspricht dem PHP-Code:
+Beachten Sie, dass wir der Einfachheit halber anstelle von `->` `::` verwenden, siehe [Ausdrucksmittel |#expression means]. Diese Fabrikmethoden werden generiert:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-Methodenaufrufe können wie in PHP aneinandergereiht werden:
+Der DI-Container muss den Typ des erzeugten Dienstes kennen. Wenn wir einen Dienst mit einer Methode erstellen, die keinen bestimmten Rückgabetyp hat, müssen wir diesen Typ in der Konfiguration explizit angeben:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Entspricht dem PHP-Code:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argumente .[#toc-arguments]
 ===========================
 
-Benannte Parameter können auch zur Übergabe von Argumenten verwendet werden:
+Wir übergeben Argumente an Konstruktoren und Methoden auf eine Weise, die der von PHP sehr ähnlich ist:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # positional
-		username: root                      # named
-		password: secret                    # named
-	)
-```
-
-Die Verwendung von Kommas ist optional, wenn Argumente in mehrere Zeilen aufgeteilt werden.
-
-Natürlich können wir auch [andere Dienste |#Referencing Services] oder [Parameter |configuration#parameters] als Argumente verwenden:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-Entspricht dem PHP-Code:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Wenn das erste Argument [autowired |autowiring] ist und Sie das zweite angeben wollen, lassen Sie das erste mit `_` character, for example `Foo(_, %appDir%)` weg. Oder noch besser, übergeben Sie nur das zweite Argument als benannten Parameter, z. B. `Foo(path: %appDir%)`.
-
-Nette DI und das NEON-Format geben Ihnen extrem leistungsfähige Ausdrucksmöglichkeiten, um fast alles zu schreiben. So kann ein Argument ein neu erstelltes Objekt sein, Sie können statische Methoden, Methoden anderer Dienste oder sogar globale Funktionen unter Verwendung einer speziellen Notation aufrufen:
+Zur besseren Lesbarkeit können wir die Argumente in separaten Zeilen auflisten. In diesem Format ist die Verwendung von Kommas optional:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)        # Objekt erstellen
-		DateTime::createFromFormat('Y-m-d') # statische Methode aufrufen
-		@anotherService                     # Übergabe eines anderen Dienstes
-		@http.request::getRemoteAddress()   # Aufruf einer anderen Dienstmethode
-		::getenv(NetteMode)                 # Aufruf einer globalen Funktion
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-Entspricht dem 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('NetteMode')
-	);
-}
-```
-
-
-Spezielle Funktionen .[#toc-special-functions]
-----------------------------------------------
-
-Sie können auch spezielle Funktionen in Argumenten verwenden, um Werte zu casten oder zu negieren:
-
-- `not(%arg%)` negation
-- `bool(%arg%)` verlustfreie Umwandlung in bool
-- `int(%arg%)` verlustfreie Umwandlung in int
-- `float(%arg%)` verlustfreie Umwandlung in float
-- `string(%arg%)` lossless cast to string
+Sie können die Argumente auch benennen, dann brauchen Sie sich nicht um ihre Reihenfolge zu kümmern:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-Verlustfreies Rewriting unterscheidet sich von normalem PHP Rewriting, z.B. mit `(int)`, dadurch, dass es eine Ausnahme für nicht-numerische Werte auslöst.
-
-Es können mehrere Dienste als Argumente übergeben werden. Ein Array mit allen Diensten eines bestimmten Typs (d.h. Klasse oder Schnittstelle) wird von der Funktion `typed()` erstellt. Die Funktion lässt Dienste aus, bei denen die automatische Verdrahtung deaktiviert ist, und es können mehrere Typen durch ein Komma getrennt angegeben werden.
+Wenn Sie bestimmte Argumente auslassen und ihre Standardwerte verwenden oder einen Dienst über die [automatische Verdrahtung |autowiring] einfügen möchten, verwenden Sie einen Unterstrich:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-Sie können ein Array von Diensten auch automatisch mit [Autowiring |autowiring#Collection of Services] übergeben.
-
-Ein Array mit allen Diensten mit einem bestimmten [Tag |#tags] wird mit der Funktion `tagged()` erstellt. Es können mehrere Tags durch ein Komma getrennt angegeben werden.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Referenzierungsdienste .[#toc-referencing-services]
-===================================================
-
-Die einzelnen Dienste werden mit dem Zeichen `@` and name, so for example `@database` referenziert:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-Entspricht dem PHP-Code:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Auch anonyme Dienste können über einen Callback referenziert werden, man muss nur ihren Typ (Klasse oder Schnittstelle) anstelle ihres Namens angeben. Dies ist jedoch aufgrund der [automatischen Verdrahtung |autowiring] normalerweise nicht erforderlich.
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection) # oder @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Argumente können Dienste, Parameter und vieles mehr sein, siehe [Ausdrucksmittel |#expression means].
 
 
 Einrichtung .[#toc-setup]
 =========================
 
-Im Abschnitt "Setup" werden die Methoden aufgeführt, die bei der Erstellung des Dienstes aufgerufen werden müssen:
+Im Abschnitt `setup` definieren wir die Methoden, die bei der Erstellung des Dienstes aufgerufen werden sollen.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Entspricht dem PHP-Code:
+In PHP würde dies wie folgt aussehen:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-Properites können auch gesetzt werden. Das Hinzufügen eines Elements zu einem Array wird ebenfalls unterstützt und sollte in Anführungszeichen geschrieben werden, um nicht mit der NEON-Syntax in Konflikt zu geraten:
-
+Zusätzlich zu Methodenaufrufen können Sie auch Werte an Eigenschaften übergeben. Das Hinzufügen eines Elements zu einem Array wird ebenfalls unterstützt, aber Sie müssen es in Anführungszeichen setzen, um Kollisionen mit der NEON-Syntax zu vermeiden:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Entspricht dem PHP-Code:
+In PHP würde dies bedeuten:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-Es können aber auch statische Methoden oder Methoden anderer Dienste im Setup aufgerufen werden. Wir übergeben ihnen den eigentlichen Dienst als `@self`:
-
+Im Setup können Sie auch statische Methoden oder Methoden von anderen Diensten aufrufen. Wenn Sie den aktuellen Dienst als Argument übergeben müssen, verwenden Sie `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Entspricht dem PHP-Code:
+Beachten Sie, dass wir der Einfachheit halber anstelle von `->` `::` verwenden, siehe [Ausdrucksmittel |#expression means]. Dies erzeugt die folgende Fabrikmethode:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
-Autowiring .[#toc-autowiring]
-=============================
+Ausdrucksmittel .[#toc-expression-means]
+========================================
+
+Nette DI bietet uns außergewöhnlich reichhaltige Ausdrucksmöglichkeiten, die es uns erlauben, fast alles zu artikulieren. In Konfigurationsdateien können wir [Parameter |configuration#parameters] verwenden:
+
+```neon
+# Parameter
+%wwwDir%
+
+# Wert unter einem Parameterschlüssel
+%mailer.user%
+
+# Parameter innerhalb einer Zeichenkette
+'%wwwDir%/images'
+```
+
+Wir können auch Objekte erstellen, Methoden und Funktionen aufrufen:
+
+```neon
+# ein Objekt erstellen
+DateTime()
+
+# eine statische Methode aufrufen
+Collator::create(%locale%)
+
+# eine PHP-Funktion aufrufen
+::getenv(DB_USER)
+```
+
+Beziehen Sie sich auf Dienste entweder durch ihren Namen oder durch ihren Typ:
+
+```neon
+# Dienst nach Name
+@database
+
+# Dienst nach Typ
+@Nette\Database\Connection
+```
+
+Verwenden Sie die Syntax von First-Class Callables: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Verwenden Sie Konstanten:
+
+```neon
+# Klassenkonstante
+FilesystemIterator::SKIP_DOTS
+
+# globale Konstante, die mit der PHP-Funktion constant() ermittelt wird
+::constant(PHP_VERSION)
+```
+
+Methodenaufrufe können, genau wie in PHP, verkettet werden. Der Einfachheit halber verwenden wir anstelle von `->` `::` :
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Diese Ausdrücke können bei der [Erstellung von Diensten |#Service Creation] überall verwendet werden, in [Argumenten |#Arguments], im [Setup-Abschnitt |#setup] oder in [Parametern |configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Besondere Funktionen .[#toc-special-functions]
+----------------------------------------------
+
+Innerhalb von Konfigurationsdateien können Sie diese speziellen Funktionen verwenden:
+
+- `not()` für die Negation von Werten
+- `bool()`, `int()`, `float()`, `string()` für verlustfreies Type Casting
+- `typed()` um ein Array mit allen Diensten eines bestimmten Typs zu erzeugen
+- `tagged()`, um ein Array aller Dienste mit einem bestimmten Tag zu erzeugen
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+Im Vergleich zum konventionellen Typecasting in PHP, wie z.B. `(int)`, wird beim verlustfreien Typecasting eine Exception für nicht-numerische Werte geworfen.
+
+Die Funktion `typed()` erstellt ein Array mit allen Diensten eines bestimmten Typs (Klasse oder Schnittstelle). Sie schließt Dienste mit ausgeschaltetem Autowiring aus. Es können mehrere Typen angegeben werden, getrennt durch Kommas.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+Sie können auch automatisch ein Array von Diensten eines bestimmten Typs als Argument übergeben, indem Sie [autowiring |autowiring#Collection of Services] verwenden.
+
+Die Funktion `tagged()` erstellt ein Array mit allen Diensten mit einem bestimmten Tag. Es können mehrere Tags aufgelistet werden, getrennt durch Kommas.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
+Fahrzeugverkabelung .[#toc-autowiring]
+======================================
 
-Der Autowiring-Schlüssel kann verwendet werden, um einen Dienst vom Autowiring auszuschließen oder um sein Verhalten zu beeinflussen. Weitere Informationen finden Sie im [Kapitel über Autowiring |autowiring].
+Mit der Taste `autowired` können Sie das Autowiring-Verhalten für einen bestimmten Dienst ändern. Weitere Einzelheiten finden Sie im [Kapitel über die automatische Verdrahtung |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # foo wird aus der automatischen Verdrahtung entfernt
+		autowired: false     # der Foo-Dienst ist vom Autowiring ausgeschlossen
 ```
 
 
 Tags .[#toc-tags]
 =================
 
-Benutzerinformationen können den einzelnen Diensten in Form von Tags hinzugefügt werden:
+Tags werden verwendet, um zusätzliche Informationen zu Diensten hinzuzufügen. Sie können einem Dienst ein oder mehrere Tags zuweisen:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Tags können auch einen Wert haben:
+Tags können auch Werte enthalten:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Ein Array von Diensten mit bestimmten Tags kann mit der Funktion `tagged()` als Argument übergeben werden. Es können auch mehrere Tags durch ein Komma getrennt angegeben werden.
+Um alle Dienste mit bestimmten Tags abzurufen, können Sie die Funktion `tagged()` verwenden:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Dienstnamen können mit der Methode `findByTag()` aus dem DI-Container bezogen werden:
+Im DI-Container können Sie mit der Methode `findByTag()` die Namen aller Dienste mit einem bestimmten Tag abrufen:
 
 ```php
 $names = $container->findByTag('logger');
 // $names ist ein Array, das den Dienstnamen und den Tag-Wert enthält
-// d.h. ['foo' => 'monolog.logger.event', ...]
+// z.B. ['foo' => 'monolog.logger.event', ...]
 ```
 
 
 Injektionsmodus .[#toc-inject-mode]
 ===================================
 
-Das Flag `inject: true` wird verwendet, um die Übergabe von Abhängigkeiten über öffentliche Variablen mit der [inject-Annotation |best-practices:inject-method-attribute#Inject Attributes] und den [inject*() |best-practices:inject-method-attribute#inject Methods] -Methoden zu aktivieren.
+Mit dem Flag `inject: true` wird die Übergabe von Abhängigkeiten über öffentliche Variablen mit der [inject-Annotation |best-practices:inject-method-attribute#Inject Attributes] und den [inject*() |best-practices:inject-method-attribute#inject Methods] -Methoden aktiviert.
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Standardmäßig ist `inject` nur für Präsentatoren aktiviert.
 
 
-Modifikation der Dienste .[#toc-modification-of-services]
-=========================================================
+Änderungen am Dienst .[#toc-service-modifications]
+==================================================
 
-Es gibt eine Reihe von Diensten im DI-Container, die durch eine eingebaute oder [Ihre Erweiterung |#di-extensions] hinzugefügt wurden. Die Definitionen dieser Dienste können in der Konfiguration geändert werden. Zum Beispiel kann für den Dienst `application.application`, der standardmäßig ein Objekt `Nette\Application\Application` ist, die Klasse geändert werden:
+Der DI-Container enthält viele Dienste, die entweder durch eingebaute oder [durch Benutzererweiterungen |#extensions] hinzugefügt wurden. Sie können die Definitionen dieser Dienste direkt in der Konfiguration ändern. So können Sie beispielsweise die Klasse des Dienstes `application.application`, die üblicherweise `Nette\Application\Application` lautet, in eine andere ändern:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Das Kennzeichen `alteration` ist informativ und besagt, dass wir nur einen bestehenden Dienst ändern.
+Das Kennzeichen `alteration` ist informativ und zeigt an, dass es sich lediglich um eine Änderung eines bestehenden Dienstes handelt.
 
-Wir können auch eine Einrichtung hinzufügen:
+Wir können die Einrichtung auch ergänzen:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Wenn wir einen Dienst neu schreiben, möchten wir vielleicht die ursprünglichen Argumente, Setup-Elemente oder Tags entfernen. Dafür ist `reset` gedacht:
+Wenn Sie einen Dienst überschreiben, möchten Sie vielleicht die ursprünglichen Argumente, Einrichtungselemente oder Tags entfernen, und hier kommt `reset` ins Spiel:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Ein durch eine Erweiterung hinzugefügter Dienst kann auch aus dem Container entfernt werden:
+Wenn Sie einen Dienst, der von einer Erweiterung hinzugefügt wurde, entfernen möchten, können Sie dies wie folgt tun:
 
 ```neon
 services:
diff --git a/dependency-injection/el/autowiring.texy b/dependency-injection/el/autowiring.texy
index eec1365d62..58aa89e25e 100644
--- a/dependency-injection/el/autowiring.texy
+++ b/dependency-injection/el/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Ο περιέκτης DI περνάει τότε αυτόματα έναν πίνακα υπηρεσιών που ταιριάζουν στον συγκεκριμένο τύπο. Θα παραλείψει τις υπηρεσίες που έχουν απενεργοποιήσει την αυτόματη καλωδίωση.
 
-Αν δεν μπορείτε να ελέγξετε τη μορφή του σχολίου phpDoc, μπορείτε να περάσετε έναν πίνακα υπηρεσιών απευθείας στη διαμόρφωση χρησιμοποιώντας την εντολή [`typed()` |services#Special Functions].
+Ο τύπος στο σχόλιο μπορεί επίσης να είναι της μορφής `array<int, Class>` ή `list<Class>`. Αν δεν μπορείτε να ελέγξετε τη μορφή του σχολίου phpDoc, μπορείτε να περάσετε έναν πίνακα υπηρεσιών απευθείας στη ρύθμιση παραμέτρων χρησιμοποιώντας την εντολή [`typed()` |services#Special Functions].
 
 
 Scalar Arguments .[#toc-scalar-arguments]
diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy
index c56264af03..2fb9c48458 100644
--- a/dependency-injection/el/configuration.texy
+++ b/dependency-injection/el/configuration.texy
@@ -67,7 +67,7 @@ parameters:
 ```neon
 decorator:
 	# για όλες τις υπηρεσίες που είναι στιγμιότυπα αυτής της κλάσης ή διεπαφής
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # καλέστε αυτή τη μέθοδο
 			- $absoluteUrls = true   # και ορίστε τη μεταβλητή
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Εάν δεν χρησιμοποιείτε τον πίνακα `$container->parameters`, μπορείτε να απενεργοποιήσετε την εξαγωγή παραμέτρων. Επιπλέον, μπορείτε να εξάγετε μόνο τις ετικέτες μέσω των οποίων λαμβάνετε υπηρεσίες χρησιμοποιώντας τη μέθοδο `$container->findByTag(...)`.
+Εάν δεν χρησιμοποιείτε τον πίνακα `$container->getParameters()`, μπορείτε να απενεργοποιήσετε την εξαγωγή παραμέτρων. Επιπλέον, μπορείτε να εξάγετε μόνο τις ετικέτες μέσω των οποίων λαμβάνετε υπηρεσίες χρησιμοποιώντας τη μέθοδο `$container->findByTag(...)`.
 Αν δεν καλείτε καθόλου τη μέθοδο, μπορείτε να απενεργοποιήσετε εντελώς την εξαγωγή ετικετών με τη μέθοδο `false`.
 
 Μπορείτε να μειώσετε σημαντικά τα μεταδεδομένα για την [αυτόματη καλωδίωση |autowiring], καθορίζοντας τις κλάσεις που χρησιμοποιείτε ως παράμετρο στη μέθοδο `$container->getByType()`.
@@ -191,20 +191,15 @@ return [
 
 ```neon
 search:
-	# επιλέγετε μόνοι σας τα ονόματα των τμημάτων
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Συνήθως, όμως, δεν θέλουμε να προσθέσουμε όλες τις κλάσεις και τις διεπαφές, οπότε μπορούμε να τις φιλτράρουμε:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# φιλτράρισμα με βάση το όνομα αρχείου (string|string[])
 		files:
@@ -220,7 +215,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+αρχεία: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/el/extensions.texy b/dependency-injection/el/extensions.texy
index 969759ea52..ac8a328055 100644
--- a/dependency-injection/el/extensions.texy
+++ b/dependency-injection/el/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialization .[wiki-method]
 ==============================
 
-Ο διαμορφωτής καλεί τον κώδικα αρχικοποίησης μετά τη [δημιουργία του περιέκτη |application:bootstrap#index.php], ο οποίος δημιουργείται με εγγραφή σε ένα αντικείμενο `$this->initialization` χρησιμοποιώντας τη [μέθοδο addBody() |php-generator:#method-and-function-body].
+Ο διαμορφωτής καλεί τον κώδικα αρχικοποίησης μετά τη [δημιουργία του περιέκτη |application:bootstrap#index.php], ο οποίος δημιουργείται με εγγραφή σε ένα αντικείμενο `$this->initialization` χρησιμοποιώντας τη [μέθοδο addBody() |php-generator:#method-and-function-bodies].
 
 Θα δείξουμε ένα παράδειγμα για το πώς να ξεκινήσετε μια συνεδρία ή να ξεκινήσετε υπηρεσίες που έχουν την ετικέτα `run` χρησιμοποιώντας κώδικα αρχικοποίησης:
 
diff --git a/dependency-injection/el/factory.texy b/dependency-injection/el/factory.texy
index cb608707a4..d6f61b4c87 100644
--- a/dependency-injection/el/factory.texy
+++ b/dependency-injection/el/factory.texy
@@ -170,39 +170,45 @@ Multifactory/Accessor .[#toc-multifactory-accessor]
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Αντί να περνάτε πολλαπλά παραγόμενα εργοστάσια και accessors, μπορείτε να περνάτε μόνο ένα σύνθετο multifactory.
 
-Εναλλακτικά, μπορείτε να χρησιμοποιήσετε τις διευθύνσεις `create()` και `get()` με μια παράμετρο αντί για πολλαπλές μεθόδους:
+Εναλλακτικά, μπορείτε να χρησιμοποιήσετε το `get()` με μια παράμετρο αντί για πολλαπλές μεθόδους:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Στην περίπτωση αυτή, η `MultiFactory::createArticle()` κάνει το ίδιο πράγμα με την `MultiFactoryAlt::create('article')`. Ωστόσο, η εναλλακτική σύνταξη έχει μερικά μειονεκτήματα. Δεν είναι σαφές ποιες τιμές `$name` υποστηρίζονται και ο τύπος επιστροφής δεν μπορεί να καθοριστεί στη διεπαφή όταν χρησιμοποιούνται πολλαπλές διαφορετικές τιμές `$name`.
+Σε αυτή την περίπτωση, το `MultiFactory::getArticle()` κάνει το ίδιο πράγμα με το `MultiFactoryAlt::get('article')`. Ωστόσο, η εναλλακτική σύνταξη έχει μερικά μειονεκτήματα. Δεν είναι σαφές ποιες τιμές `$name` υποστηρίζονται και ο τύπος επιστροφής δεν μπορεί να καθοριστεί στη διεπαφή όταν χρησιμοποιούνται πολλές διαφορετικές τιμές `$name`.
 
 
 Ορισμός με λίστα .[#toc-definition-with-a-list]
 -----------------------------------------------
-Πώς να ορίσετε ένα multifactory στη διαμόρφωσή σας; Ας δημιουργήσουμε τρεις υπηρεσίες που θα επιστρέφονται από το multifactory, καθώς και το ίδιο το multifactory:
+Αυτός ο τρόπος μπορεί να χρησιμοποιηθεί για τον ορισμό ενός πολλαπλού εργοστασίου στη διαμόρφωση: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Ή, στον ορισμό του εργοστασίου, μπορούμε να αναφερθούμε σε υπάρχουσες υπηρεσίες χρησιμοποιώντας μια αναφορά:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ services:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/el/faq.texy b/dependency-injection/el/faq.texy
index 0ee71b6c73..43f2cd3e23 100644
--- a/dependency-injection/el/faq.texy
+++ b/dependency-injection/el/faq.texy
@@ -61,7 +61,7 @@
 
 Γιατί η σύνθεση προτιμάται από την κληρονομικότητα; .[#toc-why-composition-is-preferred-over-inheritance]
 ---------------------------------------------------------------------------------------------------------
-Είναι προτιμότερο να χρησιμοποιείται η σύνθεση παρά η κληρονομικότητα, καθώς εξυπηρετεί τον σκοπό της δυνατότητας επαναχρησιμοποίησης του κώδικα χωρίς να χρειάζεται να ανησυχείτε για την επίδραση της αλλαγής. Έτσι, παρέχει πιο χαλαρή σύζευξη όπου δεν χρειάζεται να ανησυχούμε για το αν η αλλαγή κάποιου κώδικα προκαλεί την αλλαγή κάποιου άλλου εξαρτημένου κώδικα που απαιτεί αλλαγή. Ένα τυπικό παράδειγμα είναι η κατάσταση που προσδιορίζεται ως [κόλαση των κατασκευαστών |passing-dependencies#Constructor hell].
+Είναι προτιμότερο να χρησιμοποιείται η [σύνθεση |nette:introduction-to-object-oriented-programming#composition] αντί για [την κληρονομικότητα |nette:introduction-to-object-oriented-programming#inheritance], επειδή χρησιμεύει στην επαναχρησιμοποίηση του κώδικα χωρίς να χρειάζεται να ανησυχείτε για τις συνέπειες των αλλαγών. Έτσι, παρέχει μια πιο χαλαρή σύζευξη, όπου δεν χρειάζεται να ανησυχούμε ότι η αλλαγή κάποιου κώδικα θα προκαλέσει την ανάγκη αλλαγής άλλου εξαρτημένου κώδικα. Ένα τυπικό παράδειγμα είναι μια κατάσταση που αναφέρεται ως [κόλαση των κατασκευαστών |passing-dependencies#Constructor hell].
 
 
 Μπορεί το Nette DI Container να χρησιμοποιηθεί εκτός της Nette; .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/el/global-state.texy b/dependency-injection/el/global-state.texy
index 621b419f46..c9684f8313 100644
--- a/dependency-injection/el/global-state.texy
+++ b/dependency-injection/el/global-state.texy
@@ -301,4 +301,4 @@ class Foo
 
 Κατά τη διάρκεια αυτής της διαδικασίας, μπορεί να διαπιστώσετε ότι πρέπει να χωρίσετε μια κλάση επειδή έχει περισσότερες από μία αρμοδιότητες. Μην ανησυχείτε γι' αυτό- επιδιώξτε την αρχή της μίας ευθύνης.
 
-*Θα ήθελα να ευχαριστήσω τον Miško Hevery, του οποίου άρθρα όπως το [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] αποτελούν τη βάση αυτού του κεφαλαίου.*
+*Θα ήθελα να ευχαριστήσω τον Miško Hevery, του οποίου άρθρα όπως το [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] αποτελούν τη βάση αυτού του κεφαλαίου.*
diff --git a/dependency-injection/el/passing-dependencies.texy b/dependency-injection/el/passing-dependencies.texy
index 01698c8e6a..29863c21af 100644
--- a/dependency-injection/el/passing-dependencies.texy
+++ b/dependency-injection/el/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Το πρόβλημα εμφανίζεται όταν θέλουμε να αλλάξουμε τον κατασκευαστή της κλάσης `BaseClass`, για παράδειγμα όταν προστίθεται μια νέα εξάρτηση. Τότε πρέπει να τροποποιήσουμε και όλους τους κατασκευαστές των παιδιών. Το οποίο κάνει μια τέτοια τροποποίηση κόλαση.
 
-Πώς μπορεί να αποφευχθεί αυτό; Η λύση είναι η **προτεραιότητα της σύνθεσης έναντι της κληρονομικότητας**.
+Πώς να το αποτρέψετε αυτό; Η λύση είναι η **προτεραιότητα της [σύνθεσης έναντι της κληρονομικότητας** |faq#Why composition is preferred over inheritance].
 
-Ας σχεδιάσουμε λοιπόν τον κώδικα με διαφορετικό τρόπο. Θα αποφύγουμε τις αφηρημένες κλάσεις `Base*`. Αντί το `MyClass` να παίρνει κάποια λειτουργικότητα κληρονομώντας από το `BaseClass`, θα έχει αυτή τη λειτουργικότητα περασμένη ως εξάρτηση:
+Ας σχεδιάσουμε λοιπόν τον κώδικα με διαφορετικό τρόπο. Θα αποφύγουμε τις [αφηρημένες |nette:introduction-to-object-oriented-programming#abstract-classes] κλάσεις `Base*`. Αντί το `MyClass` να παίρνει κάποια λειτουργικότητα κληρονομώντας από το `BaseClass`, θα έχει αυτή τη λειτουργικότητα περασμένη ως εξάρτηση:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ class MyClass
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ $obj->cache = $cache;
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/el/services.texy b/dependency-injection/el/services.texy
index f264fd21f6..81c7740e4e 100644
--- a/dependency-injection/el/services.texy
+++ b/dependency-injection/el/services.texy
@@ -2,32 +2,32 @@
 *****************
 
 .[perex]
-Η διαμόρφωση είναι το σημείο όπου τοποθετούμε τους ορισμούς των προσαρμοσμένων υπηρεσιών. Αυτό γίνεται στην ενότητα `services`.
+Η διαμόρφωση είναι το μέρος όπου δίνουμε οδηγίες στο DI container για το πώς να συναρμολογήσει τις επιμέρους υπηρεσίες και πώς να τις συνδέσει με άλλες εξαρτήσεις. Η Nette παρέχει έναν πολύ σαφή και κομψό τρόπο για να το επιτύχουμε αυτό.
 
-Για παράδειγμα, έτσι δημιουργούμε μια υπηρεσία με το όνομα `database`, η οποία θα είναι μια περίπτωση της κλάσης `PDO`:
+Η ενότητα `services` στο αρχείο ρυθμίσεων NEON είναι το σημείο όπου ορίζουμε τις προσαρμοσμένες υπηρεσίες μας και τις διαμορφώσεις τους. Ας δούμε ένα απλό παράδειγμα ορισμού μιας υπηρεσίας με το όνομα `database`, η οποία αντιπροσωπεύει μια περίπτωση της κλάσης `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Η ονοματοδοσία των υπηρεσιών χρησιμοποιείται για να μας επιτρέπει να τις [αναφέρουμε |#Referencing Services]. Εάν μια υπηρεσία δεν αναφέρεται, δεν υπάρχει λόγος να την ονομάσουμε. Έτσι, αντί για όνομα χρησιμοποιούμε απλώς ένα σημείο αναφοράς:
+Αυτή η διαμόρφωση έχει ως αποτέλεσμα την ακόλουθη εργοστασιακή μέθοδο στο [δοχείο DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  # ανώνυμη υπηρεσία
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Μια καταχώρηση μιας γραμμής μπορεί να σπάσει σε πολλές γραμμές για να επιτραπεί η προσθήκη πρόσθετων κλειδιών, όπως το [setup |#setup]. Το ψευδώνυμο για το κλειδί `create:` είναι `factory:`.
+Τα ονόματα υπηρεσιών μας επιτρέπουν να τα αναφέρουμε σε άλλα μέρη του αρχείου διαμόρφωσης, χρησιμοποιώντας τη μορφή `@serviceName`. Εάν δεν υπάρχει ανάγκη να δώσουμε όνομα στην υπηρεσία, μπορούμε απλά να χρησιμοποιήσουμε ένα σημείο αναφοράς:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Στη συνέχεια, ανακτούμε την υπηρεσία από το δοχείο DI χρησιμοποιώντας τη μέθοδο `getService()` με βάση το όνομα ή, ακόμα καλύτερα, τη μέθοδο `getByType()` με βάση τον τύπο:
+Για να ανακτήσουμε μια υπηρεσία από το δοχείο DI, μπορούμε να χρησιμοποιήσουμε τη μέθοδο `getService()` με το όνομα της υπηρεσίας ως παράμετρο ή τη μέθοδο `getByType()` με τον τύπο της υπηρεσίας:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Δημιουργία υπηρεσίας .[#toc-creating-a-service]
-===============================================
+Δημιουργία υπηρεσιών .[#toc-service-creation]
+=============================================
 
-Τις περισσότερες φορές, δημιουργούμε μια υπηρεσία με την απλή δημιουργία μιας περίπτωσης μιας κλάσης:
+Συνήθως, δημιουργούμε μια υπηρεσία απλά με την ενσάρκωση μιας συγκεκριμένης κλάσης. Για παράδειγμα:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Η οποία θα δημιουργήσει μια μέθοδο εργοστασίου στο [DI |container] container:
+Εάν χρειάζεται να επεκτείνουμε τη διαμόρφωση με πρόσθετα κλειδιά, ο ορισμός μπορεί να επεκταθεί σε πολλές γραμμές:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Εναλλακτικά, ένα κλειδί `arguments` μπορεί να χρησιμοποιηθεί για να περάσει [ορίσματα |#Arguments]:
+Το κλειδί `create` έχει το ψευδώνυμο `factory`, και οι δύο εκδοχές είναι κοινές στην πράξη. Ωστόσο, συνιστούμε τη χρήση του κλειδιού `create`.
+
+Τα ορίσματα του κατασκευαστή ή η μέθοδος δημιουργίας μπορούν εναλλακτικά να γραφτούν στο κλειδί `arguments`:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Μια στατική μέθοδος μπορεί επίσης να δημιουργήσει μια υπηρεσία:
+Οι υπηρεσίες δεν χρειάζεται να δημιουργούνται μόνο με απλή ενσάρκωση μιας κλάσης- μπορούν επίσης να προκύψουν από την κλήση στατικών μεθόδων ή μεθόδων άλλων υπηρεσιών:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
+Σημειώστε ότι για λόγους απλότητας, αντί για `->`, χρησιμοποιούμε `::`, βλέπε [μέσα έκφρασης |#expression means]. Αυτές οι εργοστασιακές μέθοδοι δημιουργούνται:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Μια στατική μέθοδος `My\Database::create()` θεωρείται ότι έχει καθορισμένη τιμή επιστροφής που πρέπει να γνωρίζει ο περιέκτης DI. Εάν δεν την έχει, γράφουμε τον τύπο στη διαμόρφωση:
+Ο περιέκτης DI πρέπει να γνωρίζει τον τύπο της δημιουργούμενης υπηρεσίας. Αν δημιουργήσουμε μια υπηρεσία χρησιμοποιώντας μια μέθοδο που δεν έχει καθορισμένο τύπο επιστροφής, πρέπει να αναφέρουμε ρητά αυτόν τον τύπο στη διαμόρφωση:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Η Nette DI σας δίνει εξαιρετικά ισχυρές δυνατότητες έκφρασης για να γράψετε σχεδόν οτιδήποτε. Για παράδειγμα, για να [αναφερθούμε |#Referencing Services] σε μια άλλη υπηρεσία και να καλέσουμε τη μέθοδό της. Για λόγους απλότητας, χρησιμοποιείται το `::` αντί του `->`.
+
+Επιχειρήματα .[#toc-arguments]
+==============================
+
+Παραδίδουμε ορίσματα σε κατασκευαστές και μεθόδους με τρόπο που μοιάζει πολύ με την κανονική PHP:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Αντιστοιχεί σε κώδικα PHP:
+Για καλύτερη αναγνωσιμότητα, μπορούμε να απαριθμήσουμε τα ορίσματα σε ξεχωριστές γραμμές. Σε αυτή τη μορφή, η χρήση των κομμάτων είναι προαιρετική:
 
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
-
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-Οι κλήσεις μεθόδων μπορούν να συνδεθούν αλυσιδωτά όπως στην PHP:
+Μπορείτε επίσης να ονομάσετε τα ορίσματα, γεγονός που σας επιτρέπει τότε να μην ανησυχείτε για τη σειρά τους:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
+Αν θέλετε να παραλείψετε ορισμένα ορίσματα και να χρησιμοποιήσετε τις προεπιλεγμένες τιμές τους ή να εισαγάγετε μια υπηρεσία μέσω [αυτόματης καλωδίωσης |autowiring], χρησιμοποιήστε μια υπογράμμιση:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Τα επιχειρήματα μπορεί να είναι υπηρεσίες, παράμετροι και πολλά άλλα, δείτε τα [μέσα έκφρασης |#expression means].
 
-Επιχειρήματα .[#toc-arguments]
-==============================
 
-Οι ονομαστικές παράμετροι μπορούν επίσης να χρησιμοποιηθούν για τη μετάδοση επιχειρημάτων:
+Εγκατάσταση .[#toc-setup]
+=========================
+
+Στην ενότητα `setup`, ορίζουμε τις μεθόδους που πρέπει να κληθούν κατά τη δημιουργία της υπηρεσίας.
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # θέση
-		username: root                      # όνομα
-		password: secret                    # named
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Η χρήση των κομμάτων είναι προαιρετική όταν τα ορίσματα χωρίζονται σε πολλές γραμμές.
+Σε PHP, αυτό θα έμοιαζε ως εξής:
 
-Φυσικά, μπορούμε επίσης να χρησιμοποιήσουμε [άλλες υπηρεσίες |#Referencing Services] ή [παραμέτρους |configuration#parameters] ως ορίσματα:
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
+
+Εκτός από τις κλήσεις μεθόδων, μπορείτε επίσης να μεταβιβάζετε τιμές σε ιδιότητες. Η προσθήκη ενός στοιχείου σε έναν πίνακα υποστηρίζεται επίσης, αλλά πρέπει να το περικλείσετε σε εισαγωγικά για να αποφύγετε τη σύγκρουση με τη σύνταξη NEON:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
+Στην PHP, αυτό θα μεταφραζόταν ως εξής:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
- `_` character, for example `Foo(_, %appDir%)`Ή ακόμα καλύτερα, περάστε μόνο το δεύτερο όρισμα ως ονομαστική παράμετρο, π.χ. `Foo(path: %appDir%)`.
-
-Το Nette DI και η μορφή NEON σας δίνουν εξαιρετικά ισχυρές εκφραστικές δυνατότητες για να γράψετε σχεδόν οτιδήποτε. Έτσι, ένα όρισμα μπορεί να είναι ένα νεοδημιουργημένο αντικείμενο, μπορείτε να καλέσετε στατικές μεθόδους, μεθόδους άλλων υπηρεσιών ή ακόμη και παγκόσμιες συναρτήσεις χρησιμοποιώντας ειδικό συμβολισμό:
+Στην εγκατάσταση, μπορείτε επίσης να καλέσετε στατικές μεθόδους ή μεθόδους άλλων υπηρεσιών. Αν πρέπει να περάσετε την τρέχουσα υπηρεσία ως όρισμα, χρησιμοποιήστε το `@self`:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)         # δημιουργία αντικειμένου
-		DateTime::createFromFormat('Y-m-d')  # κλήση στατικής μεθόδου
-		@anotherService                      # περνώντας μια άλλη υπηρεσία
-		@http.request::getRemoteAddress()    # κλήση άλλης μεθόδου υπηρεσίας
-		::getenv(NetteMode)                  # κλήση παγκόσμιας συνάρτησης
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
+Σημειώστε ότι για λόγους απλότητας, αντί για `->`, χρησιμοποιούμε `::`, βλέπε [μέσα έκφρασης |#expression means]. Αυτό δημιουργεί την ακόλουθη εργοστασιακή μέθοδο:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-PHP: Ειδικές λειτουργίες .[#toc-special-functions]
---------------------------------------------------
-
-Μπορείτε επίσης να χρησιμοποιήσετε ειδικές συναρτήσεις σε ορίσματα για να ρίξετε ή να αναιρέσετε τιμές:
+Έκφραση Μέσα .[#toc-expression-means]
+=====================================
 
-- `not(%arg%)` negation
-- `bool(%arg%)` cast χωρίς απώλειες σε bool
-- `int(%arg%)` cast χωρίς απώλειες σε int
-- `float(%arg%)` lossless cast to float
-- `string(%arg%)` lossless cast to string
+Το Nette DI μας παρέχει εξαιρετικά πλούσιες δυνατότητες έκφρασης, επιτρέποντάς μας να εκφράσουμε σχεδόν τα πάντα. Στα αρχεία ρυθμίσεων, μπορούμε να χρησιμοποιούμε [παραμέτρους |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
-
-Η αναδιαγραφή χωρίς απώλειες διαφέρει από την κανονική αναδιαγραφή της PHP, π.χ. με τη χρήση του `(int)`, στο ότι πετάει μια εξαίρεση για μη αριθμητικές τιμές.
+# παράμετρος
+%wwwDir%
 
-Πολλαπλές υπηρεσίες μπορούν να περάσουν ως ορίσματα. Ένας πίνακας όλων των υπηρεσιών ενός συγκεκριμένου τύπου (δηλ. κλάσης ή διεπαφής) δημιουργείται από τη συνάρτηση `typed()`. Η συνάρτηση θα παραλείψει τις υπηρεσίες που έχουν απενεργοποιήσει την αυτόματη καλωδίωση και μπορούν να καθοριστούν πολλαπλοί τύποι που χωρίζονται με κόμμα.
+# τιμή κάτω από ένα κλειδί παραμέτρου
+%mailer.user%
 
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# παράμετρος μέσα σε μια συμβολοσειρά
+'%wwwDir%/images'
 ```
 
-Μπορείτε επίσης να περάσετε έναν πίνακα υπηρεσιών αυτόματα χρησιμοποιώντας [την αυτόματη καλωδίωση |autowiring#Collection of Services].
-
-Ένας πίνακας όλων των υπηρεσιών με μια συγκεκριμένη [ετικέτα |#tags] δημιουργείται από τη συνάρτηση `tagged()`. Μπορούν να καθοριστούν πολλαπλές ετικέτες που χωρίζονται με κόμμα.
+Μπορούμε επίσης να δημιουργήσουμε αντικείμενα, να καλέσουμε μεθόδους και συναρτήσεις:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# δημιουργήστε ένα αντικείμενο
+DateTime()
 
+# κλήση μιας στατικής μεθόδου
+Collator::create(%locale%)
 
-Αναφορά σε υπηρεσίες .[#toc-referencing-services]
-=================================================
+# κλήση μιας συνάρτησης PHP
+::getenv(DB_USER)
+```
 
-Η αναφορά σε μεμονωμένες υπηρεσίες γίνεται με τη χρήση των χαρακτήρων `@` and name, so for example `@database`:
+Να αναφερόμαστε σε υπηρεσίες είτε με το όνομά τους είτε με τον τύπο τους:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# υπηρεσία με όνομα
+@database
+
+# υπηρεσία ανά τύπο
+@Nette\Database\Connection
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
+Χρησιμοποιήστε σύνταξη πρώτης κατηγορίας callable: .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-Ακόμα και ανώνυμες υπηρεσίες μπορούν να αναφερθούν χρησιμοποιώντας μια επανάκληση, απλά καθορίστε τον τύπο τους (κλάση ή διεπαφή) αντί για το όνομά τους. Ωστόσο, αυτό συνήθως δεν είναι απαραίτητο λόγω της [αυτόματης καλωδίωσης |autowiring].
+Χρήση σταθερών:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # ή @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# σταθερά κατηγορίας
+FilesystemIterator::SKIP_DOTS
+
+# παγκόσμια σταθερά που λαμβάνεται από τη συνάρτηση constant() της PHP
+::constant(PHP_VERSION)
 ```
 
+όπως ακριβώς και στην PHP. Για λόγους απλότητας, αντί του `->`, χρησιμοποιούμε το `::`:
 
-Ρύθμιση .[#toc-setup]
-=====================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
 
-Στην ενότητα setup παραθέτουμε τις μεθόδους που θα κληθούν κατά τη δημιουργία της υπηρεσίας:
+@http.request::getUrl()::getHost()
+# PHP: http.request')->getUrl()->getHost()
+```
+
+Αυτές οι εκφράσεις μπορούν να χρησιμοποιηθούν οπουδήποτε κατά τη [δημιουργία υπηρεσιών |#Service Creation], σε [ορίσματα |#Arguments], στο τμήμα [εγκατάστασης |#setup] ή σε [παραμέτρους |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Ειδικές λειτουργίες .[#toc-special-functions]
+---------------------------------------------
 
-Properites μπορεί επίσης να οριστεί. Η προσθήκη ενός στοιχείου σε έναν πίνακα υποστηρίζεται επίσης, και θα πρέπει να γράφεται σε εισαγωγικά για να μην έρχεται σε σύγκρουση με τη σύνταξη του NEON:
+Μέσα σε αρχεία ρυθμίσεων, μπορείτε να χρησιμοποιήσετε αυτές τις ειδικές λειτουργίες:
 
+- `not()` για άρνηση τιμών
+- `bool()`, `int()`, `float()`, `string()` για μετατροπή τύπου χωρίς απώλειες
+- `typed()` για τη δημιουργία ενός πίνακα όλων των υπηρεσιών ενός συγκεκριμένου τύπου
+- `tagged()` για τη δημιουργία ενός πίνακα όλων των υπηρεσιών με μια συγκεκριμένη ετικέτα
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Αντιστοιχεί στον κώδικα PHP:
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-Ωστόσο, οι στατικές μέθοδοι ή οι μέθοδοι άλλων υπηρεσιών μπορούν επίσης να κληθούν στη ρύθμιση. Τους περνάμε την πραγματική υπηρεσία ως `@self`:
+Σε σύγκριση με το συμβατικό typecasting στην PHP, όπως το `(int)`, το lossless type casting θα πετάξει μια εξαίρεση για μη αριθμητικές τιμές.
 
+Η συνάρτηση `typed()` δημιουργεί έναν πίνακα όλων των υπηρεσιών ενός συγκεκριμένου τύπου (κλάση ή διεπαφή). Εξαιρεί τις υπηρεσίες με απενεργοποιημένη την αυτόματη σύνδεση. Μπορούν να καθοριστούν πολλαπλοί τύποι, χωρισμένοι με κόμμα.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Αντιστοιχεί στον κώδικα PHP:
+Μπορείτε επίσης να περάσετε αυτόματα έναν πίνακα υπηρεσιών ενός συγκεκριμένου τύπου ως όρισμα χρησιμοποιώντας την [αυτόματη καλωδίωση |autowiring#Collection of Services].
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+Η συνάρτηση `tagged()` δημιουργεί έναν πίνακα όλων των υπηρεσιών με μια καθορισμένη ετικέτα. Μπορούν να παρατίθενται πολλαπλές ετικέτες, διαχωρισμένες με κόμμα.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-Autowiring .[#toc-autowiring]
-=============================
+Αυτόματη καλωδίωση .[#toc-autowiring]
+=====================================
 
-Το κλειδί autowired μπορεί να χρησιμοποιηθεί για να αποκλείσει μια υπηρεσία από την αυτόματη σύνδεση ή για να επηρεάσει τη συμπεριφορά της. Για περισσότερες πληροφορίες, ανατρέξτε στο [κεφάλαιο σχετικά με την αυτόματη σύνδεση |autowiring].
+Το κλειδί `autowired` σας επιτρέπει να τροποποιήσετε τη συμπεριφορά αυτόματης καλωδίωσης για μια συγκεκριμένη υπηρεσία. Για περισσότερες λεπτομέρειες, ανατρέξτε [στο κεφάλαιο αυτόματη σύνδεση |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # Το foo αφαιρείται από την αυτόματη καλωδίωση
+		autowired: false     # η υπηρεσία foo αποκλείεται από την αυτόματη καλωδίωση
 ```
 
 
 Ετικέτες .[#toc-tags]
 =====================
 
-Οι πληροφορίες χρήστη μπορούν να προστεθούν σε μεμονωμένες υπηρεσίες με τη μορφή ετικετών:
+Οι ετικέτες χρησιμοποιούνται για την προσθήκη συμπληρωματικών πληροφοριών στις υπηρεσίες. Μπορείτε να αντιστοιχίσετε μία ή περισσότερες ετικέτες σε μια υπηρεσία:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Οι ετικέτες μπορούν επίσης να έχουν μια τιμή:
+Οι ετικέτες μπορούν επίσης να φέρουν τιμές:
 
 ```neon
 services:
@@ -370,14 +363,14 @@ services:
 			logger: monolog.logger.event
 ```
 
-Ένας πίνακας υπηρεσιών με συγκεκριμένες ετικέτες μπορεί να περάσει ως όρισμα χρησιμοποιώντας τη συνάρτηση `tagged()`. Μπορούν επίσης να καθοριστούν πολλαπλές ετικέτες που χωρίζονται με κόμμα.
+Για να ανακτήσετε όλες τις υπηρεσίες με συγκεκριμένες ετικέτες, μπορείτε να χρησιμοποιήσετε τη λειτουργία `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Τα ονόματα των υπηρεσιών μπορούν να ληφθούν από το δοχείο DI χρησιμοποιώντας τη μέθοδο `findByTag()`:
+Στο δοχείο DI, μπορείτε να λάβετε τα ονόματα όλων των υπηρεσιών με μια συγκεκριμένη ετικέτα χρησιμοποιώντας τη μέθοδο `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
@@ -386,10 +379,10 @@ $names = $container->findByTag('logger');
 ```
 
 
-Inject Mode .[#toc-inject-mode]
-===============================
+Λειτουργία έγχυσης .[#toc-inject-mode]
+======================================
 
-Η σημαία `inject: true` χρησιμοποιείται για την ενεργοποίηση του περάσματος εξαρτήσεων μέσω δημόσιων μεταβλητών με τον σχολιασμό [inject |best-practices:inject-method-attribute#Inject Attributes] και τις μεθόδους [inject*() |best-practices:inject-method-attribute#inject Methods].
+Η χρήση της σημαίας `inject: true` ενεργοποιεί τη μεταβίβαση εξαρτήσεων μέσω δημόσιων μεταβλητών με το σχόλιο [inject |best-practices:inject-method-attribute#Inject Attributes] και τις μεθόδους [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Από προεπιλογή, το `inject` είναι ενεργοποιημένο μόνο για τους παρουσιαστές.
 
 
-Τροποποίηση των υπηρεσιών .[#toc-modification-of-services]
-==========================================================
+Τροποποιήσεις υπηρεσιών .[#toc-service-modifications]
+=====================================================
 
-Υπάρχει ένας αριθμός υπηρεσιών στο δοχείο DI που έχουν προστεθεί από ενσωματωμένο ή από [την επέκτασή σας |#di-extensions]. Οι ορισμοί αυτών των υπηρεσιών μπορούν να τροποποιηθούν στη διαμόρφωση. Για παράδειγμα, για την υπηρεσία `application.application`, η οποία είναι εξ ορισμού ένα αντικείμενο `Nette\Application\Application`, μπορούμε να αλλάξουμε την κλάση:
+Ο περιέκτης DI περιέχει πολλές υπηρεσίες που προστίθενται είτε από ενσωματωμένες είτε από [επεκτάσεις χρηστών |#extensions]. Μπορείτε να τροποποιήσετε τους ορισμούς αυτών των υπηρεσιών απευθείας στη διαμόρφωση. Για παράδειγμα, μπορείτε να αλλάξετε την κλάση της υπηρεσίας `application.application`, η οποία είναι συμβατικά `Nette\Application\Application`, σε κάτι άλλο:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Η σημαία `alteration` είναι πληροφοριακή και δηλώνει ότι απλώς τροποποιούμε μια υπάρχουσα υπηρεσία.
+Η σημαία `alteration` είναι πληροφοριακή, υποδεικνύοντας ότι απλώς τροποποιούμε μια υπάρχουσα υπηρεσία.
 
-Μπορούμε επίσης να προσθέσουμε μια ρύθμιση:
+Μπορούμε επίσης να συμπληρώσουμε τη ρύθμιση:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Γι' αυτό υπάρχει το `reset`:
+Εδώ είναι που το `reset` είναι χρήσιμο:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Μια υπηρεσία που προστίθεται με επέκταση μπορεί επίσης να αφαιρεθεί από το δοχείο:
+Αν θέλετε να αφαιρέσετε μια υπηρεσία που προστέθηκε από μια επέκταση, μπορείτε να το κάνετε ως εξής:
 
 ```neon
 services:
diff --git a/dependency-injection/en/autowiring.texy b/dependency-injection/en/autowiring.texy
index 92c827f3de..c4c2a6728a 100644
--- a/dependency-injection/en/autowiring.texy
+++ b/dependency-injection/en/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 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].
+The type in the comment can also be of the form `array<int, Class>` or `list<Class>`. 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].
 
 
 Scalar Arguments
diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy
index a43f9a653c..baa5467cfb 100644
--- a/dependency-injection/en/configuration.texy
+++ b/dependency-injection/en/configuration.texy
@@ -67,7 +67,7 @@ How to bulk edit all services of a certain type? Need to call a certain method f
 ```neon
 decorator:
 	# for all services that are instances of this class or interface
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # call this method
 			- $absoluteUrls = true   # and set the variable
@@ -122,7 +122,7 @@ di:
 			- 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 use the `$container->getParameters()` 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.
@@ -191,20 +191,15 @@ Just specify in which directories (and subdirectories) the classes should be sea
 
 ```neon
 search:
-	# you choose the section names yourself
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	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
+	-	in: %appDir%/Forms
 
 		# filtering by file name (string|string[])
 		files:
@@ -220,7 +215,7 @@ Or we can select classes that inherit or implement at least one of the following
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ You can also define negative rules, ie class name masks or ancestors and if they
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+			files: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Tags can be set for added services:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/en/extensions.texy b/dependency-injection/en/extensions.texy
index 4e016ce8b7..7180a78b89 100644
--- a/dependency-injection/en/extensions.texy
+++ b/dependency-injection/en/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $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:#method-and-function-body].
+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:#method-and-function-bodies].
 
 We will show an example of how to start a session or start services that have the `run` tag using initialization code:
 
diff --git a/dependency-injection/en/factory.texy b/dependency-injection/en/factory.texy
index daf99d3f3f..d3cc3a3c6c 100644
--- a/dependency-injection/en/factory.texy
+++ b/dependency-injection/en/factory.texy
@@ -170,39 +170,45 @@ So far, the factories and accessors could only create or return just one object.
 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:
+Alternatively, you can use `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.
+In this case, `MultiFactory::getArticle()` does the same thing as `MultiFactoryAlt::get('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:
+This way can be used to define a multiple factory in the configuration: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Or, in the factory definition, we can refer to existing services using a reference:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Another option how to define a multifactory is to use [tags|services#Tags]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/en/faq.texy b/dependency-injection/en/faq.texy
index ecf0ee0df0..0bfecefd8c 100644
--- a/dependency-injection/en/faq.texy
+++ b/dependency-injection/en/faq.texy
@@ -61,7 +61,7 @@ Remember that moving to Dependency Injection is an investment in code quality an
 
 Why composition is preferred over inheritance?
 ----------------------------------------------
-It is preferable to use composition rather then inheritance as it serves the purpose of code reuse-ability without having the need to worry about the trickle down effect of change. Thus it provides more loosely coupling where we do not have to worry about changing some code causing some other dependent code requiring change. A typical example is the situation identified as [constructor hell |passing-dependencies#Constructor hell].
+It is preferable to use [composition |nette:introduction-to-object-oriented-programming#composition] instead of [inheritance |nette:introduction-to-object-oriented-programming#inheritance] because it serves to reuse code without having to worry about the consequences of changes. Thus, it provides a looser coupling where we don't have to worry that changing some code will cause the need to change other dependent code. A typical example is a situation referred to as [constructor hell |passing-dependencies#Constructor hell].
 
 
 Can Nette DI Container be used outside of Nette?
diff --git a/dependency-injection/en/global-state.texy b/dependency-injection/en/global-state.texy
index f8f47d4b7e..a3c30bc990 100644
--- a/dependency-injection/en/global-state.texy
+++ b/dependency-injection/en/global-state.texy
@@ -301,4 +301,4 @@ When contemplating code design, keep in mind that each `static $foo` represents
 
 During this process, you may find that you need to split a class because it has more than one responsibility. Don't worry about it; strive for the principle of one responsibility.
 
-*I would like to thank Miško Hevery, whose articles such as [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] form the basis of this chapter.*
+*I would like to thank Miško Hevery, whose articles such as [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] form the basis of this chapter.*
diff --git a/dependency-injection/en/passing-dependencies.texy b/dependency-injection/en/passing-dependencies.texy
index 43912611d4..bff2e4746f 100644
--- a/dependency-injection/en/passing-dependencies.texy
+++ b/dependency-injection/en/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 The problem occurs when we want to change the constructor of the `BaseClass` class, for example when a new dependency is added. Then we have to modify all the constructors of the children as well. Which makes such a modification hell.
 
-How to prevent this? The solution is to **prioritize composition over inheritance**.
+How to prevent this? The solution is to **prioritize [composition over inheritance |faq#Why composition is preferred over inheritance]**.
 
-So let's design the code differently. We'll avoid abstract `Base*` classes. Instead of `MyClass` getting some functionality by inheriting from `BaseClass`, it will have that functionality passed as a dependency:
+So let's design the code differently. We will avoid [abstract |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` classes. Instead of `MyClass` getting some functionality by inheriting from `BaseClass`, it will have that functionality passed as a dependency:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ The setter call is defined in the DI container configuration in [section setup |
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ The setting of the variable is defined in the DI container configuration in [sec
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy
index b0ba6e9eaa..d1f30a9613 100644
--- a/dependency-injection/en/services.texy
+++ b/dependency-injection/en/services.texy
@@ -2,32 +2,32 @@ Service Definitions
 *******************
 
 .[perex]
-Configuration is where we place the definitions of custom services. This is done in section `services`.
+Configuration is the place where we instruct the DI container on how to assemble individual services and how to connect them with other dependencies. Nette provides a very clear and elegant way to achieve this.
 
-For example, this is how we create a service named `database`, which will be an instance of class `PDO`:
+The `services` section in the NEON configuration file is where we define our custom services and their configurations. Let's look at a simple example of defining a service named `database`, which represents an instance of the `PDO` class:
 
 ```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:
+This configuration results in the following factory method in the [DI container|container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  #  anonymous service
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-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:`.
+Service names allow us to reference them in other parts of the configuration file, using the format `@serviceName`. If there's no need to name the service, we can simply use a bullet point:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-We then retrieve the service from the DI container using the method `getService()` by name, or better yet, the method `getByType()` by type:
+To retrieve a service from the DI container, we can use the `getService()` method with the service name as a parameter, or the `getByType()` method with the service type:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Creating a Service
-==================
+Service Creation
+================
 
-Most often, we create a service by simply creating an instance of a class:
+Most commonly, we create a service simply by instantiating a specific class. For example:
 
 ```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]:
+If we need to expand the configuration with additional keys, the definition can be expanded into multiple lines:
 
 ```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)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Corresponds to PHP code:
+The `create` key has an alias `factory`, both versions are common in practice. However, we recommend using `create`.
 
-```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:
+Constructor arguments or the creation method can alternatively be written in the `arguments` key:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-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 `->`.
+Services don't have to be created just by simple instantiation of a class; they can also result from calling static methods or methods of other services:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Corresponds to PHP code:
+Note that for simplicity, instead of `->`, we use `::`, see [#expression means]. These factory methods are generated:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-Method calls can be chained together as in PHP:
+The DI container needs to know the type of the created service. If we create a service using a method that doesn't have a specified return type, we must explicitly mention this type in the configuration:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Corresponds to PHP code:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Arguments
 =========
 
-Named parameters can also be used to pass arguments:
+We pass arguments to constructors and methods in a manner very similar to regular PHP:
 
 ```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'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-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:
+For better readability, we can list the arguments on separate lines. In this format, the use of commas is optional:
 
 ```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(NetteMode)                  # call a global function
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-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('NetteMode')
-	);
-}
-```
-
-
-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
+You can also name the arguments, which then allows you to not worry about their order:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-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.
+If you wish to omit certain arguments and use their default values or insert a service via [autowiring], use an underscore:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-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].
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Arguments can be services, parameters, and much more, see [#expression means].
 
 
 Setup
 =====
 
-In the setup section we list the methods to be called when creating the service:
+In the `setup` section, we define the methods that should be called when creating the service.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Corresponds to PHP code:
+In PHP, this would look like:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-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:
-
+In addition to method calls, you can also pass values to properties. Adding an element to an array is also supported, but you need to enclose it in quotes to avoid colliding with the NEON syntax:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Corresponds to PHP code:
+In PHP, this would translate to:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-However, static methods or methods of other services can also be called in the setup. We pass the actual service to them as `@self`:
-
+In the setup, you can also call static methods or methods of other services. If you need to pass the current service as an argument, use `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Corresponds to PHP code:
+Note that for simplicity, instead of `->`, we use `::`, see [#expression means]. This generates the following factory method:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
+Expression Means
+================
+
+Nette DI provides us with exceptionally rich expression capabilities, allowing us to articulate almost anything. In configuration files, we can use [parameters|configuration#parameters]:
+
+```neon
+# parameter
+%wwwDir%
+
+# value under a parameter key
+%mailer.user%
+
+# parameter within a string
+'%wwwDir%/images'
+```
+
+We can also create objects, call methods, and functions:
+
+```neon
+# create an object
+DateTime()
+
+# call a static method
+Collator::create(%locale%)
+
+# call a PHP function
+::getenv(DB_USER)
+```
+
+Refer to services either by their name or by type:
+
+```neon
+# service by name
+@database
+
+# service by type
+@Nette\Database\Connection
+```
+
+Use first-class callable syntax: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Use constants:
+
+```neon
+# class constant
+FilesystemIterator::SKIP_DOTS
+
+# global constant obtained by the PHP function constant()
+::constant(PHP_VERSION)
+```
+
+Method calls can be chained, just like in PHP. For simplicity, instead of `->`, we use `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+These expressions can be used anywhere when [creating services|#Service Creation], in [arguments|#Arguments], in the [#setup] section, or [parameters|configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Special Functions
+-----------------
+
+Within configuration files, you can utilize these special functions:
+
+- `not()` for value negation
+- `bool()`, `int()`, `float()`, `string()` for lossless type casting
+- `typed()` to generate an array of all services of a specified type
+- `tagged()` to create an array of all services with a given tag
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+Compared to conventional typecasting in PHP, like `(int)`, lossless type casting will throw an exception for non-numeric values.
+
+The `typed()` function creates an array of all services of a particular type (class or interface). It excludes services with autowiring turned off. Multiple types can be specified, separated by commas.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+You can also automatically pass an array of services of a specific type as an argument using [autowiring|autowiring#Collection of Services].
+
+The `tagged()` function creates an array of all services with a specified tag. Multiple tags can be listed, separated by commas.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
 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.
+The `autowired` key allows you to modify the autowiring behavior for a particular service. For more details, see [the autowiring chapter|autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo is removed from autowiring
+		autowired: false     # the foo service is excluded from autowiring
 ```
 
 
 Tags
 ====
 
-User information can be added to individual services in the form of tags:
+Tags are used to add supplementary information to services. You can assign one or more tags to a service:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Tags can also have a value:
+Tags can also carry values:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			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.
+To retrieve all services with specific tags, you can use the `tagged()` function:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Service names can be obtained from the DI container using the method `findByTag()`:
+In the DI container, you can obtain the names of all services with a specific tag using the `findByTag()` method:
 
 ```php
 $names = $container->findByTag('logger');
 // $names is an array containing the service name and tag value
-// i.e. ['foo' => 'monolog.logger.event', ...]
+// e.g. ['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 Attributes] annotation and the [inject*() |best-practices:inject-method-attribute#inject Methods] methods.
+Using the flag `inject: true` activates the passing of dependencies via public variables with the [inject |best-practices:inject-method-attribute#Inject Attributes] annotation and [inject*() |best-practices:inject-method-attribute#inject Methods] methods.
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 By default, `inject` is only activated for presenters.
 
 
-Modification of Services
-========================
+Service Modifications
+=====================
 
-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:
+The DI container contains many services added either by built-in or [user extensions|#extensions]. You can modify the definitions of these services directly in the configuration. For instance, you can change the class of the `application.application` service, which is conventionally `Nette\Application\Application`, to something else:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-The `alteration` flag is informative and says that we are just modifying an existing service.
+The `alteration` flag is informative, indicating that we're merely modifying an existing service.
 
-We can also add a setup:
+We can also supplement the setup:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$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:
+When overwriting a service, you might want to remove original arguments, setup items, or tags, which is where `reset` comes in handy:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-A service added by extension can also be removed from the container:
+If you wish to remove a service added by an extension, you can do so like this:
 
 ```neon
 services:
diff --git a/dependency-injection/es/autowiring.texy b/dependency-injection/es/autowiring.texy
index 7a459f767c..3268f6a1a5 100644
--- a/dependency-injection/es/autowiring.texy
+++ b/dependency-injection/es/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 El contenedor DI pasa automáticamente una matriz de servicios que coinciden con el tipo dado. Omitirá los servicios que tengan desactivado el autowiring.
 
-Si no puede controlar la forma del comentario phpDoc, puede pasar un array de servicios directamente en la configuración usando [`typed()`|services#Special Functions].
+El tipo en el comentario también puede ser de la forma `array<int, Class>` o `list<Class>`. Si no puede controlar la forma del comentario phpDoc, puede pasar un array de servicios directamente en la configuración usando [`typed()` |services#Special Functions].
 
 
 Argumentos escalares .[#toc-scalar-arguments]
diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy
index 5dcfe64475..536a89a5d1 100644
--- a/dependency-injection/es/configuration.texy
+++ b/dependency-injection/es/configuration.texy
@@ -67,7 +67,7 @@ Decorador .[#toc-decorator]
 ```neon
 decorator:
 	# para todos los servicios que son instancias de esta clase o interfaz
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # llamar a este método
 			- $absoluteUrls = true   # y establecer la variable
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Si no utilizas el array `$container->parameters`, puedes desactivar la exportación de parámetros. Además, puede exportar sólo aquellas etiquetas a través de las cuales obtiene servicios utilizando el método `$container->findByTag(...)`.
+Si no utilizas el array `$container->getParameters()`, puedes desactivar la exportación de parámetros. Además, puede exportar sólo aquellas etiquetas a través de las cuales obtiene servicios utilizando el método `$container->findByTag(...)`.
 Si no llama al método en absoluto, puede desactivar completamente la exportación de etiquetas con `false`.
 
 Puede reducir significativamente los metadatos para [autowiring] especificando las clases que utiliza como parámetro del método `$container->getByType()`.
@@ -191,20 +191,15 @@ Basta con especificar en qué directorios (y subdirectorios) deben buscarse las
 
 ```neon
 search:
-	# usted mismo elige los nombres de las secciones
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Normalmente, sin embargo, no queremos añadir todas las clases e interfaces, así que podemos filtrarlas:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtrado por nombre de archivo (string|string[])
 		files:
@@ -220,7 +215,7 @@ O podemos seleccionar clases que hereden o implementen al menos una de las sigui
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ También se pueden definir reglas negativas, es decir, máscaras de nombres de c
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+archivos: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Se pueden establecer etiquetas para los servicios añadidos:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/es/extensions.texy b/dependency-injection/es/extensions.texy
index 4d1deedefd..5aea07c4aa 100644
--- a/dependency-injection/es/extensions.texy
+++ b/dependency-injection/es/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialization .[wiki-method]
 ==============================
 
-El Configurador llama al código de inicialización después de [container creation |application:bootstrap#index.php], que se crea escribiendo en un objeto `$this->initialization` usando [method addBody() |php-generator:#method-and-function-body].
+El Configurador llama al código de inicialización después de [container creation |application:bootstrap#index.php], que se crea escribiendo en un objeto `$this->initialization` usando [method addBody() |php-generator:#method-and-function-bodies].
 
 Vamos a mostrar un ejemplo de cómo iniciar una sesión o iniciar servicios que tienen la etiqueta `run` usando código de inicialización:
 
diff --git a/dependency-injection/es/factory.texy b/dependency-injection/es/factory.texy
index 29891ce0a5..ef367ff00a 100644
--- a/dependency-injection/es/factory.texy
+++ b/dependency-injection/es/factory.texy
@@ -170,39 +170,45 @@ Hasta ahora, los factories (fábricas) y los accessors sólo podían crear o dev
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 En lugar de pasar múltiples fábricas y accessors generados, puedes pasar un único multifactory complejo.
 
-Alternativamente, puedes usar `create()` y `get()` con un parámetro en lugar de múltiples métodos:
+También puede utilizar `get()` con un parámetro en lugar de varios métodos:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-En este caso, `MultiFactory::createArticle()` hace lo mismo que `MultiFactoryAlt::create('article')`. Sin embargo, la sintaxis alternativa tiene algunas desventajas. No está claro qué valores de `$name` están soportados y el tipo de retorno no puede especificarse en la interfaz cuando se utilizan múltiples valores diferentes de `$name`.
+En este caso, `MultiFactory::getArticle()` hace lo mismo que `MultiFactoryAlt::get('article')`. Sin embargo, la sintaxis alternativa tiene algunas desventajas. No está claro qué valores de `$name` son compatibles y el tipo de retorno no se puede especificar en la interfaz cuando se utilizan varios valores diferentes de `$name`.
 
 
 Definición con una lista .[#toc-definition-with-a-list]
 -------------------------------------------------------
-¿Cómo definir un multifactory en tu configuración? Vamos a crear tres servicios que serán devueltos por el multifactory, y el propio multifactory:
+De esta forma se puede definir una fábrica múltiple en la configuración: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+O bien, en la definición de la fábrica, podemos hacer referencia a los servicios existentes utilizando una referencia:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Otra opción para definir un multifactory es utilizar [tags|services#Tags]:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/es/faq.texy b/dependency-injection/es/faq.texy
index ae21869cfa..40f35d038e 100644
--- a/dependency-injection/es/faq.texy
+++ b/dependency-injection/es/faq.texy
@@ -61,7 +61,7 @@ Recuerde que pasar a la inyección de dependencias es una inversión en la calid
 
 ¿Por qué se prefiere la composición a la herencia? .[#toc-why-composition-is-preferred-over-inheritance]
 --------------------------------------------------------------------------------------------------------
-Es preferible utilizar la composición en lugar de la herencia, ya que sirve al propósito de la reutilización del código sin tener que preocuparse por el efecto de goteo del cambio. Por lo tanto, proporciona un acoplamiento más laxo en el que no tenemos que preocuparnos de que el cambio de algún código provoque que otro código dependiente requiera un cambio. Un ejemplo típico es la situación identificada como [el infierno de los constructores |passing-dependencies#Constructor hell].
+Es preferible utilizar la [composición |nette:introduction-to-object-oriented-programming#composition] en lugar de [la herencia |nette:introduction-to-object-oriented-programming#inheritance] porque sirve para reutilizar código sin tener que preocuparse por las consecuencias de los cambios. Así, proporciona un acoplamiento más laxo en el que no tenemos que preocuparnos de que cambiar algún código provoque la necesidad de cambiar otro código dependiente. Un ejemplo típico es una situación conocida como [el infierno de los constructores |passing-dependencies#Constructor hell].
 
 
 ¿Se puede utilizar Nette DI Container fuera de Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/es/global-state.texy b/dependency-injection/es/global-state.texy
index 6a5d698af1..f659c7e7cd 100644
--- a/dependency-injection/es/global-state.texy
+++ b/dependency-injection/es/global-state.texy
@@ -301,4 +301,4 @@ Cuando contemples el diseño del código, ten en cuenta que cada `static $foo` r
 
 Durante este proceso, puede que descubras que necesitas dividir una clase porque tiene más de una responsabilidad. No te preocupes por ello; esfuérzate por el principio de una sola responsabilidad.
 
-*Me gustaría dar las gracias a Miško Hevery, cuyos artículos como [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] forman la base de este capítulo.*
+*Me gustaría dar las gracias a Miško Hevery, cuyos artículos como [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] forman la base de este capítulo.*
diff --git a/dependency-injection/es/passing-dependencies.texy b/dependency-injection/es/passing-dependencies.texy
index 05588ddfdc..cc895439a8 100644
--- a/dependency-injection/es/passing-dependencies.texy
+++ b/dependency-injection/es/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 El problema surge cuando queremos cambiar el constructor de la clase `BaseClass`, por ejemplo cuando se añade una nueva dependencia. Entonces tenemos que modificar también todos los constructores de los hijos. Lo que convierte tal modificación en un infierno.
 
-¿Cómo evitarlo? La solución es **priorizar la composición sobre la herencia**.
+¿Cómo evitarlo? La solución es **priorizar la [composición sobre la herencia** |faq#Why composition is preferred over inheritance].
 
-Así que diseñemos el código de otra manera. Evitaremos las clases abstractas `Base*`. En lugar de que `MyClass` obtenga alguna funcionalidad heredando de `BaseClass`, tendrá esa funcionalidad pasada como una dependencia:
+Así que vamos a diseñar el código de forma diferente. Evitaremos las clases [abstractas |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*`. En lugar de que `MyClass` obtenga alguna funcionalidad heredando de `BaseClass`, tendrá esa funcionalidad pasada como una dependencia:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ La llamada al setter se define en la configuración del contenedor DI en [secci
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ La configuración de la variable se define en la configuración del contenedor D
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/es/services.texy b/dependency-injection/es/services.texy
index 2f6af40b80..2eec71a83b 100644
--- a/dependency-injection/es/services.texy
+++ b/dependency-injection/es/services.texy
@@ -2,32 +2,32 @@ Definiciones de servicios
 *************************
 
 .[perex]
-Configuración es donde colocamos las definiciones de los servicios personalizados. Esto se hace en la sección `services`.
+La configuración es el lugar donde instruimos al contenedor DI sobre cómo ensamblar servicios individuales y cómo conectarlos con otras dependencias. Nette proporciona una forma muy clara y elegante de conseguirlo.
 
-Por ejemplo, así es como creamos un servicio llamado `database`, que será una instancia de la clase `PDO`:
+La sección `services` en el archivo de configuración NEON es donde definimos nuestros servicios personalizados y sus configuraciones. Veamos un ejemplo sencillo de definición de un servicio llamado `database`, que representa una instancia de la clase `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-El nombre de los servicios se utiliza para permitirnos [referenciarlos|#Referencing Services]. Si un servicio no es referenciado, no hay necesidad de nombrarlo. Así que simplemente usamos una viñeta en lugar de un nombre:
+Esta configuración resulta en el siguiente método de fábrica en el [contenedor DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  #  servicio anónimo
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Una entrada de una línea puede dividirse en varias líneas para permitir añadir claves adicionales, como [#setup]. El alias de la clave `create:` es `factory:`.
+Los nombres de los servicios nos permiten referenciarlos en otras partes del fichero de configuración, utilizando el formato `@serviceName`. Si no hay necesidad de nombrar el servicio, podemos usar simplemente una viñeta:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-A continuación recuperamos el servicio del contenedor DI usando el método `getService()` por nombre, o mejor aún, el método `getByType()` por tipo:
+Para recuperar un servicio del contenedor DI, podemos utilizar el método `getService()` con el nombre del servicio como parámetro, o el método `getByType()` con el tipo de servicio:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Creación de un servicio .[#toc-creating-a-service]
-==================================================
+Creación de servicios .[#toc-service-creation]
+==============================================
 
-La mayoría de las veces, creamos un servicio simplemente creando una instancia de una clase:
+Lo más común es crear un servicio simplemente instanciando una clase específica. Por ejemplo:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Lo que generará un método de fábrica en [DI container|container]:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Alternativamente, se puede usar una clave `arguments` para pasar [arguments|#Arguments]:
+Si necesitamos ampliar la configuración con claves adicionales, la definición puede ampliarse en varias líneas:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-Un método estático también puede crear un servicio:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Corresponde al código PHP:
+La clave `create` tiene un alias `factory`, ambas versiones son comunes en la práctica. No obstante, recomendamos utilizar `create`.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-Se supone que un método estático `My\Database::create()` tiene un valor de retorno definido que el contenedor DI necesita conocer. Si no lo tiene, escribimos el tipo en la configuración:
+Los argumentos del constructor o el método de creación pueden escribirse alternativamente en la clave `arguments`:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Nette DI te da facilidades de expresión extremadamente potentes para escribir casi cualquier cosa. Por ejemplo, para [refer|#Referencing services] a otro servicio y llamar a su método. Para simplificar, se utiliza `::` en lugar de `->`.
+Los servicios no tienen por qué crearse por simple instanciación de una clase; también pueden ser el resultado de llamar a métodos estáticos o a métodos de otros servicios:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Corresponde al código PHP:
+Nótese que, por simplicidad, en lugar de `->`, utilizamos `::`, véase la [expresión significa |#expression means]. Estos métodos de fábrica se generan:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-Las llamadas a métodos se pueden encadenar como en PHP:
+El contenedor DI necesita conocer el tipo del servicio creado. Si creamos un servicio utilizando un método que no tiene un tipo de retorno especificado, debemos mencionar explícitamente este tipo en la configuración:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Corresponde a código PHP:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argumentos .[#toc-arguments]
 ============================
 
-Los parámetros con nombre también pueden usarse para pasar argumentos:
+Pasamos argumentos a los constructores y métodos de una manera muy similar a PHP normal:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # positional
-		username: root                      # named
-		password: secret                    # named
-	)
-```
-
-El uso de comas es opcional cuando se dividen los argumentos en varias líneas.
-
-Por supuesto, también podemos utilizar [otros servicios|#Referencing Services] o [parámetros|configuration#parameters] como argumentos:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-Corresponde a código PHP:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Si el primer argumento es [autowired|autowiring] y quieres especificar el segundo, omite el primero con el caracter `_`, por ejemplo `Foo(_, %appDir%)`. O mejor aún, pase sólo el segundo argumento como un parámetro con nombre, por ejemplo `Foo(path: %appDir%)`.
-
-Nette DI y el formato NEON le ofrecen facilidades expresivas extremadamente potentes para escribir casi cualquier cosa. Así, un argumento puede ser un objeto recién creado, puede llamar a métodos estáticos, métodos de otros servicios, o incluso funciones globales utilizando una notación especial:
+Para una mejor legibilidad, podemos listar los argumentos en líneas separadas. En este formato, el uso de comas es opcional:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)         # crear objeto
-		DateTime::createFromFormat('Y-m-d')  # llamar método estático
-		@anotherService                      # pasar otro servicio
-		@http.request::getRemoteAddress()    # llamar a otro método de servicio
-		::getenv(NetteMode)                  # llamar a una función global
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-Corresponde al código PHP:
-
-```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('NetteMode')
-	);
-}
-```
-
-
-Funciones especiales .[#toc-special-functions]
-----------------------------------------------
-
-También puede utilizar funciones especiales en los argumentos para convertir o negar valores:
-
-- `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
+También puedes nombrar los argumentos, lo que te permitirá despreocuparte de su orden:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-La reescritura sin pérdidas difiere de la reescritura PHP normal, por ejemplo usando `(int)`, en que lanza una excepción para valores no numéricos.
-
-Se pueden pasar múltiples servicios como argumentos. La función `typed()` crea un array de todos los servicios de un tipo particular (clase o interfaz). La función omitirá los servicios que tengan desactivado el autowiring, y se pueden especificar múltiples tipos separados por una coma.
+Si desea omitir ciertos argumentos y utilizar sus valores por defecto o insertar un servicio mediante [autocableado |autowiring], utilice un guión bajo:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-También puede pasar un array de servicios automáticamente usando [autowiring|autowiring#Collection of Services].
-
-La función `tagged()` crea una matriz de todos los servicios con una determinada [tag|#tags]. Se pueden especificar múltiples etiquetas separadas por una coma.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Referencia a servicios .[#toc-referencing-services]
-===================================================
-
-Los servicios individuales se referencian utilizando el carácter `@` y el nombre, así por ejemplo `@database`:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-Corresponde a código PHP:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Incluso los servicios anónimos pueden ser referenciados usando una llamada de retorno, simplemente especificando su tipo (clase o interfaz) en lugar de su nombre. Sin embargo, esto no suele ser necesario debido a [autowiring].
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Los argumentos pueden ser servicios, parámetros y mucho más, véase [medios de expresión |#expression means].
 
 
 Configuración .[#toc-setup]
 ===========================
 
-En la sección setup listamos los métodos a llamar al crear el servicio:
+En la sección `setup`, definimos los métodos que deben ser llamados al crear el servicio.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Corresponde al código PHP:
+En PHP, esto se vería así:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-También se pueden establecer propiedades. También se puede añadir un elemento a un array, y debe escribirse entre comillas para no entrar en conflicto con la sintaxis de NEON:
-
+Además de llamadas a métodos, también puede pasar valores a propiedades. También se puede añadir un elemento a un array, pero es necesario encerrarlo entre comillas para evitar colisiones con la sintaxis NEON:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Corresponde a código PHP:
+En PHP, esto se traduciría como:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-Sin embargo, los métodos estáticos o de otros servicios también pueden ser llamados en la configuración. Les pasamos el servicio real como `@self`:
-
+En la configuración, también puede llamar a métodos estáticos o métodos de otros servicios. Si necesita pasar el servicio actual como argumento, utilice `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Corresponde al código PHP:
+Tenga en cuenta que, para simplificar, en lugar de `->`, utilizamos `::`, véase la [expresión significa |#expression means]. Esto genera el siguiente método de fábrica:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
-Autowiring (autocableado) .[#toc-autowiring]
+Medios de expresión .[#toc-expression-means]
 ============================================
 
-La clave de autocableado se puede utilizar para excluir un servicio del autocableado o para influir en su comportamiento. Ver [chapter on autowiring|autowiring] para más información.
+Nette DI nos proporciona capacidades de expresión excepcionalmente ricas, permitiéndonos articular casi cualquier cosa. En los archivos de configuración, podemos utilizar [parámetros |configuration#parameters]:
+
+```neon
+# parámetro
+%wwwDir%
+
+# valor bajo una clave de parámetro
+%mailer.user%
+
+# parámetro dentro de una cadena
+'%wwwDir%/images'
+```
+
+También podemos crear objetos, llamar a métodos y funciones:
+
+```neon
+# crear un objeto
+DateTime()
+
+# llamar a un método estático
+Collator::create(%locale%)
+
+# llamar a una función PHP
+::getenv(DB_USER)
+```
+
+Referirse a los servicios por su nombre o por su tipo:
+
+```neon
+# servicio por nombre
+@database
+
+# servicio por tipo
+@Nette\Database\Connection
+```
+
+Utilizar sintaxis de llamada de primera clase: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Utilizar constantes:
+
+```neon
+# constante de clase
+FilesystemIterator::SKIP_DOTS
+
+# constante global obtenida por la función PHP constant()
+::constant(PHP_VERSION)
+```
+
+Las llamadas a métodos pueden encadenarse, como en PHP. Para simplificar, en lugar de `->`, usamos `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('A-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Estas expresiones se pueden utilizar en cualquier lugar al [crear servicios |#Service Creation], en [argumentos |#Arguments], en la sección de [configuración |#setup] o [parámetros |configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Funciones especiales .[#toc-special-functions]
+----------------------------------------------
+
+Dentro de los archivos de configuración, puede utilizar estas funciones especiales:
+
+- `not()` para la negación de valores
+- `bool()`, `int()`, `float()`, `string()` para la conversión de tipos sin pérdidas
+- `typed()` para generar una matriz de todos los servicios de un tipo especificado
+- `tagged()` para crear una matriz de todos los servicios con una etiqueta determinada
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+Comparado con el encasillamiento convencional en PHP, como `(int)`, el encasillamiento sin pérdida lanzará una excepción para valores no numéricos.
+
+La función `typed()` crea un array de todos los servicios de un tipo particular (clase o interfaz). Excluye los servicios con autocableado desactivado. Se pueden especificar varios tipos, separados por comas.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+También puede pasar automáticamente una matriz de servicios de un tipo específico como argumento utilizando [autowiring |autowiring#Collection of Services].
+
+La función `tagged()` crea una matriz de todos los servicios con una etiqueta especificada. Se pueden listar varias etiquetas, separadas por comas.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
+Autocableado .[#toc-autowiring]
+===============================
+
+La tecla `autowired` permite modificar el comportamiento del autocableado para un servicio en particular. Para más detalles, consulte [el capítulo |autowiring] sobre autocableado.
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo is removed from autowiring
+		autowired: false     # el servicio foo queda excluido del autocableado
 ```
 
 
 Etiquetas .[#toc-tags]
 ======================
 
-Se puede añadir información de usuario a servicios individuales en forma de etiquetas:
+Las etiquetas se utilizan para añadir información complementaria a los servicios. Puede asignar una o varias etiquetas a un servicio:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Las etiquetas también pueden tener un valor:
+Las etiquetas también pueden llevar valores:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Con la función `tagged()` se puede pasar como argumento un array de servicios con determinadas etiquetas. También se pueden especificar varias etiquetas separadas por una coma.
+Para recuperar todos los servicios con etiquetas específicas, puede utilizar la función `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Los nombres de los servicios pueden obtenerse del contenedor DI utilizando el método `findByTag()`:
+En el contenedor DI, puede obtener los nombres de todos los servicios con una etiqueta específica utilizando el método `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
-// $names es una matriz que contiene el nombre del servicio y el valor de la etiqueta
-// i.e. ['foo' => 'monolog.logger.event', ...]
+// $names es un array que contiene el nombre del servicio y el valor de la etiqueta
+// por ejemplo ['foo' => 'monolog.logger.event', ...]
 ```
 
 
 Modo de inyección .[#toc-inject-mode]
 =====================================
 
-El indicador `inject: true` se utiliza para activar el paso de dependencias a través de variables públicas con la anotación [inject |best-practices:inject-method-attribute#Inject Attributes] y los métodos [inject*() |best-practices:inject-method-attribute#inject Methods].
+El uso de la bandera `inject: true` activa el paso de dependencias a través de variables públicas con la anotación [inject |best-practices:inject-method-attribute#Inject Attributes] y los métodos [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Por defecto, `inject` sólo está activado para los presentadores.
 
 
-Modificación de servicios .[#toc-modification-of-services]
-==========================================================
+Modificaciones del servicio .[#toc-service-modifications]
+=========================================================
 
-Hay una serie de servicios en el contenedor DI que han sido añadidos por built-in o [su extensión|#di-extensions]. Las definiciones de estos servicios se pueden modificar en la configuración. Por ejemplo, para el servicio `application.application`, que por defecto es un objeto `Nette\Application\Application`, podemos cambiar la clase:
+El contenedor DI contiene muchos servicios añadidos por [extensiones |#extensions] incorporadas o [de usuario |#extensions]. Puedes modificar las definiciones de estos servicios directamente en la configuración. Por ejemplo, puede cambiar la clase del servicio `application.application`, que convencionalmente es `Nette\Application\Application`, por otra:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-La bandera `alteration` es informativa e indica que estamos modificando un servicio existente.
+La bandera `alteration` es informativa, indicando que simplemente estamos modificando un servicio existente.
 
-También podemos añadir una configuración:
+También podemos complementar la configuración:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Al reescribir un servicio, es posible que queramos eliminar los argumentos, elementos de configuración o etiquetas originales, que es para lo que sirve `reset`:
+Al sobrescribir un servicio, es posible que desee eliminar los argumentos originales, elementos de configuración o etiquetas, que es donde `reset` es muy útil:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Un servicio añadido por extensión también se puede eliminar del contenedor:
+Si deseas eliminar un servicio añadido por una extensión, puedes hacerlo así:
 
 ```neon
 services:
diff --git a/dependency-injection/fr/autowiring.texy b/dependency-injection/fr/autowiring.texy
index 1ab809a378..a1c95b780f 100644
--- a/dependency-injection/fr/autowiring.texy
+++ b/dependency-injection/fr/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Le conteneur DI passe alors automatiquement un tableau de services correspondant au type donné. Il omettra les services dont le câblage automatique est désactivé.
 
-Si vous ne pouvez pas contrôler la forme du commentaire phpDoc, vous pouvez passer un tableau de services directement dans la configuration en utilisant la commande [`typed()` |services#Special Functions].
+Le type dans le commentaire peut également être de la forme `array<int, Class>` ou `list<Class>`. Si vous ne pouvez pas contrôler la forme du commentaire phpDoc, vous pouvez passer un tableau de services directement dans la configuration en utilisant la commande [`typed()` |services#Special Functions].
 
 
 Arguments scalaires .[#toc-scalar-arguments]
diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy
index 0a423fb41b..4241d58871 100644
--- a/dependency-injection/fr/configuration.texy
+++ b/dependency-injection/fr/configuration.texy
@@ -67,7 +67,7 @@ Comment modifier en masse tous les services d'un certain type ? Vous avez besoin
 ```neon
 decorator:
 	# pour tous les services qui sont des instances de cette classe ou interface
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)      # appelle cette méthode
 			- $absoluteUrls = true  # et définir la variable
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Si vous n'utilisez pas le tableau `$container->parameters`, vous pouvez désactiver l'exportation des paramètres. En outre, vous pouvez exporter uniquement les balises par lesquelles vous obtenez des services en utilisant la méthode `$container->findByTag(...)`.
+Si vous n'utilisez pas le tableau `$container->getParameters()`, vous pouvez désactiver l'exportation des paramètres. En outre, vous pouvez exporter uniquement les balises par lesquelles vous obtenez des services en utilisant la méthode `$container->findByTag(...)`.
 Si vous n'appelez pas du tout la méthode, vous pouvez désactiver complètement l'exportation des balises avec `false`.
 
 Vous pouvez réduire considérablement les métadonnées pour le [câblage automatique |autowiring] en spécifiant les classes que vous utilisez comme paramètre de la méthode `$container->getByType()`.
@@ -191,20 +191,15 @@ Il suffit de préciser dans quels répertoires (et sous-répertoires) les classe
 
 ```neon
 recherche:
-	# vous choisissez vous-même les noms des sections
-	mesFormulaires:
-		in: %appDir%/Forms
-
-	modèle:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 En général, cependant, nous ne voulons pas ajouter toutes les classes et interfaces, nous pouvons donc les filtrer :
 
 ```neon
 recherche:
-	mesFormulaires:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtrer par nom de fichier (string|string[])
 		files:
@@ -220,7 +215,7 @@ Ou nous pouvons sélectionner les classes qui héritent ou implémentent au moin
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Vous pouvez également définir des règles négatives, c'est-à-dire des masque
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+fichiers : ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Des étiquettes peuvent être définies pour les services ajoutés :
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/fr/extensions.texy b/dependency-injection/fr/extensions.texy
index e54b2acff0..a8e8b5bb93 100644
--- a/dependency-injection/fr/extensions.texy
+++ b/dependency-injection/fr/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialisation .[wiki-method]
 ==============================
 
-Le configurateur appelle le code d'initialisation après la [création du conteneur |application:bootstrap#index.php], qui est créé en écrivant dans un objet `$this->initialization` à l'aide de la [méthode addBody() |php-generator:#method-and-function-body].
+Le configurateur appelle le code d'initialisation après la [création du conteneur |application:bootstrap#index.php], qui est créé en écrivant dans un objet `$this->initialization` à l'aide de la [méthode addBody() |php-generator:#method-and-function-bodies].
 
 Nous allons montrer un exemple de la façon de démarrer une session ou de lancer des services qui ont la balise `run` en utilisant le code d'initialisation :
 
diff --git a/dependency-injection/fr/factory.texy b/dependency-injection/fr/factory.texy
index a57c5fa1da..836e6ee438 100644
--- a/dependency-injection/fr/factory.texy
+++ b/dependency-injection/fr/factory.texy
@@ -170,39 +170,45 @@ Jusqu'à présent, les fabriques et les accesseurs ne pouvaient créer ou renvoy
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Au lieu de passer plusieurs fabriques et accesseurs générés, vous pouvez passer une seule multifactory complexe.
 
-Vous pouvez également utiliser `create()` et `get()` avec un paramètre au lieu de plusieurs méthodes :
+Vous pouvez également utiliser `get()` avec un paramètre au lieu de plusieurs méthodes :
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Dans ce cas, `MultiFactory::createArticle()` fait la même chose que `MultiFactoryAlt::create('article')`. Toutefois, cette syntaxe alternative présente quelques inconvénients. On ne sait pas clairement quelles valeurs de `$name` sont prises en charge et le type de retour ne peut pas être spécifié dans l'interface lorsqu'on utilise plusieurs valeurs différentes de `$name`.
+Dans ce cas, `MultiFactory::getArticle()` fait la même chose que `MultiFactoryAlt::get('article')`. Cependant, la syntaxe alternative présente quelques inconvénients. Les valeurs `$name` prises en charge ne sont pas claires et le type de retour ne peut pas être spécifié dans l'interface en cas d'utilisation de plusieurs valeurs `$name` différentes.
 
 
 Définition avec une liste .[#toc-definition-with-a-list]
 --------------------------------------------------------
-Comment définir un multifactory dans votre configuration ? Créons trois services qui seront retournés par le multifactory, et le multifactory lui-même :
+Cette méthode peut être utilisée pour définir une usine multiple dans la configuration : .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Ou bien, dans la définition de la fabrique, nous pouvons nous référer à des services existants en utilisant une référence :
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Une autre option pour définir un multifactory est d'utiliser des [balises |serv
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/fr/faq.texy b/dependency-injection/fr/faq.texy
index 6a16f99f8a..ed54ba9878 100644
--- a/dependency-injection/fr/faq.texy
+++ b/dependency-injection/fr/faq.texy
@@ -61,7 +61,7 @@ N'oubliez pas que le passage à l'injection de dépendances est un investissemen
 
 Pourquoi la composition est-elle préférable à l'héritage ? .[#toc-why-composition-is-preferred-over-inheritance]
 ----------------------------------------------------------------------------------------------------------------
-Il est préférable d'utiliser la composition plutôt que l'héritage car elle permet de réutiliser le code sans avoir à s'inquiéter de l'effet de ruissellement des changements. Elle permet donc un couplage plus lâche, sans avoir à se soucier du fait que la modification d'un code entraîne la modification d'un autre code dépendant. Un exemple typique est la situation identifiée comme l'[enfer des constructeurs |passing-dependencies#Constructor hell].
+Il est préférable d'utiliser la [composition |nette:introduction-to-object-oriented-programming#composition] plutôt que l'[héritage |nette:introduction-to-object-oriented-programming#inheritance] car elle permet de réutiliser le code sans avoir à se soucier des conséquences des changements. Ainsi, elle permet un couplage plus lâche où nous n'avons pas à nous soucier du fait que la modification d'un code entraînera la nécessité de modifier d'autres codes dépendants. Un exemple typique est une situation appelée " [enfer du constructeur" |passing-dependencies#Constructor hell].
 
 
 Nette DI Container peut-il être utilisé en dehors de Nette ? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/fr/global-state.texy b/dependency-injection/fr/global-state.texy
index e55a85076d..f1471bab7a 100644
--- a/dependency-injection/fr/global-state.texy
+++ b/dependency-injection/fr/global-state.texy
@@ -301,4 +301,4 @@ Lorsque vous envisagez la conception d'un code, gardez à l'esprit que chaque `s
 
 Au cours de ce processus, vous constaterez peut-être que vous devez diviser une classe parce qu'elle a plus d'une responsabilité. Ne vous en préoccupez pas ; efforcez-vous de respecter le principe de la responsabilité unique.
 
-*Je tiens à remercier Miško Hevery, dont les articles tels que [Flaw : Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] constituent la base de ce chapitre*.
+*Je tiens à remercier Miško Hevery, dont les articles tels que [Flaw : Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] constituent la base de ce chapitre*.
diff --git a/dependency-injection/fr/passing-dependencies.texy b/dependency-injection/fr/passing-dependencies.texy
index 67f2ea3138..b40d5b3da1 100644
--- a/dependency-injection/fr/passing-dependencies.texy
+++ b/dependency-injection/fr/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Le problème se pose lorsque nous voulons modifier le constructeur de la classe `BaseClass`, par exemple lorsqu'une nouvelle dépendance est ajoutée. Il faut alors modifier tous les constructeurs des enfants. Ce qui rend une telle modification infernale.
 
-Comment éviter cela ? La solution est de **prioriser la composition sur l'héritage**.
+Comment éviter cela ? La solution est de **prioriser la [composition sur l'héritage** |faq#Why composition is preferred over inheritance].
 
-Concevons donc le code différemment. Nous éviterons les classes abstraites `Base*`. Au lieu que `MyClass` obtienne une fonctionnalité en héritant de `BaseClass`, cette fonctionnalité lui sera transmise en tant que dépendance :
+Concevons donc le code différemment. Nous éviterons les classes [abstraites |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*`. Au lieu que `MyClass` obtienne une fonctionnalité en héritant de `BaseClass`, cette fonctionnalité lui sera transmise en tant que dépendance :
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ L'appel au setter est défini dans la configuration du conteneur DI dans la [sec
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Le paramétrage de la variable est défini dans la configuration du conteneur DI
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/fr/services.texy b/dependency-injection/fr/services.texy
index 95f152a65b..ecfd61ae7a 100644
--- a/dependency-injection/fr/services.texy
+++ b/dependency-injection/fr/services.texy
@@ -2,32 +2,32 @@ Définitions des services
 ************************
 
 .[perex]
-La configuration est l'endroit où nous plaçons les définitions des services personnalisés. Ceci est fait dans la section `services`.
+La configuration est l'endroit où nous indiquons au conteneur DI comment assembler des services individuels et comment les relier à d'autres dépendances. Nette fournit une méthode très claire et élégante pour y parvenir.
 
-Par exemple, voici comment nous créons un service nommé `database`, qui sera une instance de la classe `PDO`:
+La section `services` du fichier de configuration NEON est l'endroit où nous définissons nos services personnalisés et leurs configurations. Examinons un exemple simple de définition d'un service nommé `database`, qui représente une instance de la classe `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Le nommage des services est utilisé pour nous permettre de les [référencer |#Referencing Services]. Si un service n'est pas référencé, il n'est pas nécessaire de le nommer. Nous utilisons donc simplement une puce au lieu d'un nom :
+Cette configuration se traduit par la méthode d'usine suivante dans le [conteneur DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # service anonyme
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Une entrée d'une ligne peut être décomposée en plusieurs lignes pour permettre l'ajout de clés supplémentaires, telles que [setup |#setup]. L'alias de la clé `create:` est `factory:`.
+Les noms des services nous permettent de les référencer dans d'autres parties du fichier de configuration, en utilisant le format `@serviceName`. S'il n'est pas nécessaire de nommer le service, nous pouvons simplement utiliser un point :
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Nous récupérons ensuite le service dans le conteneur DI en utilisant la méthode `getService()` par nom, ou mieux encore, la méthode `getByType()` par type :
+Pour récupérer un service dans le conteneur DI, nous pouvons utiliser la méthode `getService()` avec le nom du service comme paramètre, ou la méthode `getByType()` avec le type de service :
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Création d'un service .[#toc-creating-a-service]
-================================================
+Création de services .[#toc-service-creation]
+=============================================
 
-Le plus souvent, nous créons un service en créant simplement une instance d'une classe :
+Le plus souvent, nous créons un service en instanciant simplement une classe spécifique. Par exemple, nous pouvons créer un service en instanciant une classe spécifique :
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Ce qui va générer une méthode de fabrique dans le [conteneur DI |container]:
+Si nous avons besoin d'étendre la configuration avec des clés supplémentaires, la définition peut être développée en plusieurs lignes :
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Alternativement, une clé `arguments` peut être utilisée pour passer des [arguments |#Arguments]:
+La clé `create` a un alias `factory`, les deux versions sont courantes dans la pratique. Cependant, nous recommandons d'utiliser `create`.
+
+Les arguments du constructeur ou la méthode de création peuvent également être écrits dans la clé `arguments`:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Une méthode statique peut également créer un service :
+Les services ne doivent pas nécessairement être créés par la simple instanciation d'une classe ; ils peuvent également résulter de l'appel de méthodes statiques ou de méthodes d'autres services :
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Correspond au code PHP :
+Notez que pour plus de simplicité, au lieu de `->`, nous utilisons `::`, voir [les moyens d'expression. |#expression means] Ces méthodes d'usine sont générées :
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Une méthode statique `My\Database::create()` est supposée avoir une valeur de retour définie que le conteneur DI doit connaître. S'il ne l'a pas, nous écrivons le type dans la configuration :
+Le conteneur DI doit connaître le type du service créé. Si nous créons un service en utilisant une méthode qui n'a pas de type de retour spécifié, nous devons explicitement mentionner ce type dans la configuration :
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Nette DI vous donne des facilités d'expression extrêmement puissantes pour écrire presque n'importe quoi. Par exemple, pour [faire référence |#Referencing Services] à un autre service et appeler sa méthode. Pour simplifier, on utilise `::` au lieu de `->`.
+
+Arguments .[#toc-arguments]
+===========================
+
+Nous passons des arguments aux constructeurs et aux méthodes d'une manière très similaire à celle de PHP :
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Correspond au code PHP :
-
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
+Pour une meilleure lisibilité, nous pouvons lister les arguments sur des lignes séparées. Dans ce format, l'utilisation des virgules est optionnelle :
 
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-Les appels de méthode peuvent être enchaînés comme en PHP :
+Vous pouvez également nommer les arguments, ce qui vous permet de ne pas vous soucier de leur ordre :
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Correspond au code PHP :
+Si vous souhaitez omettre certains arguments et utiliser leurs valeurs par défaut ou insérer un service par [câblage automatique |autowiring], utilisez un trait de soulignement :
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Les arguments peuvent être des services, des paramètres et bien d'autres choses encore, voir les [moyens d'expression |#expression means].
 
-Arguments .[#toc-arguments]
+
+Configuration .[#toc-setup]
 ===========================
 
-Les paramètres nommés peuvent également être utilisés pour transmettre des arguments :
+Dans la section `setup`, nous définissons les méthodes qui doivent être appelées lors de la création du service.
 
 ```neon
 services:
-	database: PDO(
-		mysql:host=127.0.0.1;dbname=test' # positionnel
-		username: root                    # nommé
-		password: secret                  # nommé
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-L'utilisation de virgules est facultative lorsque les arguments sont répartis sur plusieurs lignes.
+En PHP, cela ressemblerait à
+
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
 
-Bien entendu, nous pouvons également utiliser [d'autres services |#Referencing Services] ou [paramètres |configuration#parameters] comme arguments :
+En plus des appels de méthodes, vous pouvez également passer des valeurs aux propriétés. L'ajout d'un élément à un tableau est également possible, mais vous devez le mettre entre guillemets pour éviter toute collision avec la syntaxe NEON :
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Correspond au code PHP :
+En PHP, cela se traduirait par :
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-Si le premier argument est [autodirigé |autowiring] et que vous souhaitez spécifier le second, omettez le premier avec `_` character, for example `Foo(_, %appDir%)`. Ou mieux encore, passez uniquement le second argument comme paramètre nommé, par exemple `Foo(path: %appDir%)`.
-
-Nette DI et le format NEON vous offrent des possibilités d'expression extrêmement puissantes pour écrire presque tout. Ainsi, un argument peut être un objet nouvellement créé, vous pouvez appeler des méthodes statiques, des méthodes d'autres services, ou même des fonctions globales en utilisant une notation spéciale :
+Dans la configuration, vous pouvez également appeler des méthodes statiques ou des méthodes d'autres services. Si vous devez passer le service courant comme argument, utilisez `@self`:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)        # créer un objet
-		DateTime::createFromFormat('Y-m-d') # appelle la méthode statique
-		@anotherService                     # passage d'un autre service
-		@http.request::getRemoteAddress()   # appel d'une autre méthode de service
-		::getenv(NetteMode)                 # appel d'une fonction globale
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Correspond au code PHP :
+Notez que pour plus de simplicité, au lieu de `->`, nous utilisons `::`, voir [les moyens d'expression |#expression means]. Cela génère la méthode d'usine suivante :
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-Fonctions spéciales .[#toc-special-functions]
----------------------------------------------
-
-Vous pouvez également utiliser des fonctions spéciales dans les arguments pour exprimer ou nier des valeurs :
+Moyens d'expression .[#toc-expression-means]
+============================================
 
-- `not(%arg%)` négation
-- `bool(%arg%)` Conversion sans perte en bool
-- `int(%arg%)` Conversion sans perte en int
-- `float(%arg%)` conversion sans perte en float
-- `string(%arg%)` Moulage sans perte vers string
+Nette DI nous offre des capacités d'expression exceptionnellement riches, nous permettant d'articuler presque n'importe quoi. Dans les fichiers de configuration, nous pouvons utiliser des [paramètres |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
-
-La réécriture sans perte diffère de la réécriture PHP normale, par exemple en utilisant `(int)`, car elle lève une exception pour les valeurs non numériques.
+# paramètre
+%wwwDir%
 
-Plusieurs services peuvent être passés en argument. Un tableau de tous les services d'un type particulier (c'est-à-dire une classe ou une interface) est créé par la fonction `typed()`. La fonction omettra les services dont le câblage automatique est désactivé, et plusieurs types séparés par une virgule peuvent être spécifiés.
+# valeur sous une clé de paramètre
+%mailer.user%
 
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# paramètre dans une chaîne de caractères
+'%wwwDir%/images'
 ```
 
-Vous pouvez également passer un tableau de services automatiquement en utilisant le [câblage automatique |autowiring#Collection of Services].
-
-Un tableau de tous les services avec une certaine [étiquette |#tags] est créé par la fonction `tagged()`. Plusieurs balises séparées par une virgule peuvent être spécifiées.
+Nous pouvons également créer des objets, appeler des méthodes et des fonctions :
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# créer un objet
+DateTime()
 
+# appeler une méthode statique
+Collator::create(%locale%)
 
-Services de référencement .[#toc-referencing-services]
-======================================================
+# appeler une fonction PHP
+::getenv(DB_USER)
+```
 
-Les services individuels sont référencés à l'aide du caractère `@` and name, so for example `@database`:
+Faire référence aux services soit par leur nom, soit par leur type :
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# service par nom
+@database
+
+# service par type
+@Nette\Database\Connection
 ```
 
-Correspond au code PHP :
+Utiliser une syntaxe d'appel de première classe : .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-Même les services anonymes peuvent être référencés à l'aide d'un callback, il suffit de spécifier leur type (classe ou interface) au lieu de leur nom. Cependant, cela n'est généralement pas nécessaire en raison du [câblage automatique |autowiring].
+Utiliser des constantes :
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # ou @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# constante de classe
+FilesystemIterator::SKIP_DOTS
+
+# constante globale obtenue par la fonction PHP constant()
+::constant(PHP_VERSION)
 ```
 
+Les appels de méthodes peuvent être enchaînés, comme en PHP. Pour simplifier, au lieu de `->`, nous utilisons `::`:
 
-Configuration .[#toc-setup]
-===========================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
 
-Dans la section "setup", nous listons les méthodes à appeler lors de la création du service :
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Ces expressions peuvent être utilisées n'importe où lors de la [création de services |#Service Creation], dans les [arguments |#Arguments], dans la section de [configuration |#setup] ou dans les [paramètres |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Correspond au code PHP :
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Fonctions spéciales .[#toc-special-functions]
+---------------------------------------------
 
-Les propriétés peuvent également être définies. L'ajout d'un élément à un tableau est également supporté, et doit être écrit entre guillemets pour ne pas entrer en conflit avec la syntaxe NEON :
+Dans les fichiers de configuration, vous pouvez utiliser ces fonctions spéciales :
 
+- `not()` pour la négation des valeurs
+- `bool()`, `int()`, `float()`, `string()` pour le moulage de type sans perte
+- `typed()` pour générer un tableau de tous les services d'un type spécifié
+- `tagged()` pour créer un tableau de tous les services avec une étiquette donnée
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Correspond au code PHP :
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-Cependant, les méthodes statiques ou les méthodes d'autres services peuvent également être appelées dans la configuration. Nous leur passons le service réel en tant que `@self`:
+Par rapport au typage conventionnel en PHP, comme `(int)`, le typage sans perte lèvera une exception pour les valeurs non numériques.
 
+La fonction `typed()` crée un tableau de tous les services d'un type particulier (classe ou interface). Elle exclut les services dont le câblage automatique est désactivé. Plusieurs types peuvent être spécifiés, séparés par des virgules.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Correspond au code PHP :
+Vous pouvez également passer automatiquement un tableau de services d'un type spécifique comme argument en utilisant le [câblage automatique |autowiring#Collection of Services].
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+La fonction `tagged()` crée un tableau de tous les services ayant une balise spécifiée. Plusieurs balises peuvent être listées, séparées par des virgules.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-Câblage automatique .[#toc-autowiring]
-======================================
+Câblage automobile .[#toc-autowiring]
+=====================================
 
-La clé autowired peut être utilisée pour exclure un service de l'autowiring ou pour influencer son comportement. Voir le [chapitre sur le câblage automatique |autowiring] pour plus d'informations.
+La clé `autowired` permet de modifier le comportement de l'autocâblage pour un service particulier. Pour plus de détails, voir [le chapitre sur |autowiring] l'autocâblage.
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # foo est retiré de l'autowiring
+		autowired: false     # le service foo est exclu de l'autocâblage
 ```
 
 
 Tags .[#toc-tags]
 =================
 
-Des informations sur les utilisateurs peuvent être ajoutées aux services individuels sous la forme de balises :
+Les balises sont utilisées pour ajouter des informations supplémentaires aux services. Vous pouvez attribuer une ou plusieurs balises à un service :
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Les étiquettes peuvent également avoir une valeur :
+Les balises peuvent également comporter des valeurs :
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Un tableau de services avec certaines balises peut être passé comme argument en utilisant la fonction `tagged()`. Plusieurs balises séparées par une virgule peuvent également être spécifiées.
+Pour retrouver tous les services ayant des étiquettes spécifiques, vous pouvez utiliser la fonction `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Les noms des services peuvent être obtenus du conteneur DI à l'aide de la méthode `findByTag()`:
+Dans le conteneur DI, vous pouvez obtenir les noms de tous les services avec une étiquette spécifique en utilisant la méthode `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
 // $names est un tableau contenant le nom du service et la valeur du tag
-// c'est-à-dire ['foo' => 'monolog.logger.event', ...]
+// par exemple ['foo' => 'monolog.logger.event', ...]
 ```
 
 
 Mode d'injection .[#toc-inject-mode]
 ====================================
 
-L'indicateur `inject: true` est utilisé pour activer le passage des dépendances via des variables publiques avec l'annotation [inject |best-practices:inject-method-attribute#Inject Attributes] et les méthodes [inject*() |best-practices:inject-method-attribute#inject Methods].
+L'utilisation du drapeau `inject: true` active le passage de dépendances via des variables publiques avec l'annotation [inject |best-practices:inject-method-attribute#Inject Attributes] et les méthodes [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Par défaut, `inject` n'est activé que pour les présentateurs.
 
 
-Modification des services .[#toc-modification-of-services]
-==========================================================
+Modifications du service .[#toc-service-modifications]
+======================================================
 
-Il existe un certain nombre de services dans le conteneur DI qui ont été ajoutés par l'intégration ou [votre extension |#di-extensions]. Les définitions de ces services peuvent être modifiées dans la configuration. Par exemple, pour le service `application.application`, qui est par défaut un objet `Nette\Application\Application`, nous pouvons changer la classe :
+Le conteneur DI contient de nombreux services ajoutés soit par des [extensions |#extensions] intégrées, soit par des [extensions utilisateur |#extensions]. Vous pouvez modifier les définitions de ces services directement dans la configuration. Par exemple, vous pouvez changer la classe du service `application.application`, qui est conventionnellement `Nette\Application\Application`, en quelque chose d'autre :
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Le drapeau `alteration` est informatif et indique que nous ne faisons que modifier un service existant.
+Le drapeau `alteration` est informatif, indiquant que nous modifions simplement un service existant.
 
-Nous pouvons également ajouter un service :
+Nous pouvons également compléter la configuration :
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Lorsque nous réécrivons un service, nous pouvons vouloir supprimer les arguments, les éléments de configuration ou les balises d'origine, ce à quoi sert `reset`:
+Lors de l'écrasement d'un service, il se peut que vous souhaitiez supprimer les arguments, les éléments de configuration ou les balises d'origine, et c'est là que `reset` s'avère utile :
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Un service ajouté par extension peut également être retiré du conteneur :
+Si vous souhaitez supprimer un service ajouté par une extension, vous pouvez procéder comme suit :
 
 ```neon
 services:
diff --git a/dependency-injection/hu/autowiring.texy b/dependency-injection/hu/autowiring.texy
index fd1c0b7e10..743d7cc478 100644
--- a/dependency-injection/hu/autowiring.texy
+++ b/dependency-injection/hu/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 A DI konténer ekkor automatikusan átadja a megadott típusnak megfelelő szolgáltatások tömbjét. Kihagyja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva.
 
-Ha nem tudja ellenőrizni a phpDoc megjegyzés formáját, akkor közvetlenül a konfigurációban is átadhatja a szolgáltatások tömbjét a következővel [`typed()` |services#Special Functions].
+A megjegyzésben szereplő típus lehet a következő formájú is `array<int, Class>` vagy `list<Class>`. Ha nem tudja ellenőrizni a phpDoc megjegyzés formáját, akkor közvetlenül a konfigurációban átadhatja a szolgáltatások tömbjét a következővel [`typed()` |services#Special Functions].
 
 
 Skaláris argumentumok .[#toc-scalar-arguments]
diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy
index 1563ee5bf8..16d1097e80 100644
--- a/dependency-injection/hu/configuration.texy
+++ b/dependency-injection/hu/configuration.texy
@@ -67,7 +67,7 @@ Hogyan lehet egy bizonyos típusú összes szolgáltatást tömegesen szerkeszte
 ```neon
 decorator:
 	# minden olyan szolgáltatáshoz, amely ennek az osztálynak vagy interfésznek a példánya.
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- # hívja meg ezt a metódust
 			- $absoluteUrls = true # és állítsuk be a változót
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Ha nem használja a `$container->parameters` tömböt, kikapcsolhatja a paraméterek exportálását. Továbbá csak azokat a címkéket exportálhatja, amelyeken keresztül a `$container->findByTag(...)` módszerrel szolgáltatásokat kap.
+Ha nem használja a `$container->getParameters()` tömböt, kikapcsolhatja a paraméterek exportálását. Továbbá csak azokat a címkéket exportálhatja, amelyeken keresztül a `$container->findByTag(...)` módszerrel szolgáltatásokat kap.
 Ha egyáltalán nem hívja meg a módszert, akkor a `false` segítségével teljesen letilthatja a címkék exportálását.
 
 Jelentősen csökkentheti az [autowiring |autowiring] metaadatait, ha a `$container->getByType()` metódus paramétereként megadja a használt osztályokat.
@@ -191,20 +191,15 @@ Csak adjuk meg, hogy mely könyvtárakban (és alkönyvtárakban) kell keresni a
 
 ```neon
 search:
-	# te magad választod ki a szekciók nevét
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Általában azonban nem akarjuk az összes osztályt és interfészt felvenni, így szűrhetjük őket:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# szűrés fájlnév alapján (string|string[])
 		files:
@@ -220,7 +215,7 @@ Vagy kiválaszthatjuk azokat az osztályokat, amelyek a következő osztályok k
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Meghatározhatunk negatív szabályokat is, azaz osztálynév maszkokat vagy ős
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+fájlok: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ A hozzáadott szolgáltatásokhoz címkéket lehet beállítani:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/hu/extensions.texy b/dependency-injection/hu/extensions.texy
index 1064295fba..d46f379952 100644
--- a/dependency-injection/hu/extensions.texy
+++ b/dependency-injection/hu/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $inicializálás .[wiki-method]
 =============================
 
-A konfigurátor a [konténer létrehozása |application:bootstrap#index.php] után hívja meg az inicializálási kódot, amely a `$this->initialization` objektumba való írással jön létre az [addBody() metódus |php-generator:#method-and-function-body] segítségével.
+A konfigurátor a [konténer létrehozása |application:bootstrap#index.php] után hívja meg az inicializálási kódot, amely a `$this->initialization` objektumba való írással jön létre az [addBody() metódus |php-generator:#method-and-function-bodies] segítségével.
 
 Mutatunk egy példát arra, hogyan indíthatunk el egy munkamenetet vagy indíthatunk el szolgáltatásokat, amelyek a `run` címkével rendelkeznek az inicializálási kód segítségével:
 
diff --git a/dependency-injection/hu/factory.texy b/dependency-injection/hu/factory.texy
index 1929e3e8ec..5ae2bec739 100644
--- a/dependency-injection/hu/factory.texy
+++ b/dependency-injection/hu/factory.texy
@@ -170,39 +170,45 @@ Eddig a factories és accessorok csak egy objektumot tudtak létrehozni vagy vis
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Ahelyett, hogy több generált gyárat és accessort adna át, csak egy összetett multifactory-t adhat át.
 
-Alternatívaként több metódus helyett használhatja a `create()` és a `get()` egy paramétert:
+Alternatívaként használhatja a `get()` címet is egy paraméterrel, több metódus helyett:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Ebben az esetben a `MultiFactory::createArticle()` ugyanazt teszi, mint a `MultiFactoryAlt::create('article')`. Az alternatív szintaxisnak azonban van néhány hátránya. Nem egyértelmű, hogy mely `$name` értékek támogatottak, és több különböző `$name` érték használata esetén a visszatérési típus nem adható meg az interfészben.
+Ebben az esetben a `MultiFactory::getArticle()` ugyanazt teszi, mint a `MultiFactoryAlt::get('article')`. Az alternatív szintaxisnak azonban van néhány hátránya. Nem egyértelmű, hogy mely `$name` értékek támogatottak, és a visszatérési típus nem adható meg az interfészben, ha több különböző `$name` értéket használunk.
 
 
 Definíció listával .[#toc-definition-with-a-list]
 -------------------------------------------------
-Hos definiálni egy multifactory-t a konfigurációban? Hozzunk létre három szolgáltatást, amelyeket a multifactory fog visszaadni, és magát a multifactory-t:
+Így több gyárat lehet definiálni a konfigurációban: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Vagy a gyár definíciójában hivatkozással hivatkozhatunk meglévő szolgáltatásokra:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Egy másik lehetőség a multifactory definiálására a [címkék |services#Tag
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/hu/faq.texy b/dependency-injection/hu/faq.texy
index 7bb9fe4437..65c5acc939 100644
--- a/dependency-injection/hu/faq.texy
+++ b/dependency-injection/hu/faq.texy
@@ -61,7 +61,7 @@ Ne feledje, hogy a függőségi injektálásra való áttérés a kód minőség
 
 Miért előnyösebb a kompozíció az örökléssel szemben? .[#toc-why-composition-is-preferred-over-inheritance]
 ----------------------------------------------------------------------------------------------------------
-Az öröklés helyett előnyösebb a kompozíciót használni, mivel ez a kód újrafelhasználhatóságát szolgálja anélkül, hogy aggódnunk kellene a változtatások átcsapó hatása miatt. Így lazább csatolást biztosít, ahol nem kell aggódnunk amiatt, hogy egy kód megváltoztatása más függő kódok megváltoztatását eredményezi. Tipikus példa erre a [konstruktorpokolként |passing-dependencies#Constructor hell] azonosított helyzet.
+Az [öröklés |nette:introduction-to-object-oriented-programming#inheritance] helyett előnyösebb a [kompozíciót |nette:introduction-to-object-oriented-programming#composition] használni, mert ez a kód újrafelhasználását szolgálja anélkül, hogy aggódnunk kellene a változások következményei miatt. Így lazább csatolást biztosít, ahol nem kell aggódnunk amiatt, hogy bizonyos kódok megváltoztatása más függő kódok megváltoztatásának szükségességét eredményezi. Tipikus példa erre a [konstruktorpokolnak |passing-dependencies#Constructor hell] nevezett helyzet.
 
 
 Használható-e a Nette DI Container a Nette rendszeren kívül is? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/hu/global-state.texy b/dependency-injection/hu/global-state.texy
index 3ef1f4916f..1e1c80841e 100644
--- a/dependency-injection/hu/global-state.texy
+++ b/dependency-injection/hu/global-state.texy
@@ -301,4 +301,4 @@ Amikor a kódtervezésről gondolkodik, tartsa szem előtt, hogy minden egyes `s
 
 E folyamat során előfordulhat, hogy egy osztályt fel kell osztanod, mert egynél több felelőssége van. Ne aggódjon emiatt; törekedjen az egy felelősség elvére.
 
-*Köszönöm Miško Hevery-nek, akinek olyan cikkei, mint a [Flaw: Brittle Global State & Singletons (Hiba: Törékeny globális állapot és szingletonok |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] ) képezik e fejezet alapját.*
+*Köszönöm Miško Hevery-nek, akinek olyan cikkei, mint a [Flaw: Brittle Global State & Singletons (Hiba: Törékeny globális állapot és szingletonok |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] ) képezik e fejezet alapját.*
diff --git a/dependency-injection/hu/passing-dependencies.texy b/dependency-injection/hu/passing-dependencies.texy
index a426543d32..0ec0b57a4c 100644
--- a/dependency-injection/hu/passing-dependencies.texy
+++ b/dependency-injection/hu/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 A probléma akkor jelentkezik, amikor a `BaseClass` osztály konstruktorát meg akarjuk változtatni, például egy új függőség hozzáadásakor. Ekkor a gyerekek összes konstruktorát is módosítani kell. Ami pokollá teszi az ilyen módosítást.
 
-Hogyan lehet ezt megelőzni? A megoldás az, hogy **prioritást adunk a kompozíciónak az örökléssel szemben**.
+Hogyan lehet ezt megelőzni? A megoldás az, hogy **elsőbbséget adunk a [kompozíciónak az örökléssel szemben** |faq#Why composition is preferred over inheritance].
 
-Tehát tervezzük meg a kódot másképp. Kerüljük az absztrakt `Base*` osztályokat. Ahelyett, hogy a `MyClass` a `BaseClass` örökölése révén kapna bizonyos funkciókat, ahelyett, hogy a függőségként kapná meg ezeket a funkciókat:
+Tervezzük meg tehát a kódot másképp. Kerüljük az [absztrakt |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` osztályokat. Ahelyett, hogy a `MyClass` a `BaseClass` osztályból örökölve kapna bizonyos funkciókat, ahelyett, hogy függőségként átadnánk ezeket a funkciókat:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ A setter hívás a DI konténer konfigurációjában a [setup szakaszban |servic
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ A változó beállítását a DI konténer konfigurációjában, a [setup szakas
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/hu/services.texy b/dependency-injection/hu/services.texy
index d1630dc19a..50fb688c91 100644
--- a/dependency-injection/hu/services.texy
+++ b/dependency-injection/hu/services.texy
@@ -2,32 +2,32 @@ Szolgáltatás meghatározások
 ***************************
 
 .[perex]
-A konfigurációban helyezzük el az egyéni szolgáltatások definícióit. Ez a `services` szakaszban történik.
+A konfiguráció az a hely, ahol utasítjuk a DI konténert, hogyan állítsa össze az egyes szolgáltatásokat, és hogyan kapcsolja össze őket más függőségekkel. A Nette egy nagyon világos és elegáns módot biztosít erre.
 
-Például így hozunk létre egy `database` nevű szolgáltatást, amely a `PDO` osztály példánya lesz:
+A NEON konfigurációs fájl `services` szakasza az a hely, ahol definiáljuk az egyéni szolgáltatásainkat és azok konfigurációit. Nézzünk egy egyszerű példát a `database` nevű szolgáltatás definiálására, amely a `PDO` osztály egy példányát képviseli:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-A szolgáltatások elnevezése arra szolgál, hogy [hivatkozni |#Referencing Services] tudjunk rájuk. Ha egy szolgáltatásra nem hivatkozunk, akkor nincs szükség nevet adni neki. Ezért a név helyett csak egy felsoroláspontot használunk:
+Ez a konfiguráció a következő gyári metódust eredményezi a [DI konténerben |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # anonim szolgáltatás
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Az egysoros bejegyzés több sorra bontható, hogy további kulcsokat lehessen hozzáadni, például [setup |#setup]. A `create:` billentyű álneve a `factory:`.
+A szolgáltatásnevek lehetővé teszik, hogy a konfigurációs fájl más részeiben hivatkozzunk rájuk a `@serviceName` formátumban. Ha nincs szükség a szolgáltatás elnevezésére, akkor egyszerűen használhatunk egy felsorolásjelet:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Ezután a szolgáltatást a DI konténerből a `getService()` metódus segítségével hívjuk le név szerint, vagy még jobb esetben a `getByType()` metódus segítségével típus szerint:
+Egy szolgáltatás lekérdezéséhez a DI konténerből a `getService()` metódust használhatjuk a szolgáltatás nevével paraméterként, vagy a `getByType()` metódust a szolgáltatás típusával:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Szolgáltatás létrehozása .[#toc-creating-a-service]
-===================================================
+Szolgáltatás létrehozása .[#toc-service-creation]
+=================================================
 
-Leggyakrabban úgy hozunk létre egy szolgáltatást, hogy egyszerűen létrehozzuk egy osztály példányát:
+Leggyakrabban egy szolgáltatást egyszerűen egy adott osztály példányosításával hozunk létre. Például:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Ami egy gyári metódust generál a [DI konténerben |container]:
+Ha a konfigurációt további kulcsokkal kell bővítenünk, a definíciót több sorban is kibővíthetjük:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Alternatívaként egy kulcsot `arguments` lehet használni [az argumentumok |#Arguments] átadására:
+A `create` kulcsnak van egy aliasa: `factory`, mindkét változat gyakori a gyakorlatban. Javasoljuk azonban a `create` használatát.
+
+A konstruktor argumentumai vagy a létrehozási módszer alternatívaként a `arguments` kulcsban is leírhatók:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Egy statikus módszer is létrehozhat egy szolgáltatást:
+A szolgáltatásokat nem csak egy osztály egyszerű példányosításával kell létrehozni; létrejöhetnek statikus metódusok vagy más szolgáltatások metódusainak hívásából is:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Megfelel a PHP-kódnak:
+Megjegyezzük, hogy az egyszerűség kedvéért a `->` helyett a `::` használjuk, lásd a [kifejezés eszközeit |#expression means]. Ezeket a gyári metódusokat generáljuk:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Egy statikus metódus `My\Database::create()` feltételezhetően rendelkezik egy meghatározott visszatérési értékkel, amelyet a DI konténernek ismernie kell. Ha nem rendelkezik vele, akkor a típusát a konfigurációba írjuk:
+A DI konténernek tudnia kell a létrehozott szolgáltatás típusát. Ha olyan metódussal hozunk létre egy szolgáltatást, amelynek nincs megadott visszatérési típusa, akkor ezt a típust kifejezetten meg kell említenünk a konfigurációban:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-A Nette DI rendkívül hatékony kifejezési lehetőségeket biztosít, amelyekkel szinte bármit leírhatunk. Például egy másik szolgáltatásra való [hivatkozás |#Referencing Services] és annak metódusának meghívása. Az egyszerűség kedvéért a `->` helyett a `::` -t használjuk.
+
+Érvek .[#toc-arguments]
+=======================
+
+A konstruktoroknak és metódusoknak a hagyományos PHP-hoz nagyon hasonló módon adunk át argumentumokat:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Megfelel a PHP-kódnak:
+A jobb olvashatóság érdekében az argumentumokat külön sorokban is felsorolhatjuk. Ebben a formátumban a vesszők használata opcionális:
 
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
-
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-A metódushívások a PHP-hez hasonlóan láncolhatók egymáshoz:
+Az argumentumokat el is nevezhetjük, így nem kell aggódnunk a sorrendjük miatt:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Megfelel a PHP kódnak:
+Ha bizonyos argumentumokat el akar hagyni, és azok alapértelmezett értékét kívánja használni, vagy egy szolgáltatást [automatikus bekötéssel |autowiring] szeretne beilleszteni, használjon aláhúzást:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Az argumentumok lehetnek szolgáltatások, paraméterek és még sok más, lásd a [kifejezés eszközeit |#expression means].
 
-Érvek: .[#toc-arguments]
-========================
 
-A megnevezett paraméterek argumentumok átadására is használhatók:
+Beállítás .[#toc-setup]
+=======================
+
+A `setup` szakaszban definiáljuk azokat a metódusokat, amelyeket a szolgáltatás létrehozásakor meg kell hívni.
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # pozicionális
-		username: root                      # named
-		password: secret                    # named
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-A vesszők használata opcionális, ha az argumentumokat több sorra bontjuk.
+PHP nyelven ez így nézne ki:
 
-Természetesen [más szolgáltatásokat |#Referencing Services] vagy [paramétereket |configuration#parameters] is használhatunk argumentumként:
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
+
+A metódushívások mellett értékeket is átadhat a tulajdonságoknak. Egy elem hozzáadása egy tömbhöz szintén támogatott, de azt idézőjelek közé kell zárni, hogy ne ütközzön a NEON szintaxissal:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Megfelel a PHP-kódnak:
+PHP-ben ez a következőképpen hangzana:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-`_` character, for example `Foo(_, %appDir%)`Vagy még jobb, ha csak a második argumentumot adjuk át megnevezett paraméterként, pl. `Foo(path: %appDir%)`.
-
-A Nette DI és a NEON formátum rendkívül erőteljes kifejezési lehetőségeket biztosít szinte bármi megírásához. Így egy argumentum lehet egy újonnan létrehozott objektum, hívhat statikus metódusokat, más szolgáltatások metódusait, vagy akár globális függvényeket is, speciális jelölés használatával:
+A beállításban statikus módszereket vagy más szolgáltatások metódusait is meghívhatja. Ha az aktuális szolgáltatást kell átadni argumentumként, használja a `@self` címet:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)        # create object
-		DateTime::createFromFormat('Y-m-d') # statikus metódus hívása
-		@anotherService                     # egy másik szolgáltatás átadása
-		@http.request::getRemoteAddress()   # egy másik szolgáltatás metódusának hívása
-		::getenv(NetteMode)                 # globális függvény hívása
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Megfelel a PHP kódnak:
+Vegye figyelembe, hogy az egyszerűség kedvéért a `->` helyett a `::`, lásd a [kifejezés eszközeit |#expression means]. Ez a következő gyári metódust generálja:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-Speciális funkciók .[#toc-special-functions]
---------------------------------------------
-
-Speciális függvényeket is használhat az argumentumokban értékek kiértékelésére vagy negálására:
+Kifejezés Eszközök .[#toc-expression-means]
+===========================================
 
-- `not(%arg%)` negáció
-- `bool(%arg%)` lossless cast to bool
-- `int(%arg%)` veszteségmentes átváltás int-re
-- `float(%arg%)` lossless cast to float
-- `string(%arg%)` lossless cast to string
+A Nette DI kivételesen gazdag kifejezési lehetőségeket biztosít számunkra, lehetővé téve számunkra, hogy szinte bármit megfogalmazzunk. A konfigurációs fájlokban használhatunk [paramétereket |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
+# paraméter
+%wwwDir%
 
-A veszteségmentes átírás abban különbözik a normál PHP átírástól, pl. a `(int)` használatával, hogy a nem numerikus értékek esetén kivételt dob.
+# érték egy paraméterkulcs alatt
+%mailer.user%
 
-Több szolgáltatás is átadható argumentumként. Egy adott típusú (azaz osztály vagy interfész) összes szolgáltatásának tömbjét a `typed()` függvény hozza létre. A függvény kihagyja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva, és több típus is megadható vesszővel elválasztva.
-
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# paraméter egy karakterláncon belül
+'%wwwDir%/images'
 ```
 
-A szolgáltatások tömbjét automatikusan is átadhatja az [automatikus bekötés |autowiring#Collection of Services] segítségével.
-
-A `tagged()` függvény létrehozza az összes, egy adott [címkével |#tags] rendelkező szolgáltatás tömbjét. Több, vesszővel elválasztott címke is megadható.
+Objektumokat is létrehozhatunk, metódusokat és függvényeket hívhatunk:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# hozzon létre egy objektumot
+DateTime()
 
+# statikus metódus hívása
+Collator::create(%locale%)
 
-Szolgáltatásokra való hivatkozás .[#toc-referencing-services]
-=============================================================
+# PHP függvény hívása
+::getenv(DB_USER)
+```
 
-Az egyes szolgáltatásokra a `@` and name, so for example `@database` karakterek segítségével lehet hivatkozni:
+A szolgáltatásokra a nevük vagy a típusuk alapján hivatkozhatunk:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# szolgáltatás név szerint
+@database
+
+# szolgáltatás típusa szerint
+@Nette\Database\Connection
 ```
 
-Megfelel a PHP kódnak:
+Első osztályú hívható szintaxis használata: .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-A névtelen szolgáltatásokra is lehet hivatkozni visszahívással, csak a típusukat (osztály vagy interfész) kell megadni a nevük helyett. Erre azonban az [autowiring |autowiring] miatt általában nincs szükség.
+Konstanciák használata:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# osztálykonstans
+FilesystemIterator::SKIP_DOTS
+
+# globális konstans, amelyet a PHP konstans() függvényével kapunk.
+::constant(PHP_VERSION)
 ```
 
+A metódushívások láncolhatók, akárcsak a PHP-ban. Az egyszerűség kedvéért a `->` helyett a `::` címet használjuk:
 
-Beállítás .[#toc-setup]
-=======================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
 
-A setup szakaszban felsoroljuk a szolgáltatás létrehozásakor meghívandó metódusokat:
+@http.request::getUrl()::getHost()
+# PHP: http.request')->getUrl()->getHost()
+```
+
+Ezek a kifejezések bárhol használhatók a [szolgáltatások létrehozásakor |#Service Creation], az [argumentumokban |#Arguments], a [beállítási |#setup] szakaszban vagy a [paraméterekben |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Megfelel a PHP-kódnak:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Különleges funkciók .[#toc-special-functions]
+---------------------------------------------
 
-Properites is beállítható. Egy elem hozzáadása egy tömbhöz szintén támogatott, és idézőjelek közé kell írni, hogy ne ütközzön a NEON szintaxissal:
+A konfigurációs fájlokon belül használhatja ezeket a speciális funkciókat:
 
+- `not()` az érték negációjához
+- `bool()`, `int()`, `float()`, `string()` a veszteségmentes típusváltáshoz.
+- `typed()` a megadott típusú szolgáltatások tömbjének létrehozásához.
+- `tagged()` egy adott címkével rendelkező összes szolgáltatás tömbjének létrehozásához.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Megfelel a PHP-kódnak:
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-A beállításban azonban statikus metódusok vagy más szolgáltatások metódusai is meghívhatók. Az aktuális szolgáltatást a `@self` címen adjuk át nekik:
+A PHP hagyományos típuskiosztásához képest, mint például a `(int)`, a veszteségmentes típuskiosztás kivételt dob a nem numerikus értékek esetén.
 
+A `typed()` függvény egy adott típusú (osztály vagy interfész) összes szolgáltatásának tömbjét hozza létre. Kizárja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva. Több típus is megadható, vesszővel elválasztva.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Megfelel a PHP kódnak:
+Az [autowiring |autowiring#Collection of Services] használatával egy adott típusú szolgáltatások tömbjét is automatikusan átadhatja argumentumként.
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+A `tagged()` függvény létrehozza a megadott címkével rendelkező összes szolgáltatás tömbjét. Több címke is felsorolható, vesszővel elválasztva.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
 Autowiring .[#toc-autowiring]
 =============================
 
-Az autowired kulccsal kizárható egy szolgáltatás az autowiringből, vagy befolyásolható a viselkedése. További információért lásd [az autowiring fejezetet |autowiring].
+A `autowired` billentyűvel módosíthatja egy adott szolgáltatás autowiring viselkedését. További részletekért lásd [az autowiring fejezetet |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false       # foo-t eltávolítjuk az autowiringből
+		autowired: false     # a foo szolgáltatás ki van zárva az automatikus bekötésből
 ```
 
 
 Címkék .[#toc-tags]
 ===================
 
-A felhasználói információk címkék formájában adhatók hozzá az egyes szolgáltatásokhoz:
+A címkék a szolgáltatások kiegészítő információkkal való kiegészítésére szolgálnak. Egy vagy több címkét rendelhet egy szolgáltatáshoz:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-A címkéknek lehet értékük is:
+A címkék értékeket is hordozhatnak:
 
 ```neon
 services:
@@ -370,14 +363,14 @@ services:
 			logger: monolog.logger.event
 ```
 
-A `tagged()` függvény segítségével bizonyos címkékkel rendelkező szolgáltatások tömbje adható át argumentumként. Több, vesszővel elválasztott címke is megadható.
+A `tagged()` funkcióval lekérdezheti az adott címkékkel rendelkező összes szolgáltatást:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-A szolgáltatások nevei a DI konténerből a `findByTag()` módszerrel szerezhetők be:
+A DI konténerben a `findByTag()` metódus segítségével megkaphatja az összes, egy adott címkével rendelkező szolgáltatás nevét:
 
 ```php
 $names = $container->findByTag('logger');
@@ -386,10 +379,10 @@ $names = $container->findByTag('logger');
 ```
 
 
-Inject Mode .[#toc-inject-mode]
-===============================
+Injektálás mód .[#toc-inject-mode]
+==================================
 
-A `inject: true` flag a függőségek nyilvános változókon keresztüli átadásának aktiválására szolgál az [inject |best-practices:inject-method-attribute#Inject Attributes] annotációval és az [inject*() |best-practices:inject-method-attribute#inject Methods] metódusokkal.
+A `inject: true` jelző használata aktiválja a függőségek átadását nyilvános változókon keresztül az [inject |best-practices:inject-method-attribute#Inject Attributes] megjegyzésekkel és az [inject*() |best-practices:inject-method-attribute#inject Methods] metódusokkal.
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Alapértelmezés szerint a `inject` csak az előadók esetében van aktiválva.
 
 
-A szolgáltatások módosítása .[#toc-modification-of-services]
-============================================================
+Szolgáltatás módosítások .[#toc-service-modifications]
+======================================================
 
-A DI konténerben számos olyan szolgáltatás van, amelyet beépített vagy [a bővítménye |#di-extensions] adott hozzá. Ezeknek a szolgáltatásoknak a definíciói a konfigurációban módosíthatók. Például a `application.application` szolgáltatás esetében, amely alapértelmezés szerint egy `Nette\Application\Application` objektum, megváltoztathatjuk az osztályt:
+A DI konténer számos beépített vagy [felhasználói bővítéssel |#extensions] hozzáadott szolgáltatást tartalmaz. Ezeknek a szolgáltatásoknak a definícióit közvetlenül a konfigurációban módosíthatja. Például megváltoztathatja a `application.application` szolgáltatás osztályát, amely a hagyományos `Nette\Application\Application`, másra:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-A `alteration` jelző tájékoztató jellegű, és azt mondja, hogy csak egy meglévő szolgáltatást módosítunk.
+A `alteration` jelző tájékoztató jellegű, jelzi, hogy csupán egy meglévő szolgáltatást módosítunk.
 
-Hozzáadhatunk egy beállítást is:
+Kiegészíthetjük a beállítást is:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Erre való a `reset`:
+Itt jön jól a `reset`:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-A kiterjesztéssel hozzáadott szolgáltatás is eltávolítható a konténerből:
+Ha egy bővítmény által hozzáadott szolgáltatást szeretne eltávolítani, akkor ezt a következőképpen teheti meg:
 
 ```neon
 services:
diff --git a/dependency-injection/it/autowiring.texy b/dependency-injection/it/autowiring.texy
index 35b1a3f2d4..3c94f70378 100644
--- a/dependency-injection/it/autowiring.texy
+++ b/dependency-injection/it/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Il contenitore DI passa automaticamente un array di servizi che corrispondono al tipo dato. Ometterà i servizi che hanno il cablaggio automatico disattivato.
 
-Se non si può controllare la forma del commento di phpDoc, si può passare un array di servizi direttamente nella configurazione, usando il metodo [`typed()` |services#Special Functions].
+Il tipo nel commento può anche essere della forma `array<int, Class>` oppure `list<Class>`. Se non si può controllare la forma del commento di phpDoc, si può passare un array di servizi direttamente nella configurazione usando [`typed()` |services#Special Functions].
 
 
 Argomenti scalari .[#toc-scalar-arguments]
diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy
index 58a933c479..f1c063c0ad 100644
--- a/dependency-injection/it/configuration.texy
+++ b/dependency-injection/it/configuration.texy
@@ -67,7 +67,7 @@ Come modificare in blocco tutti i servizi di un certo tipo? È necessario chiama
 ```neon
 decorator:
 	# per tutti i servizi che sono istanze di questa classe o interfaccia
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # chiama questo metodo
 			- $absoluteUrls = true # e imposta la variabile
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Se non si usa l'array `$container->parameters`, si può disabilitare l'esportazione dei parametri. Inoltre, si possono esportare solo i tag attraverso i quali si ottengono servizi con il metodo `$container->findByTag(...)`.
+Se non si usa l'array `$container->getParameters()`, si può disabilitare l'esportazione dei parametri. Inoltre, si possono esportare solo i tag attraverso i quali si ottengono servizi con il metodo `$container->findByTag(...)`.
 Se non si chiama affatto il metodo, si può disabilitare completamente l'esportazione dei tag con `false`.
 
 È possibile ridurre in modo significativo i metadati per il [cablaggio automatico |autowiring], specificando le classi utilizzate come parametro del metodo `$container->getByType()`.
@@ -191,20 +191,15 @@ Basta specificare in quali directory (e sottodirectory) devono essere cercate le
 
 ```neon
 search:
-	# scegliete voi stessi i nomi delle sezioni
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Di solito, però, non vogliamo aggiungere tutte le classi e le interfacce, quindi possiamo filtrarle:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtrare per nome di file (string|string[])
 		files:
@@ -220,7 +215,7 @@ Oppure possiamo selezionare le classi che ereditano o implementano almeno una de
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Si possono anche definire regole negative, cioè maschere di nomi di classi o an
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+file: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ I tag possono essere impostati per i servizi aggiunti:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/it/extensions.texy b/dependency-injection/it/extensions.texy
index 380674ded4..e408550d46 100644
--- a/dependency-injection/it/extensions.texy
+++ b/dependency-injection/it/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $inizializzazione .[wiki-method]
 ================================
 
-Il Configuratore chiama il codice di inizializzazione dopo la [creazione del contenitore |application:bootstrap#index.php], che viene creato scrivendo su un oggetto `$this->initialization` con il [metodo addBody() |php-generator:#method-and-function-body].
+Il Configuratore chiama il codice di inizializzazione dopo la [creazione del contenitore |application:bootstrap#index.php], che viene creato scrivendo su un oggetto `$this->initialization` con il [metodo addBody() |php-generator:#method-and-function-bodies].
 
 Verrà mostrato un esempio di come avviare una sessione o servizi che hanno il tag `run` usando il codice di inizializzazione:
 
diff --git a/dependency-injection/it/factory.texy b/dependency-injection/it/factory.texy
index d2645a41ed..5487c86971 100644
--- a/dependency-injection/it/factory.texy
+++ b/dependency-injection/it/factory.texy
@@ -170,39 +170,45 @@ Finora, i factory e gli accessor potevano creare o restituire un solo oggetto. 
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Invece di passare più factory e accessor generati, si può passare un solo multifactory complesso.
 
-In alternativa, si possono usare `create()` e `get()` con un parametro, invece di più metodi:
+In alternativa, si può usare `get()` con un parametro invece di più metodi:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-In questo caso, `MultiFactory::createArticle()` fa la stessa cosa di `MultiFactoryAlt::create('article')`. Tuttavia, la sintassi alternativa presenta alcuni svantaggi. Non è chiaro quali valori di `$name` siano supportati e il tipo di ritorno non può essere specificato nell'interfaccia quando si usano più valori diversi di `$name`.
+In questo caso, `MultiFactory::getArticle()` fa la stessa cosa di `MultiFactoryAlt::get('article')`. Tuttavia, la sintassi alternativa presenta alcuni svantaggi. Non è chiaro quali valori di `$name` siano supportati e il tipo di ritorno non può essere specificato nell'interfaccia quando si usano più valori diversi di `$name`.
 
 
 Definizione con un elenco .[#toc-definition-with-a-list]
 --------------------------------------------------------
-Come definire una multifactory nella propria configurazione? Creiamo tre servizi che saranno restituiti dalla multifactory e la multifactory stessa:
+Questo modo può essere usato per definire una fabbrica multipla nella configurazione: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Oppure, nella definizione del factory, si può fare riferimento a servizi esistenti usando un riferimento:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Un'altra opzione per definire una multifactory è quella di usare i [tag |servic
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/it/faq.texy b/dependency-injection/it/faq.texy
index 4dfa2d5e1a..80ab92df88 100644
--- a/dependency-injection/it/faq.texy
+++ b/dependency-injection/it/faq.texy
@@ -61,7 +61,7 @@ Ricordate che il passaggio alla Dependency Injection è un investimento nella qu
 
 Perché la composizione è preferibile all'ereditarietà? .[#toc-why-composition-is-preferred-over-inheritance]
 ------------------------------------------------------------------------------------------------------------
-È preferibile usare la composizione piuttosto che l'ereditarietà, perché serve a riutilizzare il codice senza doversi preoccupare dell'effetto a cascata delle modifiche. In questo modo si ottiene un accoppiamento più lasco, in cui non ci si deve preoccupare che la modifica di un codice provochi la modifica di un altro codice dipendente. Un esempio tipico è la situazione definita [inferno dei costruttori |passing-dependencies#Constructor hell].
+È preferibile usare la [composizione |nette:introduction-to-object-oriented-programming#composition] invece dell'[ereditarietà |nette:introduction-to-object-oriented-programming#inheritance] perché serve a riutilizzare il codice senza doversi preoccupare delle conseguenze delle modifiche. In questo modo, si ottiene un accoppiamento meno rigido, in cui non ci si deve preoccupare che la modifica di un codice comporti la necessità di modificare altro codice dipendente. Un esempio tipico è la situazione denominata " [inferno dei costruttori |passing-dependencies#Constructor hell]".
 
 
 Nette DI Container può essere utilizzato al di fuori di Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/it/global-state.texy b/dependency-injection/it/global-state.texy
index 11fc656413..3bba0b1c54 100644
--- a/dependency-injection/it/global-state.texy
+++ b/dependency-injection/it/global-state.texy
@@ -301,4 +301,4 @@ Quando si progetta il codice, bisogna tenere presente che ogni `static $foo` rap
 
 Durante questo processo, potreste scoprire che è necessario dividere una classe perché ha più di una responsabilità. Non preoccupatevi di questo; cercate di mantenere il principio di una sola responsabilità.
 
-*Vorrei ringraziare Miško Hevery, i cui articoli, come [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], costituiscono la base di questo capitolo.*
+*Vorrei ringraziare Miško Hevery, i cui articoli, come [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], costituiscono la base di questo capitolo.*
diff --git a/dependency-injection/it/passing-dependencies.texy b/dependency-injection/it/passing-dependencies.texy
index bfd95ad60a..849437fa9c 100644
--- a/dependency-injection/it/passing-dependencies.texy
+++ b/dependency-injection/it/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Il problema si presenta quando si vuole modificare il costruttore della classe `BaseClass`, ad esempio quando viene aggiunta una nuova dipendenza. Allora dobbiamo modificare anche tutti i costruttori dei figli. Il che rende tale modifica un inferno.
 
-Come evitarlo? La soluzione è quella di **privilegiare la composizione rispetto all'ereditarietà**.
+Come evitarlo? La soluzione è quella di **privilegiare la [composizione rispetto all'ereditarietà** |faq#Why composition is preferred over inheritance].
 
-Quindi progettiamo il codice in modo diverso. Eviteremo le classi astratte di `Base*`. Invece di ottenere una funzionalità da `MyClass` ereditando da `BaseClass`, avrà quella funzionalità passata come dipendenza:
+Quindi progettiamo il codice in modo diverso. Eviteremo le classi [astratte |nette:introduction-to-object-oriented-programming#abstract-classes] di `Base*`. Invece di ottenere alcune funzionalità ereditando da `BaseClass`, `MyClass` avrà quella funzionalità passata come dipendenza:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ La chiamata al setter è definita nella configurazione del contenitore DI, nella
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ L'impostazione della variabile è definita nella configurazione del contenitore
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/it/services.texy b/dependency-injection/it/services.texy
index d3b690fe82..d445cbeb8d 100644
--- a/dependency-injection/it/services.texy
+++ b/dependency-injection/it/services.texy
@@ -2,32 +2,32 @@ Definizioni del servizio
 ************************
 
 .[perex]
-La configurazione è il punto in cui si inseriscono le definizioni dei servizi personalizzati. Questo viene fatto nella sezione `services`.
+La configurazione è il luogo in cui si istruisce il contenitore DI su come assemblare i singoli servizi e come collegarli con altre dipendenze. Nette fornisce un modo molto chiaro ed elegante per raggiungere questo obiettivo.
 
-Per esempio, ecco come si crea un servizio chiamato `database`, che sarà un'istanza della classe `PDO`:
+La sezione `services` del file di configurazione di NEON è il luogo in cui si definiscono i servizi personalizzati e le loro configurazioni. Vediamo un semplice esempio di definizione di un servizio chiamato `database`, che rappresenta un'istanza della classe `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-La denominazione dei servizi serve a consentirci di fare [riferimento a |#Referencing Services] essi. Se un servizio non è referenziato, non c'è bisogno di dargli un nome. Per questo motivo, al posto del nome si usa un punto elenco:
+Questa configurazione dà luogo al seguente metodo factory nel [contenitore DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # servizio anonimo
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Una voce di una riga può essere suddivisa in più righe per consentire l'aggiunta di altre chiavi, come [setup |#setup]. L'alias della chiave `create:` è `factory:`.
+I nomi dei servizi consentono di fare riferimento ad essi in altre parti del file di configurazione, utilizzando il formato `@serviceName`. Se non è necessario dare un nome al servizio, si può usare semplicemente un punto:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Si recupera quindi il servizio dal contenitore DI usando il metodo `getService()` per nome o, meglio ancora, il metodo `getByType()` per tipo:
+Per recuperare un servizio dal contenitore DI, si può usare il metodo `getService()` con il nome del servizio come parametro, oppure il metodo `getByType()` con il tipo di servizio:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Creare un servizio .[#toc-creating-a-service]
+Creazione di servizi .[#toc-service-creation]
 =============================================
 
-Il più delle volte, per creare un servizio basta creare un'istanza di una classe:
+Più comunemente, si crea un servizio semplicemente istanziando una classe specifica. Ad esempio:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Il che genererà un metodo factory nel [contenitore DI |container]:
+Se abbiamo bisogno di espandere la configurazione con ulteriori chiavi, la definizione può essere espansa in più righe:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-In alternativa, si può usare una chiave `arguments` per passare gli [argomenti |#Arguments]:
+La chiave `create` ha un alias `factory`, entrambe le versioni sono comuni nella pratica. Tuttavia, si consiglia di utilizzare `create`.
+
+Gli argomenti del costruttore o il metodo di creazione possono essere scritti in alternativa nella chiave `arguments`:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Un metodo statico può anche creare un servizio:
+I servizi non devono essere creati solo tramite la semplice istanziazione di una classe; possono anche derivare dalla chiamata di metodi statici o di altri servizi:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Corrisponde al codice PHP:
+Si noti che per semplicità, al posto di `->`, si usa `::`, vedi [espressione significa |#expression means]. Questi metodi di fabbrica sono generati:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Si presume che un metodo statico `My\Database::create()` abbia un valore di ritorno definito che il contenitore DI deve conoscere. Se non ce l'ha, si scrive il tipo nella configurazione:
+Il contenitore DI deve conoscere il tipo del servizio creato. Se si crea un servizio usando un metodo che non ha un tipo di ritorno specificato, si deve menzionare esplicitamente questo tipo nella configurazione:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Nette DI offre strumenti di espressione estremamente potenti per scrivere quasi tutto. Ad esempio, per fare [riferimento |#Referencing Services] a un altro servizio e chiamare il suo metodo. Per semplicità, si usa `::` invece di `->`.
+
+Argomenti .[#toc-arguments]
+===========================
+
+Passiamo gli argomenti ai costruttori e ai metodi in modo molto simile al normale PHP:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Corrisponde al codice PHP:
+Per una migliore leggibilità, possiamo elencare gli argomenti su righe separate. In questo formato, l'uso delle virgole è facoltativo:
 
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
-
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-Le chiamate ai metodi possono essere concatenate come in PHP:
+È possibile anche dare un nome agli argomenti, in modo da non preoccuparsi del loro ordine:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Corrisponde al codice PHP:
+Se si desidera omettere alcuni argomenti e utilizzare i loro valori predefiniti o inserire un servizio tramite [autocablaggio |autowiring], utilizzare un trattino basso:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Gli argomenti possono essere servizi, parametri e molto altro, vedere i [mezzi di espressione |#expression means].
 
-Argomenti .[#toc-arguments]
-===========================
 
-I parametri denominati possono essere usati anche per passare argomenti:
+Impostazione .[#toc-setup]
+==========================
+
+Nella sezione `setup`, si definiscono i metodi che devono essere richiamati durante la creazione del servizio.
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test' # posizionale
-		username: root                     # nominato
-		password: secret                   # nominato
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-L'uso delle virgole è facoltativo quando si suddividono gli argomenti in più righe.
+In PHP, questo sarebbe simile a:
+
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
 
-Naturalmente, è possibile utilizzare [altri servizi |#Referencing Services] o [parametri |configuration#parameters] come argomenti:
+Oltre alle chiamate di metodo, è possibile passare valori alle proprietà. È supportata anche l'aggiunta di un elemento a un array, ma è necessario racchiuderlo tra virgolette per evitare di scontrarsi con la sintassi NEON:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Corrisponde al codice PHP:
+In PHP, questo si tradurrebbe in:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-Se il primo argomento è [autocablato |autowiring] e si vuole specificare il secondo, omettere il primo con `_` character, for example `Foo(_, %appDir%)`. O meglio ancora, passare solo il secondo argomento come parametro con nome, ad esempio `Foo(path: %appDir%)`.
-
-Nette DI e il formato NEON offrono strumenti espressivi estremamente potenti per scrivere praticamente qualsiasi cosa. Un argomento può essere un oggetto appena creato, si possono chiamare metodi statici, metodi di altri servizi o persino funzioni globali, utilizzando una notazione speciale:
+Nella configurazione, si possono anche chiamare metodi statici o metodi di altri servizi. Se è necessario passare il servizio corrente come argomento, utilizzare `@self`:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)             # creare l'oggetto
-		DateTime::createFromFormat('Y-m-d')      # chiama un metodo statico
-		@anotherService                          # passare un altro servizio
-		@http.request::getRemoteAddress()        # chiamare un altro metodo del servizio
-		::getenv(NetteMode)                      # chiama una funzione globale
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Corrisponde al codice PHP:
+Si noti che per semplicità, al posto di `->`, si usa `::`, vedi [espressione significa |#expression means]. Questo genera il seguente metodo di fabbrica:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-Funzioni speciali .[#toc-special-functions]
--------------------------------------------
-
-È inoltre possibile utilizzare funzioni speciali negli argomenti per eseguire il cast o la negazione dei valori:
+Mezzi di espressione .[#toc-expression-means]
+=============================================
 
-- `not(%arg%)` negazione
-- `bool(%arg%)` cast senza perdite a bool
-- `int(%arg%)` cast senza perdite in int
-- `float(%arg%)` cast senza perdite a float
-- `string(%arg%)` cast senza perdite a stringa
+Nette DI ci fornisce capacità di espressione eccezionalmente ricche, che ci permettono di articolare quasi tutto. Nei file di configurazione, possiamo usare dei [parametri |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
-
-La riscrittura lossless differisce dalla normale riscrittura PHP, ad esempio utilizzando `(int)`, in quanto lancia un'eccezione per i valori non numerici.
+# parametro
+%wwwDir%
 
-È possibile passare più servizi come argomenti. Un array di tutti i servizi di un particolare tipo (cioè, classe o interfaccia) viene creato dalla funzione `typed()`. La funzione ometterà i servizi che hanno il cablaggio automatico disabilitato e si possono specificare più tipi separati da una virgola.
+# valore sotto una chiave di parametro
+%mailer.user%
 
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# parametro all'interno di una stringa
+'%wwwDir%/images'
 ```
 
-È anche possibile passare automaticamente un array di servizi utilizzando l'[autowiring |autowiring#Collection of Services].
-
-Un array di tutti i servizi con un determinato [tag |#tags] viene creato dalla funzione `tagged()`. È possibile specificare più tag separati da una virgola.
+Possiamo anche creare oggetti, chiamare metodi e funzioni:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# creare un oggetto
+DateTime()
 
+# chiamare un metodo statico
+Collator::create(%locale%)
 
-Servizi di riferimento .[#toc-referencing-services]
-===================================================
+# chiamare una funzione PHP
+::getenv(DB_USER)
+```
 
-I singoli servizi sono referenziati utilizzando il carattere `@` and name, so for example `@database`:
+Fare riferimento ai servizi con il loro nome o con il loro tipo:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# servizio per nome
+@database
+
+# servizio per tipo
+@Nette\Database\Connection
 ```
 
-Corrisponde al codice PHP:
+Usare la sintassi dei callable di prima classe: .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-Anche i servizi anonimi possono essere referenziati usando un callback, basta specificare il loro tipo (classe o interfaccia) invece del loro nome. Tuttavia, di solito non è necessario, a causa del [cablaggio automatico |autowiring].
+Utilizzare le costanti:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# costante di classe
+FilesystemIterator::SKIP_DOTS
+
+# costante globale ottenuta con la funzione PHP constant()
+::constant(PHP_VERSION)
 ```
 
+Le chiamate ai metodi possono essere concatenate, proprio come in PHP. Per semplicità, invece di `->`, usiamo `::`:
 
-Configurazione .[#toc-setup]
-============================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
 
-Nella sezione di configurazione vengono elencati i metodi da richiamare durante la creazione del servizio:
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Queste espressioni possono essere utilizzate ovunque durante la [creazione di servizi |#Service Creation], nei [parametri |#Arguments], nella sezione di [impostazione |#setup] o nei [parametri |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Corrisponde al codice PHP:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Funzioni speciali .[#toc-special-functions]
+-------------------------------------------
 
-È possibile impostare anche le proprietà. È supportata anche l'aggiunta di un elemento a un array, che deve essere scritto tra virgolette per non entrare in conflitto con la sintassi NEON:
+All'interno dei file di configurazione è possibile utilizzare queste funzioni speciali:
 
+- `not()` per la negazione dei valori
+- `bool()`, `int()`, `float()`, `string()` per la fusione dei tipi senza perdita di informazioni
+- `typed()` per generare un array di tutti i servizi di un tipo specificato
+- `tagged()` per creare un array di tutti i servizi con un determinato tag
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Corrisponde al codice PHP:
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-Tuttavia, anche i metodi statici o i metodi di altri servizi possono essere chiamati nel setup. Si passa il servizio effettivo a loro come `@self`:
+Rispetto al typecasting convenzionale in PHP, come `(int)`, il type casting lossless lancia un'eccezione per i valori non numerici.
 
+La funzione `typed()` crea un array di tutti i servizi di un particolare tipo (classe o interfaccia). Esclude i servizi con il cablaggio automatico disattivato. È possibile specificare più tipi, separati da virgole.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Corrisponde al codice PHP:
+È anche possibile passare automaticamente un array di servizi di un tipo specifico come argomento utilizzando l'[autowiring |autowiring#Collection of Services].
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+La funzione `tagged()` crea un array di tutti i servizi con un tag specificato. È possibile elencare più tag, separati da virgole.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-Cablaggio automatico .[#toc-autowiring]
-=======================================
+Cablaggio auto .[#toc-autowiring]
+=================================
 
-La chiave autowiring può essere usata per escludere un servizio dall'autowiring o per influenzarne il comportamento. Per ulteriori informazioni, vedere il [capitolo sull'autowiring |autowiring].
+Il tasto `autowired` consente di modificare il comportamento del cablaggio automatico per un particolare servizio. Per maggiori dettagli, vedere [il capitolo sul cablaggio automatico |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # foo è rimosso dall'autowiring
+		autowired: false     # il servizio pippo è escluso dal cablaggio automatico
 ```
 
 
 Tag .[#toc-tags]
 ================
 
-Le informazioni sugli utenti possono essere aggiunte ai singoli servizi sotto forma di tag:
+I tag sono utilizzati per aggiungere informazioni supplementari ai servizi. È possibile assegnare uno o più tag a un servizio:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-I tag possono anche avere un valore:
+I tag possono anche contenere dei valori:
 
 ```neon
 services:
@@ -370,14 +363,14 @@ services:
 			logger: monolog.logger.event
 ```
 
-Un array di servizi con determinati tag può essere passato come argomento utilizzando la funzione `tagged()`. Si possono anche specificare più tag separati da una virgola.
+Per recuperare tutti i servizi con tag specifici, è possibile utilizzare la funzione `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-I nomi dei servizi possono essere ottenuti dal contenitore DI con il metodo `findByTag()`:
+Nel contenitore DI, è possibile ottenere i nomi di tutti i servizi con un tag specifico utilizzando il metodo `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
@@ -386,10 +379,10 @@ $names = $container->findByTag('logger');
 ```
 
 
-Modalità Inject .[#toc-inject-mode]
-===================================
+Modalità di iniezione .[#toc-inject-mode]
+=========================================
 
-Il flag `inject: true` è usato per attivare il passaggio di dipendenze tramite variabili pubbliche con l'annotazione [inject |best-practices:inject-method-attribute#Inject Attributes] e i metodi [inject*() |best-practices:inject-method-attribute#inject Methods].
+L'uso del flag `inject: true` attiva il passaggio delle dipendenze tramite variabili pubbliche con l'annotazione [inject |best-practices:inject-method-attribute#Inject Attributes] e i metodi [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Per impostazione predefinita, `inject` è attivato solo per i presentatori.
 
 
-Modifica dei servizi .[#toc-modification-of-services]
-=====================================================
+Modifiche del servizio .[#toc-service-modifications]
+====================================================
 
-Nel contenitore DI sono presenti diversi servizi aggiunti da un'[estensione |#di-extensions] incorporata o dall'[utente |#di-extensions]. Le definizioni di questi servizi possono essere modificate nella configurazione. Ad esempio, per il servizio `application.application`, che per impostazione predefinita è un oggetto `Nette\Application\Application`, si può cambiare la classe:
+Il contenitore DI contiene molti servizi aggiunti da [estensioni |#extensions] integrate o dall'[utente |#extensions]. È possibile modificare le definizioni di questi servizi direttamente nella configurazione. Per esempio, si può cambiare la classe del servizio `application.application`, che è convenzionalmente `Nette\Application\Application`, in un'altra:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Il flag `alteration` è informativo e indica che stiamo solo modificando un servizio esistente.
+Il flag `alteration` è informativo e indica che stiamo semplicemente modificando un servizio esistente.
 
-Possiamo anche aggiungere una configurazione:
+Possiamo anche completare la configurazione:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Quando si riscrive un servizio, si possono rimuovere gli argomenti originali, gli elementi di configurazione o i tag, a questo serve `reset`:
+Quando si sovrascrive un servizio, si potrebbe voler rimuovere gli argomenti originali, gli elementi di configurazione o i tag, ed è qui che `reset` si rivela utile:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Un servizio aggiunto per estensione può anche essere rimosso dal contenitore:
+Se si desidera rimuovere un servizio aggiunto da un'estensione, è possibile farlo in questo modo:
 
 ```neon
 services:
diff --git a/dependency-injection/ja/autowiring.texy b/dependency-injection/ja/autowiring.texy
index b968fa720e..9d99f3d2fb 100644
--- a/dependency-injection/ja/autowiring.texy
+++ b/dependency-injection/ja/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 DI コンテナは、指定した型に対応するサービスの配列を自動的に渡します。DI コンテナは、指定した型に対応するサービスの配列を自動的に渡します。自動配線が無効になっているサービスは省略されます。
 
-phpDoc のコメントの形式を制御できない場合は、 サービスの配列を直接設定に渡すこともできます。 [`typed()` |services#Special Functions].
+コメントの型は、以下の形式も可能である。 `array<int, Class>`または `list<Class>`.phpDoc のコメントの形式を制御できない場合は、 サービスの配列を直接渡すこともできます。 [`typed()` |services#Special Functions].
 
 
 スカラー引数 .[#toc-scalar-arguments]
diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy
index 6da88d5eec..e2c485badc 100644
--- a/dependency-injection/ja/configuration.texy
+++ b/dependency-injection/ja/configuration.texy
@@ -67,7 +67,7 @@ parameters:
 ```neon
 decorator:
 	# for all services that are instances of this class or interface
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # call this method
 			- $absoluteUrls = true   # and set the variable
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-`$container->parameters` 配列を使用しない場合は、パラメータのエクスポートを無効にすることができます。さらに、`$container->findByTag(...)` メソッドを使って、サービスを取得するタグだけをエクスポートすることができます。
+`$container->getParameters()` 配列を使用しない場合は、パラメータのエクスポートを無効にすることができます。さらに、`$container->findByTag(...)` メソッドを使って、サービスを取得するタグだけをエクスポートすることができます。
 このメソッドを全く呼び出さない場合は、`false` を使ってタグのエクスポートを完全に無効にすることができます。
 
 `$container->getByType()` メソッドのパラメータとして使用するクラスを指定すれば、[自動配線の |autowiring]ためのメタデータを大幅に減らすことができます。
@@ -191,20 +191,15 @@ DIコンテナにサービスを自動追加することで、非常に快適に
 
 ```neon
 search:
-	# you choose the section names yourself
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 しかし、通常は、すべてのクラスとインターフェイスを追加したくないので、フィルタリングすることができます。
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtering by file name (string|string[])
 		files:
@@ -220,7 +215,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+ファイル: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/ja/extensions.texy b/dependency-injection/ja/extensions.texy
index beccfd35c0..4c41625fb1 100644
--- a/dependency-injection/ja/extensions.texy
+++ b/dependency-injection/ja/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialization .[wiki-method]
 ==============================
 
-Configurator は、[コンテナ作成 |application:en:bootstrap#index.php]後に初期化コードを呼び出します。このコードは、[メソッド addBody() |php-generator:#method-and-function-body] を使用してオブジェクト`$this->initialization` に書き込むことで作成されます。
+Configurator は、[コンテナ作成 |application:en:bootstrap#index.php]後に初期化コードを呼び出します。このコードは、[メソッド addBody() |php-generator:#method-and-function-bodies] を使用してオブジェクト`$this->initialization` に書き込むことで作成されます。
 
 ここでは、初期化コードを用いて、セッションの開始や、`run` タグを持つサービスの開始を行う例を示します。
 
diff --git a/dependency-injection/ja/factory.texy b/dependency-injection/ja/factory.texy
index 726203ee1b..e5e83e538e 100644
--- a/dependency-injection/ja/factory.texy
+++ b/dependency-injection/ja/factory.texy
@@ -170,39 +170,45 @@ services:
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 生成された複数のファクトリーとアクセッサを渡す代わりに、複雑なマルチファクトリーを1つだけ渡すことができます。
 
-あるいは、複数のメソッドの代わりに、パラメータで`create()` と`get()` を使うこともできます。
+あるいは、複数のメソッドの代わりに、`get()` をパラメータ付きで使うこともできる:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-この場合、`MultiFactory::createArticle()` は`MultiFactoryAlt::create('article')` と同じことをします。 しかし、この代替構文にはいくつかの欠点があります。どの`$name` の値がサポートされているかは不明ですし、複数の異なる`$name` の値を使用する場合、インターフェースで戻り値の型を指定することができません。
+この場合、`MultiFactory::getArticle()` は`MultiFactoryAlt::get('article')` と同じことをする。 しかし、この代替構文にはいくつかの欠点がある。どの`$name` 値がサポートされているのかが明確でないことと、複数の異なる`$name` 値を使用する場合、インターフェイスで戻り値の型を指定できないことである。
 
 
 リストを使った定義 .[#toc-definition-with-a-list]
 ----------------------------------------
-マルチファクトリーを構成で定義する方法は?マルチファクトリーから返される3つのサービスと、マルチファクトリーそのものを作成してみましょう。
+この方法は、コンフィギュレーションで複数のファクトリーを定義するのに使える:.{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+あるいは、ファクトリーの定義で、参照を使用して既存のサービスを参照できます:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ services:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/ja/faq.texy b/dependency-injection/ja/faq.texy
index f8656dc7a5..f972f6d088 100644
--- a/dependency-injection/ja/faq.texy
+++ b/dependency-injection/ja/faq.texy
@@ -61,7 +61,7 @@ Dependency Injectionへの移行は、コードの品質とアプリケーショ
 
 なぜコンポジションが継承より好まれるのか? .[#toc-why-composition-is-preferred-over-inheritance]
 ---------------------------------------------------------------------------
-継承ではなく、コンポジションを使用することが望ましい。あるコードを変更すると、他の依存するコードも変更しなければならなくなるという心配がないため、より緩やかな結合が可能になります。典型的な例として、「[コンストラクタ地獄 |passing-dependencies#Constructor hell]」と呼ばれる状況があります。
+[継承の |nette:en:introduction-to-object-oriented-programming#inheritance]代わりに[コンポジションを |nette:en:introduction-to-object-oriented-programming#composition]使うのが望ましいのは、コンポジションは変更の結果を気にすることなくコードを再利用できるからだ。そのため、あるコードを変更すると、他の依存するコードも変更しなければならなくなるという心配をする必要がない。典型的な例は、[コンストラクタ地獄 |passing-dependencies#Constructor hell]と呼ばれる状況だ。
 
 
 ネッテDIコンテナは、ネッテ以外でも使えるのですか? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/ja/global-state.texy b/dependency-injection/ja/global-state.texy
index 7622def46d..7967ed3628 100644
--- a/dependency-injection/ja/global-state.texy
+++ b/dependency-injection/ja/global-state.texy
@@ -301,4 +301,4 @@ class Foo
 
 この過程で、クラスが複数の責任を持つため、クラスを分割する必要があることがわかるかもしれません。そのようなことは気にせず、1つの責任という原則を貫くようにしましょう。
 
-*本章は、Miško Hevery氏の「[Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/]」等の論文に基づくものです。
+*本章は、Miško Hevery氏の「[Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/]」等の論文に基づくものです。
diff --git a/dependency-injection/ja/passing-dependencies.texy b/dependency-injection/ja/passing-dependencies.texy
index 22d913aed6..6b7d36c81b 100644
--- a/dependency-injection/ja/passing-dependencies.texy
+++ b/dependency-injection/ja/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 問題は、新しい依存関係が追加されたときなど、`BaseClass` クラスのコンストラクタを変更したいときに発生します。そうすると、子クラスのコンストラクタもすべて変更しなければならない。そのため、このような修正は地獄のようなものです。
 
-これを防ぐにはどうしたらいいのでしょうか?解決策は、**継承よりも構成を優先させる**ことです。
+これを防ぐには?解決策は、**[継承よりもコンポジションを |faq#Why composition is preferred over inheritance]優先させる[** |faq#Why composition is preferred over inheritance]ことだ。
 
-そこで、コードを違った形で設計してみましょう。抽象的な`Base*` クラスは避けることにします。`MyClass` が`BaseClass` を継承して機能を得る代わりに、その機能は依存関係として渡されるようにします。
+そこで、コードを別の方法で設計してみよう。[抽象的な |nette:en:introduction-to-object-oriented-programming#abstract-classes] `Base*` クラスは避けよう。`MyClass` が`BaseClass` を継承して機能を得る代わりに、その機能は依存関係として渡されます:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ setter の呼び出しは、DI コンテナの設定[セクション setup |serv
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ $obj->cache = $cache;
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/ja/services.texy b/dependency-injection/ja/services.texy
index f4b2054bee..1f8dcf2e30 100644
--- a/dependency-injection/ja/services.texy
+++ b/dependency-injection/ja/services.texy
@@ -2,32 +2,32 @@
 ******
 
 .[perex]
-コンフィギュレーションは、カスタムサービスの定義を配置する場所です。これは、セクション`services` で行います。
+コンフィギュレーションは、DIコンテナに対して、個々のサービスの組み立て方や、他の依存関係との接続方法を指示する場所です。Netteは、これを実現するための非常に明確でエレガントな方法を提供します。
 
-例えば、これは`database` という名前のサービスを作成する方法で、これはクラス`PDO` のインスタンスになります。
+NEON設定ファイルの`services` セクションは、カスタムサービスとその設定を定義する場所です。`PDO` クラスのインスタンスを表す`database` というサービスを定義する簡単な例を見てみましょう:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-サービスの名前付けは,サービスを[参照 |#Referencing Services]できるようにするために行います.もしサービスが参照されないのであれば、名前を付ける必要はありません。そこで、名前の代わりに箇条書きを使っているだけです。
+この設定により、[DIコンテナの |container]ファクトリーメソッドは次のようになります:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  #  anonymous service
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-1行のエントリーを複数行に分割して、[setupなどの |#setup]キーを追加できるようにすることも可能です。`create:` キーのエイリアスは、`factory:` です。
+サービス名は、設定ファイルの他の部分で参照できるようにするためのもので、`@serviceName`.サービス名を付ける必要がない場合は、単に箇条書きを使用できます:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-次に、DIコンテナからサービスを取り出すには、名前を指定して`getService()` というメソッドを使うか、種類を指定して`getByType()` というメソッドを使うとよいでしょう。
+DIコンテナからサービスを取得するには、`getService()` メソッドにサービス名をパラメータとして指定するか、`getByType()` メソッドにサービスタイプを指定して指定します:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-サービスの作成 .[#toc-creating-a-service]
-==================================
+サービスクリエーション .[#toc-service-creation]
+====================================
 
-多くの場合、サービスの作成は単にクラスのインスタンスを作成することで行います。
+ほとんどの場合、特定のクラスをインスタンス化するだけでサービスを作成します。例えば
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-この場合、[DIコンテナ |container]内にファクトリーメソッドが生成されます。
+追加のキーで設定を拡張する必要がある場合、定義を複数行に拡張することができます:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-また、[引数の |#Arguments]受け渡しにキー`arguments` を使うこともできます。
+`create` キーには`factory` という別名がある。しかし、`create` の使用を推奨する。
+
+コンストラクタの引数や作成メソッドは、`arguments` キーに記述することもできる:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-静的メソッドは、サービスを作成することもできます。
+静的メソッドや他のサービスのメソッドを呼び出すことによって生成されることもあります:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-PHP のコードに対応します。
+簡単にするために、`->` の代わりに`::` を使うことに注意[。 |#expression means]これらのファクトリーメソッドは生成されます:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-静的メソッド`My\Database::create()` は、DI コンテナが知る必要のある戻り値が定義されていることが前提です。もしそれがない場合は、その型を設定に書き込みます。
+DIコンテナは、作成されたサービスのタイプを知る必要がある。戻り値の型が指定されていないメソッドを使用してサービスを作成する場合は、設定にこの型を明示的に記述する必要があります:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Nette DIは、非常に強力な表現機能を備えており、ほとんど何でも書くことができます。例えば、他のサービスを[参照して |#Referencing Services]、そのメソッドを呼び出すことができます。簡単のために、`->` の代わりに`::` を使用します。
+
+引数 .[#toc-arguments]
+====================
+
+コンストラクタやメソッドに引数を渡す方法は、通常のPHPとよく似ています:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-PHPのコードに対応します。
-
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
+読みやすくするために、引数を別々の行に書くこともできます。この形式では、カンマの使用は任意です:
 
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-PHPのようにメソッドコールを連鎖させることができます。
+また、引数に名前を付けることもでき、その場合は順番を気にする必要はありません:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-PHPのコードに対応しています。
+特定の引数を省略してデフォルト値を使用したい場合や、[自動配線で |autowiring]サービスを挿入したい場合は、アンダースコアを使用します:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+引数には、サービス、パラメータ、その他いろいろなものがあります[。 |#expression means]
 
-引数 .[#toc-arguments]
+
+セットアップ .[#toc-setup]
 ====================
 
-名前付きパラメータは引数の受け渡しに使うこともできます。
+`setup` セクションでは、サービスを作成する際に呼び出されるメソッドを定義します。
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # positional
-		username: root                      # named
-		password: secret                    # named
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-引数を複数行に分ける場合、カンマの使用は任意である。
+PHPでは次のようになります:
 
-もちろん、[他のサービスや |#Referencing Services] [パラメータを |configuration#parameters]引数として使用することもできます。
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
+
+メソッド呼び出しに加えて、プロパティに値を渡すこともできます。配列への要素の追加もサポートされていますが、NEON構文と衝突しないように引用符で囲む必要があります:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-PHPのコードに対応します。
+PHPでは次のようになります:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-第一引数が[自動生成で |autowiring]、第二引数を指定したい場合は、第一引数を省略して`_` character, for example `Foo(_, %appDir%)`. あるいは、第二引数のみを名前付きパラメータとして渡すのがよいでしょう。例えば、`Foo(path: %appDir%)`.
-
-Nette DI と NEON フォーマットは、ほとんど何でも書くことができる非常に強力な表現力を持っています。そのため、引数には新しく作成したオブジェクトを指定したり、静的メソッドや他のサービスのメソッドを呼び出したり、特殊な記法を使ってグローバルな関数を呼び出すこともできます。
+セットアップでは、静的メソッドや他のサービスのメソッドを呼び出すこともできます。現在のサービスを引数として渡す必要がある場合は、`@self` :
 
 ```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(NetteMode)                  # call a global function
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-PHPのコードに対応します。
+簡単のため、`->` の代わりに、`::` を使用することに注意して[ください |#expression means]。これにより、以下のファクトリーメソッドが生成される:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-特殊機能 .[#toc-special-functions]
-------------------------------
-
-引数で特殊関数を使用し、値のキャストやネゲートを行うこともできます。
+表現方法 .[#toc-expression-means]
+=============================
 
--`not(%arg%)` 負論理
--`bool(%arg%)` 無損失な bool へのキャスト
--`int(%arg%)` int へのロスレスキャスト
--`float(%arg%)` float へのロスレスキャスト
--`string(%arg%)` ロスレス キャストから文字列
+Nette DIは、非常に豊富な表現機能を備えており、ほとんど何でも表現することができます。設定ファイルでは、[パラメータを |configuration#parameters]使うことができます:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
-
-ロスレス書き換えは、通常の PHP の書き換え (`(int)` など) とは異なり、数値以外の値では例外がスローされます。
+# parameter
+%wwwDir%
 
-引数として、複数のサービスを渡すことができます。特定の型 (クラスやインターフェイス) のすべてのサービスの配列は、関数`typed()` で作成されます。この関数では,自動配線を無効にしているサービスは省略されます.また,複数のタイプをカンマで区切って指定することもできます.
+# value under a parameter key
+%mailer.user%
 
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# parameter within a string
+'%wwwDir%/images'
 ```
 
-また,[autowiringを |autowiring#Collection of Services]使用して,自動的にサービスの配列を渡すこともできます.
-
-ある[タグを |#tags]持つすべてのサービスの配列を関数`tagged()` で作成します.タグはカンマで区切って複数指定することができます。
+また、オブジェクトを作成したり、メソッドや関数を呼び出したりすることもできます:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# create an object
+DateTime()
 
+# call a static method
+Collator::create(%locale%)
 
-参照先サービス .[#toc-referencing-services]
-====================================
+# call a PHP function
+::getenv(DB_USER)
+```
 
-個々のサービスの参照には、`@` and name, so for example `@database` を使用します。
+サービスを名前またはタイプで参照する:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# service by name
+@database
+
+# service by type
+@Nette\Database\Connection
 ```
 
-PHPのコードに対応します。
+ファーストクラスの callable 構文を使用する:.{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-匿名サービスでもコールバックを使って参照することができます。ただし、[自動配線の |autowiring]関係で通常は必要ありません。
+定数を使用する:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# class constant
+FilesystemIterator::SKIP_DOTS
+
+# global constant obtained by the PHP function constant()
+::constant(PHP_VERSION)
 ```
 
+Method calls can be chained, just like in PHP. For simplicity, instead of `->`, we use `::`:
 
-セットアップ .[#toc-setup]
-====================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
 
-セットアップでは、サービスを作成する際に呼び出されるメソッドをリストアップします。
+これらの式は、[サービスを作成する |#Service Creation]際、[引数 |#Arguments]、[設定 |#setup]セクション、[パラメータなど |configuration#parameters]、どこでも使用できます:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-PHPのコードに対応します。
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+特殊機能 .[#toc-special-functions]
+------------------------------
 
-プロパティを設定することも可能です。配列への要素の追加もサポートされており、NEON の構文と衝突しないように引用符で囲んで記述する必要があります。
+コンフィギュレーション・ファイル内では、これらの特殊関数を利用することができます:
 
+-`not()` 値の否定
+-`bool()`,`int()`,`float()`,`string()` によるロスレス型キャスト
+-`typed()` 指定された型のすべてのサービスの配列を生成する。
+-`tagged()` 指定されたタグを持つすべてのサービスの配列を作成する。
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-PHP のコードに対応します。
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-ただし、静的メソッドや他のサービスのメソッドもセットアップで呼び出すことができます。それらには、実際のサービスを`@self` として渡します。
+`(int)` のような PHP の従来の型キャストと比較すると、 ロスレス型キャストは数値以外の値に対して例外をスローします。
 
+`typed()` 関数は、特定の型 (クラスまたはインターフェイス) のすべてのサービスの配列を作成します。自動配線をオフにしたサービスは除外されます。複数の型をカンマ区切りで指定することができます。
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-PHPのコードに対応する。
+また、[自動配線を |autowiring#Collection of Services]使用して、特定のタイプのサービスの配列を自動的に引数として渡すこともできます。
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+`tagged()` 関数は、指定されたタグを持つすべてのサービスの配列を作成します。複数のタグをカンマ区切りで列挙できます。
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-オートワイヤリング .[#toc-autowiring]
-============================
+自動配線 .[#toc-autowiring]
+=======================
 
-autowiredキーは、あるサービスを自動配線から除外したり、その動作に影響を与えたりするために使用されます。詳細については、「自動配線」の[章を |autowiring]参照してください。
+`autowired` キーにより、特定のサービスの自動配線の動作を変更することができます。詳細は自動配線の[章を |autowiring]参照してください。
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo is removed from autowiring
+		autowired: false     # fooサービスは自動配線の対象外です。
 ```
 
 
 タグ .[#toc-tags]
 ===============
 
-個々のサービスには、タグという形でユーザー情報を付加することができます。
+タグはサービスに補足情報を追加するために使用します。サービスには1つ以上のタグを割り当てることができます.
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-タグは値を持つこともできます。
+タグは値を持つこともできます:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-特定のタグを持つサービスの配列は,関数`tagged()` を使って引数として渡すことができます.カンマで区切って複数のタグを指定することもできます.
+特定のタグを持つすべてのサービスを検索するには、`tagged()` 関数を使用できます:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-サービス名は,DIコンテナから`findByTag()` というメソッドで取得することができる.
+DIコンテナでは、`findByTag()` メソッドを使用して、特定のタグを持つすべてのサービス名を取得できます:
 
 ```php
 $names = $container->findByTag('logger');
-// $names is an array containing the service name and tag value
-// i.e. ['foo' => 'monolog.logger.event', ...]
+// namesはサービス名とタグの値を含む配列です。
+ 例えば ['foo' => 'monolog.logger.event', ...] などです。
 ```
 
 
 インジェクトモード .[#toc-inject-mode]
 =============================
 
-`inject: true` フラグは、[inject |best-practices:en:inject-method-attribute#Inject Attributes]アノテーションと[inject*() |best-practices:en:inject-method-attribute#inject Methods]メソッドによるパブリック変数経由の依存関係の受け渡しを有効にするために使用されます。
+フラグ`inject: true` を使用すると、[inject |best-practices:en:inject-method-attribute#Inject Attributes]アノテーションと[inject*() |best-practices:en:inject-method-attribute#inject Methods]メソッドでパブリック変数を介した依存関係の受け渡しが有効になります。
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 デフォルトでは、`inject` はプレゼンターに対してのみ有効です。
 
 
-サービスの変更 .[#toc-modification-of-services]
-========================================
+サービスの変更 .[#toc-service-modifications]
+=====================================
 
-DIコンテナには、ビルトインまたは[拡張機能 |#di-extensions]によって追加されたサービスが多数存在します。これらのサービスの定義は、コンフィギュレーションで変更することができます。例えば、サービス`application.application` 、デフォルトではオブジェクト`Nette\Application\Application` 、クラスを変更することができます。
+DIコンテナには、組み込みまたは[ユーザーによる拡張によって |#extensions]追加された多くのサービスが含まれています。これらのサービスの定義は、コンフィギュレーションで直接変更できます。たとえば、従来は`Nette\Application\Application` であった`application.application` サービスのクラスを別のものに変更することができます:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-`alteration` フラグは情報提供であり、既存のサービスを変更するだけであることを示します。
+`alteration` フラグは、単に既存のサービスを変更するだけであることを示す情報的なものである。
 
-また、セットアップを追加することもできます。
+セットアップを補足することもできる:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-サービスを書き換える際、元の引数や設定項目、タグを削除したい場合があります。そのために、`reset` 。
+サービスを上書きする際に、オリジナルの引数や設定項目、タグを削除したい場合があります。このような場合に便利なのが、`reset` :
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-拡張で追加されたサービスもコンテナから削除することができます.
+拡張機能によって追加されたサービスを削除したい場合は、次のようにします:
 
 ```neon
 services:
diff --git a/dependency-injection/pl/autowiring.texy b/dependency-injection/pl/autowiring.texy
index e9c7612788..eba26cb570 100644
--- a/dependency-injection/pl/autowiring.texy
+++ b/dependency-injection/pl/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Następnie kontener DI automatycznie przekaże tablicę usług pasujących do tego typu. Pominie usługi, które mają wyłączone autowiring.
 
-Jeśli nie możesz kontrolować formy komentarza phpDoc, możesz przekazać pole usługi bezpośrednio w konfiguracji za pomocą [`typed()` |services#Special-Functions].
+Typ w komentarzu może mieć również postać `array<int, Class>` lub `list<Class>`. Jeśli nie możesz kontrolować formy komentarza phpDoc, możesz przekazać tablicę usług bezpośrednio w konfiguracji za pomocą [`typed()` |services#Special Functions].
 
 
 Argumenty skalarne .[#toc-scalar-arguments]
diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy
index 111cbc9e1e..2e1ec832d2 100644
--- a/dependency-injection/pl/configuration.texy
+++ b/dependency-injection/pl/configuration.texy
@@ -67,7 +67,7 @@ Jak masowo edytować wszystkie usługi danego typu? Na przykład wywołaj okreś
 ```neon
 decorator:
 	# dla wszystkich usług, które są instancjami tej klasy lub interfejsu
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # wywołaj tę metodę
 			- $absoluteUrls = true # i ustawić zmienną
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Jeśli nie używasz pola `$container->parameters`, możesz wyłączyć eksport parametrów. Można również wyeksportować tylko te tagi, za pośrednictwem których uzyskuje się usługi metodą `$container->findByTag(...)`.
+Jeśli nie używasz pola `$container->getParameters()`, możesz wyłączyć eksport parametrów. Można również wyeksportować tylko te tagi, za pośrednictwem których uzyskuje się usługi metodą `$container->findByTag(...)`.
 Jeśli w ogóle nie wywołujesz metody, możesz całkowicie wyłączyć eksport tagów za pomocą `false`.
 
 Możesz znacznie zmniejszyć metadane dla [autowiring |autowiring], określając klasy, których używasz jako parametr metody `$container->getByType()`.
@@ -191,20 +191,15 @@ Wystarczy określić, w których katalogach (i podkatalogach) szukać klas:
 
 ```neon
 search:
-	# wybierasz nazwy sekcji
-	formy:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Zazwyczaj nie chcemy dodawać wszystkich klas i interfejsów, więc możemy je filtrować:
 
 ```neon
 search:
-	Formy:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filter by filename (string|string[])
 		files:
@@ -220,7 +215,7 @@ Możemy też wybrać klasy, które dziedziczą lub implementują przynajmniej je
 
 ```neon
 search:
-	formuláře:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Można również zdefiniować reguły wykluczenia, czyli maski nazw klas lub dzi
 
 ```neon
 search:
-	formuláře:
+	-	in: %appDir%
 		exclude:
+pliki: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Wszystkie usługi mogą być oznakowane:
 
 ```neon
 search:
-	formuláře:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/pl/extensions.texy b/dependency-injection/pl/extensions.texy
index 4f1d5723c1..0e1d1e1128 100644
--- a/dependency-injection/pl/extensions.texy
+++ b/dependency-injection/pl/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $inicjalizacja .[wiki-method][#toc-initialization]
 ==================================================
 
-Po [utworzeniu kontenera |application:bootstrap#index-php] klasa Configurator wywołuje kod inicjalizacyjny, który powstaje poprzez zapis do obiektu `$this->initialization` za pomocą [metody addBody() |php-generator:#Method-and-Function-Body].
+Po [utworzeniu kontenera |application:bootstrap#index-php] klasa Configurator wywołuje kod inicjalizacyjny, który powstaje poprzez zapis do obiektu `$this->initialization` za pomocą [metody addBody() |php-generator:#method-and-function-bodies].
 
 Pokażemy przykład, jak np. kod inicjalizujący może uruchomić sesję lub uruchomić usługi, które mają znacznik `run`:
 
diff --git a/dependency-injection/pl/factory.texy b/dependency-injection/pl/factory.texy
index 6a55c713ca..f566dad4ee 100644
--- a/dependency-injection/pl/factory.texy
+++ b/dependency-injection/pl/factory.texy
@@ -170,39 +170,45 @@ Dotychczas nasze fabryki i accessory były w stanie wyprodukować lub zwrócić
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Więc zamiast przekazywać kilka wygenerowanych fabryk i accessorów, przekazujemy jedną bardziej złożoną fabrykę, która może zrobić więcej.
 
-Alternatywnie, zamiast korzystać z wielu metod, możemy użyć `create()` i `get()` z parametrem:
+Alternatywnie można użyć `get()` z parametrem zamiast wielu metod:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Następnie `MultiFactory::createArticle()` robi to samo, co `MultiFactoryAlt::create('article')`. Jednak alternatywna notacja ma tę wadę, że nie jest oczywiste, jakie wartości `$name` są obsługiwane, a logicznie nie jest również możliwe wyróżnienie różnych wartości zwrotnych dla różnych `$name` w interfejsie.
+W tym przypadku `MultiFactory::getArticle()` robi to samo, co `MultiFactoryAlt::get('article')`. Alternatywna składnia ma jednak kilka wad. Nie jest jasne, które wartości `$name` są obsługiwane, a typ zwracany nie może być określony w interfejsie, gdy używanych jest wiele różnych wartości `$name`.
 
 
 Definicja według listy .[#toc-definition-with-a-list]
 -----------------------------------------------------
-I jak zdefiniować wiele fabryk w konfiguracji? Tworzymy trzy serwisy, które będą tworzyć/zwracać, a następnie samą fabrykę:
+W ten sposób można zdefiniować wiele fabryk w konfiguracji: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Lub w definicji fabryki możemy odwołać się do istniejących usług za pomocą referencji:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Druga opcja to użycie [tagów |services#Tags] do definicji:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/pl/faq.texy b/dependency-injection/pl/faq.texy
index 46b1bd8cc7..7441e70a05 100644
--- a/dependency-injection/pl/faq.texy
+++ b/dependency-injection/pl/faq.texy
@@ -61,7 +61,7 @@ Pamiętaj, że przejście na Dependency Injection jest inwestycją w jakość ko
 
 Dlaczego kompozycja jest preferowana nad dziedziczeniem? .[#toc-why-composition-is-preferred-over-inheritance]
 --------------------------------------------------------------------------------------------------------------
-Lepiej jest używać kompozycji niż dziedziczenia, ponieważ służy to celowi ponownego użycia kodu bez potrzeby martwienia się o efekt podstępnej zmiany. W ten sposób zapewnia bardziej luźne sprzężenie, gdzie nie musimy się martwić o to, że zmiana jakiegoś kodu powoduje, że inny zależny kod wymaga zmiany. Typowym przykładem jest sytuacja określona jako [piekło konstruktorów |passing-dependencies#Constructor hell].
+Preferowane jest użycie [kompozycji |nette:introduction-to-object-oriented-programming#composition] zamiast [dziedziczenia |nette:introduction-to-object-oriented-programming#inheritance], ponieważ służy ona do ponownego wykorzystania kodu bez konieczności martwienia się o konsekwencje zmian. W ten sposób zapewnia luźniejsze sprzężenie, w którym nie musimy się martwić, że zmiana jakiegoś kodu spowoduje konieczność zmiany innego zależnego kodu. Typowym przykładem jest sytuacja określana jako piekło [konstruktorów |passing-dependencies#Constructor hell].
 
 
 Czy Nette DI Container może być używany poza Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/pl/global-state.texy b/dependency-injection/pl/global-state.texy
index d2812e5143..4492031a5c 100644
--- a/dependency-injection/pl/global-state.texy
+++ b/dependency-injection/pl/global-state.texy
@@ -301,4 +301,4 @@ Rozważając projekt kodu, pamiętaj, że każdy `static $foo` reprezentuje prob
 
 Podczas tego procesu może się okazać, że musisz podzielić klasę, ponieważ ma ona więcej niż jedną odpowiedzialność. Nie przejmuj się tym; dąż do zasady jednej odpowiedzialności.
 
-*Chciałbym podziękować Miško Hevery'emu, którego artykuły takie jak [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] stanowią podstawę tego rozdziału.*
+*Chciałbym podziękować Miško Hevery'emu, którego artykuły takie jak [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] stanowią podstawę tego rozdziału.*
diff --git a/dependency-injection/pl/passing-dependencies.texy b/dependency-injection/pl/passing-dependencies.texy
index d4e4656bd3..ee51056c95 100644
--- a/dependency-injection/pl/passing-dependencies.texy
+++ b/dependency-injection/pl/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Problem pojawia się, gdy chcemy zmienić konstruktor klasy `BaseClass`, na przykład gdy dodamy nową zależność. Wtedy musimy zmodyfikować również wszystkie konstruktory dzieci. Co czyni taką modyfikację piekłem.
 
-Jak temu zapobiec? Rozwiązaniem jest **priorytet kompozycji nad dziedziczeniem**.
+Jak temu zapobiec? Rozwiązaniem jest **przedkładanie [kompozycji nad dziedziczenie** |faq#Why composition is preferred over inheritance].
 
-Zaprojektujmy więc kod inaczej. Będziemy unikać klas abstrakcyjnych `Base*`. Zamiast `MyClass` uzyskać pewną funkcjonalność poprzez dziedziczenie z `BaseClass`, będzie ona miała tę funkcjonalność przekazaną jako zależność:
+Zaprojektujmy więc kod inaczej. Unikniemy [abstrakcyjnych |nette:introduction-to-object-oriented-programming#abstract-classes] klas `Base*`. Zamiast `MyClass` uzyskiwać pewną funkcjonalność poprzez dziedziczenie z `BaseClass`, będzie mieć tę funkcjonalność przekazaną jako zależność:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ Wywołanie setera jest zdefiniowane w konfiguracji kontenera DI w [sekcji |servi
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Ustawienia zmiennej definiujemy w konfiguracji kontenera DI w [sekcji setup |ser
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/pl/services.texy b/dependency-injection/pl/services.texy
index d40aece53e..1b0fdd1521 100644
--- a/dependency-injection/pl/services.texy
+++ b/dependency-injection/pl/services.texy
@@ -2,32 +2,32 @@ Definiowanie usług
 ******************
 
 .[perex]
-Konfiguracja to miejsce, w którym umieszczamy nasze niestandardowe definicje usług. Służy do tego sekcja `services`.
+Konfiguracja to miejsce, w którym instruujemy kontener DI, jak składać poszczególne usługi i jak łączyć je z innymi zależnościami. Nette zapewnia bardzo przejrzysty i elegancki sposób na osiągnięcie tego celu.
 
-Na przykład w ten sposób tworzymy serwis o nazwie `database`, który będzie instancją klasy `PDO`:
+Sekcja `services` w pliku konfiguracyjnym NEON to miejsce, w którym definiujemy nasze niestandardowe usługi i ich konfiguracje. Przyjrzyjmy się prostemu przykładowi definiowania usługi o nazwie `database`, która reprezentuje instancję klasy `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Nazewnictwo usług służy do [odwoływania się |#Referencing-Services] do nich. Jeśli usługa nie jest przywoływana, nie musi być nazwana. Więc po prostu używamy wypunktowania zamiast nazwy:
+Ta konfiguracja skutkuje następującą metodą fabryczną w [kontenerze DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # anonimowa usługa
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Wpis jednowierszowy może być rozbity na wiele wierszy, aby umożliwić dodanie innych klawiszy, takich jak [konfiguracja |#Setup]. Alias dla klucza `create:` to `factory:`.
+Nazwy usług pozwalają nam odwoływać się do nich w innych częściach pliku konfiguracyjnego, używając formatu `@serviceName`. Jeśli nie ma potrzeby nazywania usługi, możemy po prostu użyć punktora:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Usługa jest następnie pobierana z kontenera DI za pomocą metody `getService()` by name lub lepiej `getByType()` by type:
+Aby pobrać usługę z kontenera DI, możemy użyć metody `getService()` z nazwą usługi jako parametrem lub metody `getByType()` z typem usługi:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Tworzenie usługi .[#toc-creating-a-service]
-===========================================
+Tworzenie usług .[#toc-service-creation]
+========================================
 
-Najczęściej tworzymy usługę, tworząc po prostu instancję klasy:
+Najczęściej tworzymy usługę po prostu poprzez instancjonowanie określonej klasy. Na przykład:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Co generuje metodę fabryczną w [kontenerze DI |container]:
+Jeśli musimy rozszerzyć konfigurację o dodatkowe klucze, definicję można rozszerzyć na wiele linii:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Alternatywnie, klucz `arguments` może być użyty do przekazania [argumentów |#Arguments]:
+Klucz `create` ma alias `factory`, obie wersje są powszechne w praktyce. Zalecamy jednak używanie `create`.
+
+Argumenty konstruktora lub metoda tworzenia mogą być alternatywnie zapisane w kluczu `arguments`:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Metoda statyczna może również tworzyć usługę:
+Usługi nie muszą być tworzone tylko przez prostą instancję klasy; mogą one również wynikać z wywoływania metod statycznych lub metod innych usług:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Odpowiada kodowi PHP:
+Zauważ, że dla uproszczenia, zamiast `->`, używamy `::`, patrz [wyrażenie oznacza |#expression means]. Te metody fabryczne są generowane:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Zakłada się, że metoda statyczna `My\Database::create()` ma zdefiniowaną wartość zwrotną, którą kontener DI musi znać. Jeśli go nie ma, zapisz typ do konfiguracji:
+Kontener DI musi znać typ tworzonej usługi. Jeśli tworzymy usługę przy użyciu metody, która nie ma określonego typu zwracanego, musimy wyraźnie wspomnieć o tym typie w konfiguracji:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Nette DI daje nam niezwykle potężne środki wyrazu, które możesz wykorzystać do napisania niemal wszystkiego. Na przykład, aby [odwołać się do |#Referencing-Services] innej usługi i wywołać jej metodę. Dla uproszczenia, zamiast `->`, używamy `::`
+
+Argumenty .[#toc-arguments]
+===========================
+
+Przekazujemy argumenty do konstruktorów i metod w sposób bardzo podobny do zwykłego PHP:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Odpowiada kodowi PHP:
+Dla lepszej czytelności możemy wypisać argumenty w osobnych wierszach. W tym formacie użycie przecinków jest opcjonalne:
 
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
-
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-Wywołania metod mogą być łączone łańcuchowo, tak jak w PHP:
+Można również nazwać argumenty, co pozwala nie martwić się o ich kolejność:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Odpowiada kodowi PHP:
+Jeśli chcesz pominąć niektóre argumenty i użyć ich wartości domyślnych lub wstawić usługę poprzez [autowiring |autowiring], użyj podkreślenia:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Argumentami mogą być usługi, parametry i wiele innych, patrz [środki wyrazu |#expression means].
 
-Argumenty .[#toc-arguments]
-===========================
 
-Parametry nazwane mogą być również używane do przekazywania argumentów:
+Konfiguracja .[#toc-setup]
+==========================
+
+W sekcji `setup` definiujemy metody, które powinny być wywoływane podczas tworzenia usługi.
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # pozycja
-		username: root                      # nazwa
-		password: secret                    # nazwa
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Przy dzieleniu argumentów na wiele linii, użycie przecinków jest opcjonalne.
+W PHP wyglądałoby to następująco:
+
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
 
-Oczywiście jako argumenty mogą być użyte [inne usługi |#Referencing-Services] lub [parametry |configuration#parameters]:
+Oprócz wywoływania metod, można również przekazywać wartości do właściwości. Dodawanie elementu do tablicy jest również obsługiwane, ale należy je ująć w cudzysłów, aby uniknąć kolizji ze składnią NEON:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Odpowiada kodowi PHP:
+W PHP tłumaczyłoby się to na:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-Jeśli pierwszy argument ma być [autowpisywany |autowiring], a chcemy dołączyć drugi argument, to pomijamy pierwszy argument za pomocą `_`, tedy např. `Foo(_, %appDir%)`. Albo jeszcze lepiej, po prostu przekaż drugi argument jako nazwany parametr, np. `Foo(path: %appDir%)`.
-
-Nette DI i format NEON dają nam niezwykle potężne zasoby ekspresyjne, które można wykorzystać do napisania niemal wszystkiego. Tak więc argumentem może być nowo utworzony obiekt, można wywoływać metody statyczne, metody innych serwisów, a nawet funkcje globalne przy użyciu specjalnej notacji:
+W konfiguracji można również wywoływać metody statyczne lub metody innych usług. Jeśli chcesz przekazać bieżącą usługę jako argument, użyj `@self`:
 
 ```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(NetteMode)                  # volání globální funkce
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Odpowiada on kodowi PHP:
+Zauważ, że dla uproszczenia, zamiast `->`, używamy `::`, patrz [środki wyrazu |#expression means]. Spowoduje to wygenerowanie następującej metody fabrycznej:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-Funkcje specjalne .[#toc-special-functions]
--------------------------------------------
-
-Możesz również użyć specjalnych funkcji w argumentach, aby zastąpić lub zanegować wartości:
+Środki wyrazu .[#toc-expression-means]
+======================================
 
-- `not(%arg%)` negacja
-- `bool(%arg%)` lossless override to bool
-- `int(%arg%)` bezstratne przepisywanie na int
-- `float(%arg%)` bezstratny reflow do float
-- `string(%arg%)` bezstratne przepisywanie na ciąg znaków
+Nette DI zapewnia nam wyjątkowo bogate możliwości wyrażania, pozwalając nam wyrazić prawie wszystko. W plikach konfiguracyjnych możemy używać [parametrów |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
-
-Bezstratne repartycjonowanie różni się od normalnego repartycjonowania PHP, np. przy użyciu `(int)`, tym, że rzuca wyjątek dla wartości nienumerycznych.
+# parametr
+%wwwDir%
 
-Jako argumenty można przekazać wiele usług. Tablicę wszystkich usług danego typu (tj. klasy lub interfejsu) tworzy funkcja `typed()`. Funkcja pomija usługi, które mają wyłączone autowiring, można podać wiele typów oddzielonych przecinkami.
+# wartość pod kluczem parametru
+%mailer.user%
 
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# parametr w ciągu znaków
+'%wwwDir%/images'
 ```
 
-Możesz również przekazać tablicę usług automatycznie za pomocą [autowiring |autowiring#Collection-of-Services].
-
-Funkcja `tagged()` tworzy tablicę wszystkich usług z określonym [tagiem |#Tags]. Można również podać wiele tagów oddzielonych przecinkiem.
+Możemy również tworzyć obiekty, wywoływać metody i funkcje:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# utworzyć obiekt
+DateTime()
 
+# wywołać metodę statyczną
+Collator::create(%locale%)
 
-Usługi odsyłania .[#toc-referencing-services]
-=============================================
+# wywołać funkcję PHP
+::getenv(DB_USER)
+```
 
-Do usług odwołujemy się za pomocą nazwy usługi i nazwy serwisu, więc na przykład `@database`:
+Odnosić się do usług poprzez ich nazwę lub typ:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# usługa według nazwy
+@database
+
+# usługa według typu
+@Nette\Database\Connection
 ```
 
-Odpowiada kodowi PHP:
+Używaj składni wywoływalnej pierwszej klasy: .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-Nawet anonimowe usługi mogą być przywoływane poprzez alias, wystarczy podać typ (klasa lub interfejs) zamiast nazwy. Zwykle jednak nie jest to konieczne ze względu na [autowiring |autowiring].
+Użyj stałych:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # nebo třeba @PDO.
-	  setup:
-			- setCacheStorage(@cache.storage)
+# stała klasy
+FilesystemIterator::SKIP_DOTS
+
+# stała globalna uzyskana przez funkcję PHP constant()
+::constant(PHP_VERSION)
 ```
 
+Wywołania metod mogą być łańcuchowane, tak jak w PHP. Dla uproszczenia, zamiast `->`, używamy `::`:
 
-Ustawienie .[#toc-setup]
-========================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
 
-W sekcji setup znajduje się lista metod, które należy wywołać podczas tworzenia usługi:
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Wyrażenia te mogą być używane w dowolnym miejscu podczas [tworzenia usług |#Service Creation], w [argumentach |#Arguments], w sekcji [konfiguracji |#setup] lub w [parametrach |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Odpowiada kodowi PHP:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Funkcje specjalne .[#toc-special-functions]
+-------------------------------------------
 
-Można również ustawić wartości zmienne. Dodawanie elementu do tablicy jest również obsługiwane, ale musi być napisane w cudzysłowie, aby uniknąć konfliktu ze składnią NEON:
+W plikach konfiguracyjnych można korzystać z tych funkcji specjalnych:
 
+- `not()` dla negacji wartości
+- `bool()`, `int()`, `float()`, `string()` do bezstratnego rzutowania typów
+- `typed()` do generowania tablicy wszystkich usług określonego typu
+- `tagged()` do tworzenia tablicy wszystkich usług z danym tagiem
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Odpowiada kodowi PHP:
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-Jednak metody statyczne lub metody innych usług mogą być wywoływane w konfiguracji. Rzeczywista usługa jest przekazywana do nich jako `@self`:
+W porównaniu do konwencjonalnego rzutowania typów w PHP, takiego jak `(int)`, bezstratne rzutowanie typów rzuci wyjątek dla wartości nienumerycznych.
 
+Funkcja `typed()` tworzy tablicę wszystkich usług określonego typu (klasy lub interfejsu). Wyklucza ona usługi z wyłączonym autowiringiem. Można określić wiele typów, oddzielając je przecinkami.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Odpowiada kodowi PHP:
+Można również automatycznie przekazać tablicę usług określonego typu jako argument przy użyciu [autowiring |autowiring#Collection of Services].
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+Funkcja `tagged()` tworzy tablicę wszystkich usług z określonym tagiem. Można wymienić wiele tagów, oddzielając je przecinkami.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-Autowiring .[#toc-autowiring]
-=============================
+Okablowanie .[#toc-autowiring]
+==============================
 
-Możesz użyć klucza autowired, aby wykluczyć usługę z autowiring lub wpłynąć na jej zachowanie. Więcej informacji można znaleźć w [rozdziale dotyczącym autowiring |autowiring].
+Klucz `autowired` pozwala modyfikować zachowanie autoprzewodowania dla określonej usługi. Więcej szczegółów można znaleźć [w |autowiring] rozdziale autowiring.
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # service foo jest wyłączony z autowiring
+		autowired: false     # usługa foo jest wyłączona z automatycznego okablowania
 ```
 
 
 Tagi .[#toc-tags]
 =================
 
-Informacje o użytkownikach mogą być dodawane do poszczególnych serwisów w postaci tagów:
+Tagi służą do dodawania dodatkowych informacji do usług. Do usługi można przypisać jeden lub więcej tagów:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Tagi mogą mieć również wartość:
+Tagi mogą również zawierać wartości:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Możesz przekazać tablicę usług z określonymi tagami jako argument za pomocą funkcji `tagged()`. Możesz określić wiele tagów oddzielonych przecinkami.
+Aby pobrać wszystkie usługi z określonymi tagami, można użyć funkcji `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Nazwy usług można pobrać z kontenera DI za pomocą metody `findByTag()`:
+W kontenerze DI można uzyskać nazwy wszystkich usług z określonym tagiem za pomocą metody `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
-// $names jest tablicą zawierającą nazwę serwisu i wartość tagu
-// np. ['foo' => 'monolog.logger.event', ...]
+// $names to tablica zawierająca nazwę usługi i wartość tagu
+// np. ['foo' => 'monolog.logger.event', ...].
 ```
 
 
-Tryb wtrysku .[#toc-inject-mode]
-================================
+Tryb wstrzykiwania .[#toc-inject-mode]
+======================================
 
-Flaga `inject: true` służy do aktywowania przekazywania zależności poprzez zmienne publiczne z adnotacją [inject |best-practices:inject-method-attribute#Inject-Attribute] i metodami [inject*() |best-practices:inject-method-attribute#inject-Methods].
+Użycie flagi `inject: true` aktywuje przekazywanie zależności poprzez zmienne publiczne z adnotacją [inject |best-practices:inject-method-attribute#Inject Attributes] i metodami [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -398,13 +391,13 @@ services:
 		inject: true
 ```
 
-Domyślnie strona `inject` jest aktywowana tylko dla prezenterów.
+Domyślnie flaga `inject` jest aktywowana tylko dla prezenterów.
 
 
-Modyfikacja usług .[#toc-modification-of-services]
-==================================================
+Modyfikacje usługi .[#toc-service-modifications]
+================================================
 
-Istnieje wiele usług w kontenerze DI, które dodały wbudowane lub [twoje rozszerzenia |#rozšíření]. Definicje tych usług mogą być modyfikowane w konfiguracji. Na przykład dla serwisu `application.application`, który domyślnie jest obiektem `Nette\Application\Application`, możemy zmienić klasę:
+Kontener DI zawiera wiele usług dodanych przez [rozszerzenia |#extensions] wbudowane lub [użytkownika |#extensions]. Definicje tych usług można modyfikować bezpośrednio w konfiguracji. Na przykład można zmienić klasę usługi `application.application`, która jest konwencjonalnie `Nette\Application\Application`, na coś innego:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Flaga `alteration` ma charakter informacyjny i mówi, że właśnie modyfikujemy istniejącą usługę.
+Flaga `alteration` ma charakter informacyjny, wskazując, że jedynie modyfikujemy istniejącą usługę.
 
-Możemy również dodać ustawienie:
+Możemy również uzupełnić konfigurację:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Podczas przepisywania usługi możemy chcieć usunąć oryginalne argumenty, elementy ustawień lub tagi, do czego służy `reset`:
+Podczas nadpisywania usługi może być konieczne usunięcie oryginalnych argumentów, elementów konfiguracji lub tagów, co jest przydatne w przypadku `reset`:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Usługa dodana przez rozszerzenie może być również usunięta z kontenera:
+Jeśli chcesz usunąć usługę dodaną przez rozszerzenie, możesz to zrobić w następujący sposób:
 
 ```neon
 services:
diff --git a/dependency-injection/pt/autowiring.texy b/dependency-injection/pt/autowiring.texy
index b970520160..94a303420b 100644
--- a/dependency-injection/pt/autowiring.texy
+++ b/dependency-injection/pt/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 O recipiente DI passa então automaticamente uma série de serviços que correspondem ao tipo dado. Ele irá omitir serviços que tenham a fiação automática desligada.
 
-Se você não pode controlar a forma do comentário phpDoc, você pode passar uma série de serviços diretamente na configuração usando [`typed()` |services#Special Functions].
+O tipo no comentário também pode ter o formato `array<int, Class>` ou `list<Class>`. Se não for possível controlar a forma do comentário do phpDoc, você poderá passar uma matriz de serviços diretamente na configuração usando [`typed()` |services#Special Functions].
 
 
 Argumentos escalares .[#toc-scalar-arguments]
diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy
index e81ca1b571..e6fd0e2aa6 100644
--- a/dependency-injection/pt/configuration.texy
+++ b/dependency-injection/pt/configuration.texy
@@ -67,7 +67,7 @@ Como editar em massa todos os serviços de um determinado tipo? Precisa chamar u
 ```neon
 decorator:
 	# para todos os serviços que são instâncias desta classe ou interface
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # chamar este método
 			- $absoluteUrls = true # e definir a variável
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Se você não usar a matriz `$container->parameters`, você pode desativar a exportação de parâmetros. Além disso, você pode exportar somente as tags através das quais você obtém serviços usando o método `$container->findByTag(...)`.
+Se você não usar a matriz `$container->getParameters()`, você pode desativar a exportação de parâmetros. Além disso, você pode exportar somente as tags através das quais você obtém serviços usando o método `$container->findByTag(...)`.
 Se você não chamar o método, você pode desabilitar completamente a exportação de tags com `false`.
 
 Você pode reduzir significativamente os metadados para a [fiação automática |autowiring] especificando as classes que você usa como parâmetro para o método `$container->getByType()`.
@@ -191,20 +191,15 @@ Basta especificar em quais diretórios (e subdiretórios) as classes devem ser p
 
 ```neon
 search:
-	# você mesmo escolhe os nomes das seções
-	myForms:
-		em: %appDir%/Forms
-
-	model:
-		em: %appDir%/Modelo
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Normalmente, porém, não queremos acrescentar todas as classes e interfaces, para que possamos filtrá-las:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtragem por nome de arquivo (string|string[])
 		files:
@@ -220,7 +215,7 @@ Ou podemos selecionar classes que herdam ou implementam pelo menos uma das segui
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Você também pode definir regras negativas, ou seja, máscaras de nome de class
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+arquivos: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ As etiquetas podem ser definidas para serviços adicionais:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/pt/extensions.texy b/dependency-injection/pt/extensions.texy
index 6d38a69bf3..31f01cfc28 100644
--- a/dependency-injection/pt/extensions.texy
+++ b/dependency-injection/pt/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $inicialização .[wiki-method]
 =============================
 
-O Configurador chama o código de inicialização após a [criação do recipiente |application:bootstrap#index.php], que é criado escrevendo para um objeto `$this->initialization` usando [o método addBody() |php-generator:#method-and-function-body].
+O Configurador chama o código de inicialização após a [criação do recipiente |application:bootstrap#index.php], que é criado escrevendo para um objeto `$this->initialization` usando [o método addBody() |php-generator:#method-and-function-bodies].
 
 Mostraremos um exemplo de como iniciar uma sessão ou iniciar serviços que tenham a tag `run` usando o código de inicialização:
 
diff --git a/dependency-injection/pt/factory.texy b/dependency-injection/pt/factory.texy
index 4ded195f1e..293f3418b7 100644
--- a/dependency-injection/pt/factory.texy
+++ b/dependency-injection/pt/factory.texy
@@ -170,39 +170,45 @@ Até agora, as fábricas e os acessores só podiam criar ou devolver um único o
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Em vez de passar por múltiplas fábricas e acessores gerados, você pode passar apenas por uma complexa multifábrica.
 
-Alternativamente, você pode usar `create()` e `get()` com um parâmetro ao invés de múltiplos métodos:
+Como alternativa, você pode usar `get()` com um parâmetro em vez de vários métodos:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Neste caso, `MultiFactory::createArticle()` faz a mesma coisa que `MultiFactoryAlt::create('article')`. No entanto, a sintaxe alternativa tem algumas desvantagens. Não está claro quais valores `$name` são suportados e o tipo de retorno não pode ser especificado na interface quando se utiliza vários valores diferentes do `$name`.
+Nesse caso, `MultiFactory::getArticle()` faz a mesma coisa que `MultiFactoryAlt::get('article')`. Entretanto, a sintaxe alternativa tem algumas desvantagens. Não está claro quais valores de `$name` são compatíveis e o tipo de retorno não pode ser especificado na interface ao usar vários valores diferentes de `$name`.
 
 
 Definição com uma lista .[#toc-definition-with-a-list]
 ------------------------------------------------------
-Hos para definir uma multifábrica em sua configuração? Vamos criar três serviços que serão devolvidos pela multifábrica, e a própria multifábrica:
+Essa maneira pode ser usada para definir uma fábrica múltipla na configuração: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Ou, na definição da fábrica, podemos nos referir aos serviços existentes usando uma referência:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Outra opção para definir uma multifábrica é a utilização de [etiquetas |se
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/pt/faq.texy b/dependency-injection/pt/faq.texy
index 09f9f07758..c9ff9daa30 100644
--- a/dependency-injection/pt/faq.texy
+++ b/dependency-injection/pt/faq.texy
@@ -61,7 +61,7 @@ Lembre-se de que passar para a Injeção de Dependência é um investimento na q
 
 Por que a composição é preferível à herança? .[#toc-why-composition-is-preferred-over-inheritance]
 --------------------------------------------------------------------------------------------------
-É preferível usar composição em vez de herança, pois serve ao propósito da reutilização do código sem ter a necessidade de se preocupar com o efeito de trickle down da mudança. Assim, ele proporciona um acoplamento mais frouxo onde não temos que nos preocupar em mudar algum código causando algum outro código dependente que necessite de mudança. Um exemplo típico é a situação identificada como [o inferno do construtor |passing-dependencies#Constructor hell].
+É preferível usar a [composição |nette:introduction-to-object-oriented-programming#composition] em vez da [herança |nette:introduction-to-object-oriented-programming#inheritance] porque ela serve para reutilizar o código sem ter de se preocupar com as consequências das alterações. Assim, ela proporciona um acoplamento mais frouxo, em que não precisamos nos preocupar com o fato de que a alteração de algum código causará a necessidade de alterar outro código dependente. Um exemplo típico é uma situação conhecida como [inferno do construtor |passing-dependencies#Constructor hell].
 
 
 O Nette DI Container pode ser usado fora da Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/pt/global-state.texy b/dependency-injection/pt/global-state.texy
index f5a33c5ea0..b50cbab11d 100644
--- a/dependency-injection/pt/global-state.texy
+++ b/dependency-injection/pt/global-state.texy
@@ -301,4 +301,4 @@ Ao contemplar o projeto do código, tenha em mente que cada `static $foo` repres
 
 Durante este processo, você pode descobrir que precisa dividir uma classe porque ela tem mais de uma responsabilidade. Não se preocupe com isso; esforce-se pelo princípio de uma responsabilidade.
 
-*Gostaria de agradecer a Miško Hevery, cujos artigos como [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] formam a base deste capítulo.*
+*Gostaria de agradecer a Miško Hevery, cujos artigos como [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] formam a base deste capítulo.*
diff --git a/dependency-injection/pt/passing-dependencies.texy b/dependency-injection/pt/passing-dependencies.texy
index a6b4434e8d..0d9e6a6285 100644
--- a/dependency-injection/pt/passing-dependencies.texy
+++ b/dependency-injection/pt/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 O problema ocorre quando queremos mudar o construtor da classe `BaseClass`, por exemplo, quando uma nova dependência é acrescentada. Então temos que modificar todos os construtores das crianças também. O que faz de tal modificação um inferno.
 
-Como evitar isso? A solução é **priorizar a composição sobre a herança***.
+Como evitar isso? A solução é **priorizar a [composição em vez da herança** |faq#Why composition is preferred over inheritance].
 
-Portanto, vamos projetar o código de forma diferente. Evitaremos as aulas abstratas `Base*`. Ao invés de `MyClass` obter alguma funcionalidade herdando de `BaseClass`, terá essa funcionalidade passada como uma dependência:
+Portanto, vamos projetar o código de forma diferente. Evitaremos classes `Base*` [abstratas |nette:introduction-to-object-oriented-programming#abstract-classes]. Em vez de `MyClass` obter alguma funcionalidade herdando de `BaseClass`, essa funcionalidade será passada como uma dependência:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ A chamada do setter é definida na configuração do recipiente DI na [configura
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ A configuração da variável é definida na configuração do recipiente DI na
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/pt/services.texy b/dependency-injection/pt/services.texy
index d8f55bada1..40971b24e2 100644
--- a/dependency-injection/pt/services.texy
+++ b/dependency-injection/pt/services.texy
@@ -2,32 +2,32 @@ Definições de serviço
 *********************
 
 .[perex]
-A configuração é onde colocamos as definições de serviços personalizados. Isto é feito na seção `services`.
+A configuração é o local em que instruímos o contêiner DI sobre como montar serviços individuais e como conectá-los a outras dependências. O Nette oferece uma maneira muito clara e elegante de fazer isso.
 
-Por exemplo, é assim que criamos um serviço chamado `database`, que será uma instância da classe `PDO`:
+A seção `services` no arquivo de configuração do NEON é onde definimos nossos serviços personalizados e suas configurações. Vamos dar uma olhada em um exemplo simples de definição de um serviço chamado `database`, que representa uma instância da classe `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-A nomenclatura dos serviços é utilizada para nos permitir [referenciá-los |#Referencing Services]. Se um serviço não é referenciado, não há necessidade de nomeá-lo. Portanto, usamos apenas um ponto em vez de um nome:
+Essa configuração resulta no seguinte método de fábrica no [contêiner DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # serviço anônimo
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Uma entrada de uma linha pode ser dividida em várias linhas para permitir que chaves adicionais sejam adicionadas, tais como [configuração |#setup]. O pseudônimo para a chave `create:` é `factory:`.
+Os nomes dos serviços nos permitem fazer referência a eles em outras partes do arquivo de configuração, usando o formato `@serviceName`. Se não houver necessidade de nomear o serviço, podemos simplesmente usar um marcador:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Recuperamos então o serviço do recipiente DI usando o método `getService()` pelo nome, ou melhor ainda, o método `getByType()` pelo tipo:
+Para recuperar um serviço do contêiner DI, podemos usar o método `getService()` com o nome do serviço como parâmetro ou o método `getByType()` com o tipo de serviço:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Criando um serviço .[#toc-creating-a-service]
-=============================================
+Criação de serviços .[#toc-service-creation]
+============================================
 
-Na maioria das vezes, nós criamos um serviço simplesmente criando uma instância de uma classe:
+Geralmente, criamos um serviço simplesmente instanciando uma classe específica. Por exemplo:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-O que gerará um método de fábrica em [contêineres DI |container]:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Alternativamente, uma chave `arguments` pode ser usada para passar [argumentos |#Arguments]:
+Se precisarmos expandir a configuração com chaves adicionais, a definição poderá ser expandida em várias linhas:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-Um método estático também pode criar um serviço:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Corresponde ao código PHP:
+A chave `create` tem um alias `factory`, ambas as versões são comuns na prática. No entanto, recomendamos o uso de `create`.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-Presume-se que um método estático `My\Database::create()` tenha um valor de retorno definido que o recipiente DI precisa conhecer. Se não o tiver, escrevemos o tipo na configuração:
+Como alternativa, os argumentos do construtor ou o método de criação podem ser escritos na chave `arguments`:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-A Nette DI lhe dá facilidades de expressão extremamente poderosas para escrever quase tudo. Por exemplo, para [se referir |#Referencing Services] a outro serviço e chamar seu método. Para simplificar, `::` é usado ao invés de `->`.
+Os serviços não precisam ser criados apenas pela simples instanciação de uma classe; eles também podem resultar da chamada de métodos estáticos ou métodos de outros serviços:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Corresponde ao código PHP:
+Observe que, para simplificar, em vez de `->`, usamos `::`, veja a [expressão significa |#expression means]. Esses métodos de fábrica são gerados:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-As chamadas de métodos podem ser encadeadas como em PHP:
+O contêiner DI precisa saber o tipo do serviço criado. Se criarmos um serviço usando um método que não tenha um tipo de retorno especificado, devemos mencionar explicitamente esse tipo na configuração:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Corresponde ao código PHP:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argumentos .[#toc-arguments]
 ============================
 
-Os parâmetros nomeados também podem ser usados para passar argumentos:
+Passamos argumentos para construtores e métodos de forma muito semelhante ao PHP comum:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # posicional
-		username: root                      # named
-		password: secret                    # named
-	)
-```
-
-O uso de vírgulas é opcional ao quebrar argumentos em várias linhas.
-
-Naturalmente, também podemos utilizar [outros serviços |#Referencing Services] ou [parâmetros |configuration#parameters] como argumentos:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-Corresponde ao código PHP:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Se o primeiro argumento for [auto-cablado |autowiring] e você quiser especificar o segundo, omitir o primeiro com o `_` character, for example `Foo(_, %appDir%)`. Ou melhor ainda, passar apenas o segundo argumento como um parâmetro nomeado, por exemplo `Foo(path: %appDir%)`.
-
-Nette DI e o formato NEON lhe dão facilidades extremamente poderosas para escrever quase tudo. Assim, um argumento pode ser um objeto recém-criado, você pode chamar métodos estáticos, métodos de outros serviços, ou mesmo funções globais usando notação especial:
+Para facilitar a leitura, podemos listar os argumentos em linhas separadas. Nesse formato, o uso de vírgulas é opcional:
 
 ```neon
 services:
-	analisador: Meu Analisador (
-		FilesystemIterator(%appDir%)        # criar objeto
-		DateTime::createFromFormat('Y-m-d') # chama método estático
-		@anotherService                     # passando outro serviço
-		@http.request::getRemoteAddress()   # chamando outro método de serviço
-		::getenv(NetteMode)                 # chamar uma função global
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-Corresponde ao código PHP:
-
-```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('NetteMode')
-	);
-}
-```
-
-
-Funções especiais .[#toc-special-functions]
--------------------------------------------
-
-Você também pode usar funções especiais em argumentos para lançar ou negar valores:
-
-- `not(%arg%)` negação
-- `bool(%arg%)` elenco sem perdas a bool
-- `int(%arg%)` elenco sem perdas para int
-- `float(%arg%)` elenco sem perdas para flutuar
-- `string(%arg%)` elenco sem perdas para cordas
+Você também pode nomear os argumentos, o que permite que você não se preocupe com a ordem deles:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-A reescrita sem perdas difere da reescrita normal em PHP, por exemplo, usando `(int)`, na medida em que lança uma exceção para valores não-numéricos.
-
-Múltiplos serviços podem ser passados como argumentos. Um conjunto de todos os serviços de um determinado tipo (ou seja, classe ou interface) é criado pela função `typed()`. A função omitirá serviços que tenham a fiação automática desativada, e múltiplos tipos separados por uma vírgula podem ser especificados.
+Se quiser omitir determinados argumentos e usar seus valores padrão ou inserir um serviço por meio da [conexão automática |autowiring], use um sublinhado:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-Você também pode passar um conjunto de serviços automaticamente usando [a fiação automática |autowiring#Collection of Services].
-
-Um conjunto de todos os serviços com uma certa [etiqueta |#tags] é criado pela função `tagged()`. Múltiplas tags separadas por uma vírgula podem ser especificadas.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Serviços de referência .[#toc-referencing-services]
-===================================================
-
-Os serviços individuais são referenciados usando o personagem `@` and name, so for example `@database`:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-Corresponde ao código PHP:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Mesmo serviços anônimos podem ser referenciados usando uma chamada de retorno, basta especificar seu tipo (classe ou interface) ao invés de seu nome. No entanto, isto geralmente não é necessário devido ao [cabeamento automático |autowiring].
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Os argumentos podem ser serviços, parâmetros e muito mais; consulte os [meios de expressão |#expression means].
 
 
 Configuração .[#toc-setup]
 ==========================
 
-Na seção de configuração, listamos os métodos a serem chamados ao criar o serviço:
+Na seção `setup`, definimos os métodos que devem ser chamados ao criar o serviço.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Corresponde ao código PHP:
+Em PHP, isso seria parecido com:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-Também é possível definir os locais adequados. A adição de um elemento a uma matriz também é apoiada, e deve ser escrita entre aspas para não entrar em conflito com a sintaxe NEON:
-
+Além das chamadas de método, você também pode passar valores para as propriedades. A adição de um elemento a uma matriz também é suportada, mas você precisa colocá-la entre aspas para evitar colidir com a sintaxe NEON:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Corresponde ao código PHP:
+Em PHP, isso se traduziria em:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-No entanto, métodos estáticos ou métodos de outros serviços também podem ser chamados na configuração. Passamos o serviço real a eles como `@self`:
-
+Na configuração, você também pode chamar métodos estáticos ou métodos de outros serviços. Se você precisar passar o serviço atual como um argumento, use `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Corresponde ao código PHP:
+Observe que, para simplificar, em vez de `->`, usamos `::`, veja a [expressão significa |#expression means]. Isso gera o seguinte método de fábrica:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
-Cablagem automática .[#toc-autowiring]
-======================================
+Meios de Expressão .[#toc-expression-means]
+===========================================
+
+O Nette DI nos fornece recursos de expressão excepcionalmente ricos, o que nos permite articular quase tudo. Nos arquivos de configuração, podemos usar [parâmetros |configuration#parameters]:
+
+```neon
+# parâmetro
+%wwwDir%
+
+# valor em uma chave de parâmetro
+%mailer.user%
+
+# parâmetro em uma cadeia de caracteres
+'%wwwDir%/images'
+```
+
+Também podemos criar objetos, chamar métodos e funções:
+
+```neon
+# criar um objeto
+DateTime()
+
+# chamar um método estático
+Collator::create(%locale%)
+
+# chamar uma função PHP
+::getenv(DB_USER)
+```
+
+Referir-se aos serviços pelo nome ou pelo tipo:
+
+```neon
+# serviço por nome
+@database
+
+# serviço por tipo
+@Nette\Database\Connection
+```
+
+Use a sintaxe chamável de primeira classe: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Usar constantes:
+
+```neon
+# constante de classe
+FilesystemIterator::SKIP_DOTS
+
+# constante global obtida pela função constant() do PHP
+::constant(PHP_VERSION)
+```
+
+As chamadas de método podem ser encadeadas, assim como no PHP. Para simplificar, em vez de `->`, usamos `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Essas expressões podem ser usadas em qualquer lugar ao [criar serviços |#Service Creation], em [argumentos |#Arguments], na seção de [configuração |#setup] ou em [parâmetros |configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Funções especiais .[#toc-special-functions]
+-------------------------------------------
+
+Nos arquivos de configuração, você pode utilizar essas funções especiais:
+
+- `not()` para negação de valor
+- `bool()`, `int()`, `float()`, `string()` para conversão de tipos sem perdas
+- `typed()` para gerar uma matriz de todos os serviços de um tipo especificado
+- `tagged()` para criar uma matriz de todos os serviços com uma determinada tag
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+Em comparação com o typecasting convencional em PHP, como `(int)`, o lossless type casting lançará uma exceção para valores não numéricos.
+
+A função `typed()` cria uma matriz de todos os serviços de um tipo específico (classe ou interface). Ela exclui os serviços com o autowiring desativado. Vários tipos podem ser especificados, separados por vírgulas.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+Você também pode passar automaticamente uma matriz de serviços de um tipo específico como um argumento usando o [autowiring |autowiring#Collection of Services].
+
+A função `tagged()` cria uma matriz de todos os serviços com uma tag especificada. Várias tags podem ser listadas, separadas por vírgulas.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
+Fiação automática .[#toc-autowiring]
+====================================
 
-A chave autowired pode ser usada para excluir um serviço da autowired ou para influenciar seu comportamento. Consulte o [capítulo sobre a fiação automática |autowiring] para obter mais informações.
+A chave `autowired` permite modificar o comportamento de conexão automática de um serviço específico. Para obter mais detalhes, consulte [o capítulo Aut |autowiring]owiring.
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo é removido do autowiring
+		autowired: false     # O serviço foo está excluído da autocablagem
 ```
 
 
-Etiquetas .[#toc-tags]
-======================
+Tags .[#toc-tags]
+=================
 
-As informações do usuário podem ser adicionadas aos serviços individuais sob a forma de tags:
+As tags são usadas para adicionar informações suplementares aos serviços. Você pode atribuir uma ou mais tags a um serviço:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-As etiquetas também podem ter um valor:
+As tags também podem conter valores:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Uma série de serviços com determinadas tags pode ser passada como argumento usando a função `tagged()`. Múltiplas tags separadas por uma vírgula também podem ser especificadas.
+Para recuperar todos os serviços com tags específicas, você pode usar a função `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Os nomes dos serviços podem ser obtidos no recipiente DI usando o método `findByTag()`:
+No contêiner DI, você pode obter os nomes de todos os serviços com uma tag específica usando o método `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
-// $names é um array contendo o nome do serviço e o valor da etiqueta
-// i.e. ['foo' => 'monolog.logger.event', ...]
+// $names é uma matriz que contém o nome do serviço e o valor da tag
+// Por exemplo, ['foo' => 'monolog.logger.event', ...]
 ```
 
 
-Modo injetado .[#toc-inject-mode]
-=================================
+Modo de injeção .[#toc-inject-mode]
+===================================
 
-A bandeira `inject: true` é usada para ativar a passagem de dependências através de variáveis públicas com a anotação de [injeção |best-practices:inject-method-attribute#Inject Attributes] e os métodos de [injeção*() |best-practices:inject-method-attribute#inject Methods].
+O uso do sinalizador `inject: true` ativa a passagem de dependências por meio de variáveis públicas com a anotação [inject |best-practices:inject-method-attribute#Inject Attributes] e os métodos [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -398,13 +391,13 @@ services:
 		inject: true
 ```
 
-Por padrão, `inject` é ativado somente para apresentadores.
+Por padrão, o `inject` só é ativado para apresentadores.
 
 
-Modificação de serviços .[#toc-modification-of-services]
-========================================================
+Modificações no serviço .[#toc-service-modifications]
+=====================================================
 
-Há uma série de serviços no contêiner DI que foram acrescentados por embutido ou por [sua extensão |#di-extensions]. As definições desses serviços podem ser modificadas na configuração. Por exemplo, para o serviço `application.application`, que é por padrão um objeto `Nette\Application\Application`, podemos alterar a classe:
+O contêiner DI contém muitos serviços adicionados por [extensões |#extensions] internas ou [de usuário |#extensions]. Você pode modificar as definições desses serviços diretamente na configuração. Por exemplo, você pode alterar a classe do serviço `application.application`, que é convencionalmente `Nette\Application\Application`, para outra:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-A bandeira `alteration` é informativa e diz que estamos apenas modificando um serviço existente.
+O sinalizador `alteration` é informativo, indicando que estamos apenas modificando um serviço existente.
 
-Também podemos acrescentar uma configuração:
+Também podemos complementar a configuração:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Ao reescrever um serviço, podemos querer remover os argumentos originais, itens de configuração ou tags, que é para isso que serve `reset`:
+Ao substituir um serviço, talvez você queira remover argumentos, itens de configuração ou tags originais, e é aí que o `reset` se torna útil:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Um serviço adicionado por extensão também pode ser removido do container:
+Se quiser remover um serviço adicionado por uma extensão, você pode fazer isso da seguinte forma:
 
 ```neon
 services:
diff --git a/dependency-injection/ro/autowiring.texy b/dependency-injection/ro/autowiring.texy
index d9f7b90586..3a4b41cf82 100644
--- a/dependency-injection/ro/autowiring.texy
+++ b/dependency-injection/ro/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Recipientul DI transmite apoi automat un array de servicii care corespund tipului dat. Acesta va omite serviciile care au cablarea automată dezactivată.
 
-Dacă nu puteți controla forma comentariului phpDoc, puteți trece o matrice de servicii direct în configurație, utilizând [`typed()` |services#Special Functions].
+Tipul din comentariu poate fi, de asemenea, de forma `array<int, Class>` sau `list<Class>`. Dacă nu puteți controla forma comentariului phpDoc, puteți trece o matrice de servicii direct în configurație folosind [`typed()` |services#Special Functions].
 
 
 Argumente scalare .[#toc-scalar-arguments]
diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy
index 3c0a3e410c..311cbfd773 100644
--- a/dependency-injection/ro/configuration.texy
+++ b/dependency-injection/ro/configuration.texy
@@ -67,7 +67,7 @@ Cum se pot edita în bloc toate serviciile de un anumit tip? Aveți nevoie să a
 ```neon
 decorator:
 	# pentru toate serviciile care sunt instanțe ale acestei clase sau interfețe
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # apelează această metodă
 			- $absoluteUrls = true   # și setează variabila
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Dacă nu utilizați matricea `$container->parameters`, puteți dezactiva exportul de parametri. În plus, puteți exporta numai acele etichete prin care obțineți servicii utilizând metoda `$container->findByTag(...)`.
+Dacă nu utilizați matricea `$container->getParameters()`, puteți dezactiva exportul de parametri. În plus, puteți exporta numai acele etichete prin care obțineți servicii utilizând metoda `$container->findByTag(...)`.
 Dacă nu apelați deloc metoda, puteți dezactiva complet exportul de etichete cu `false`.
 
 Puteți reduce în mod semnificativ metadatele pentru [cablarea |autowiring] automată prin specificarea claselor pe care le utilizați ca parametru pentru metoda `$container->getByType()`.
@@ -191,20 +191,15 @@ Trebuie doar să specificați în ce directoare (și subdirectoare) trebuie cău
 
 ```neon
 search:
-	# alegeți singuri denumirile secțiunilor
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 De obicei, însă, nu dorim să adăugăm toate clasele și interfețele, așa că le putem filtra:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtrarea după numele fișierului (string|string[])
 		files:
@@ -220,7 +215,7 @@ Sau putem selecta clasele care moștenesc sau implementează cel puțin una dint
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ De asemenea, se pot defini reguli negative, adică măști de nume de clasă sau
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+fișiere: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Se pot stabili etichete pentru serviciile adăugate:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/ro/extensions.texy b/dependency-injection/ro/extensions.texy
index 39bab90248..1c3ba3ce1d 100644
--- a/dependency-injection/ro/extensions.texy
+++ b/dependency-injection/ro/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initializare .[wiki-method]
 ============================
 
-Configuratorul apelează codul de inițializare după [crearea containerului |application:bootstrap#index.php], care este creat prin scrierea într-un obiect `$this->initialization` folosind [metoda addBody() |php-generator:#method-and-function-body].
+Configuratorul apelează codul de inițializare după [crearea containerului |application:bootstrap#index.php], care este creat prin scrierea într-un obiect `$this->initialization` folosind [metoda addBody() |php-generator:#method-and-function-bodies].
 
 Vom prezenta un exemplu de pornire a unei sesiuni sau de pornire a serviciilor care au eticheta `run` folosind codul de inițializare:
 
diff --git a/dependency-injection/ro/factory.texy b/dependency-injection/ro/factory.texy
index 6fb2fa2fea..d282fe1624 100644
--- a/dependency-injection/ro/factory.texy
+++ b/dependency-injection/ro/factory.texy
@@ -170,39 +170,45 @@ Până acum, fabricile și accesorii puteau crea sau returna doar un singur obie
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 În loc să transmiteți mai multe fabrici și accesori generați, puteți transmite doar o singură multifactorie complexă.
 
-Alternativ, puteți utiliza `create()` și `get()` cu un parametru în loc de mai multe metode:
+Alternativ, puteți utiliza `get()` cu un parametru în loc de mai multe metode:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-În acest caz, `MultiFactory::createArticle()` face același lucru ca și `MultiFactoryAlt::create('article')`. Cu toate acestea, sintaxa alternativă are câteva dezavantaje. Nu este clar ce valori `$name` sunt acceptate, iar tipul de returnare nu poate fi specificat în interfață atunci când se utilizează mai multe valori `$name` diferite.
+În acest caz, `MultiFactory::getArticle()` face același lucru ca și `MultiFactoryAlt::get('article')`. Cu toate acestea, sintaxa alternativă are câteva dezavantaje. Nu este clar ce valori `$name` sunt acceptate, iar tipul de returnare nu poate fi specificat în interfață atunci când se utilizează mai multe valori `$name` diferite.
 
 
 Definiție cu o listă .[#toc-definition-with-a-list]
 ---------------------------------------------------
-Hos pentru a defini un multifactory în configurația dvs. Să creăm trei servicii care vor fi returnate de către multifactory și multifactory însuși:
+Acest mod poate fi utilizat pentru a defini o fabrică multiplă în configurație: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Sau, în definiția fabricii, putem face referire la serviciile existente folosind o referință:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ O altă opțiune de definire a unui multifactorial este utilizarea [etichetelor
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/ro/faq.texy b/dependency-injection/ro/faq.texy
index 9d09d2e6fe..807ecc97a1 100644
--- a/dependency-injection/ro/faq.texy
+++ b/dependency-injection/ro/faq.texy
@@ -61,7 +61,7 @@ Nu uitați că trecerea la Injectarea dependențelor este o investiție în cali
 
 De ce este preferată compoziția în locul moștenirii? .[#toc-why-composition-is-preferred-over-inheritance]
 ----------------------------------------------------------------------------------------------------------
-Este preferabilă utilizarea compoziției în locul moștenirii, deoarece servește scopului de reutilizare a codului, fără a fi nevoie să vă faceți griji cu privire la efectul de schimbare. Astfel, se asigură o cuplare mai lejeră, în care nu trebuie să ne facem griji că modificarea unui cod ar putea duce la modificarea unui alt cod dependent. Un exemplu tipic este situația identificată drept [iadul constructorilor |passing-dependencies#Constructor hell].
+Este de preferat să se utilizeze [compoziția |nette:introduction-to-object-oriented-programming#composition] în locul [moștenirii |nette:introduction-to-object-oriented-programming#inheritance], deoarece aceasta permite reutilizarea codului fără a fi nevoie să ne facem griji cu privire la consecințele modificărilor. Astfel, oferă un cuplaj mai slab, în care nu trebuie să ne facem griji că modificarea unui cod va determina necesitatea de a modifica alt cod dependent. Un exemplu tipic este o situație denumită " [iadul constructorilor |passing-dependencies#Constructor hell]".
 
 
 Poate fi utilizat Nette DI Container în afara Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/ro/global-state.texy b/dependency-injection/ro/global-state.texy
index 7a4d561745..ea7e944b2d 100644
--- a/dependency-injection/ro/global-state.texy
+++ b/dependency-injection/ro/global-state.texy
@@ -301,4 +301,4 @@ Atunci când vă gândiți la proiectarea codului, nu uitați că fiecare `stati
 
 În timpul acestui proces, s-ar putea să descoperiți că trebuie să divizați o clasă deoarece aceasta are mai multe responsabilități. Nu vă faceți griji în această privință; străduiți-vă să respectați principiul unei singure responsabilități.
 
-*Doresc să îi mulțumesc lui Miško Hevery, ale cărui articole, precum [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], constituie baza acestui capitol.*
+*Doresc să îi mulțumesc lui Miško Hevery, ale cărui articole, precum [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], constituie baza acestui capitol.*
diff --git a/dependency-injection/ro/passing-dependencies.texy b/dependency-injection/ro/passing-dependencies.texy
index 2437edaeb2..fb686cfe1d 100644
--- a/dependency-injection/ro/passing-dependencies.texy
+++ b/dependency-injection/ro/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Problema apare atunci când dorim să modificăm constructorul clasei `BaseClass`, de exemplu atunci când se adaugă o nouă dependență. Atunci trebuie să modificăm și toți constructorii copiilor. Ceea ce face ca o astfel de modificare să fie un iad.
 
-Cum să prevenim acest lucru? Soluția este să **prioritizăm compoziția în detrimentul moștenirii**.
+Cum se poate preveni acest lucru? Soluția constă în **prioritizarea [compoziției în detrimentul moștenirii** |faq#Why composition is preferred over inheritance].
 
-Așadar, haideți să proiectăm codul în mod diferit. Vom evita clasele abstracte `Base*`. În loc ca `MyClass` să obțină o anumită funcționalitate prin moștenirea de la `BaseClass`, aceasta va avea acea funcționalitate transmisă ca dependență:
+Deci, să proiectăm codul în mod diferit. Vom evita clasele [abstracte |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*`. În loc ca `MyClass` să primească o anumită funcționalitate prin moștenirea de la `BaseClass`, aceasta va avea acea funcționalitate transmisă ca dependență:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ Apelarea setterului este definită în configurația containerului DI în [secț
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Setarea variabilei este definită în configurația containerului DI în [secți
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/ro/services.texy b/dependency-injection/ro/services.texy
index 162f918633..eeb0218375 100644
--- a/dependency-injection/ro/services.texy
+++ b/dependency-injection/ro/services.texy
@@ -2,32 +2,32 @@ Definiții ale serviciilor
 *************************
 
 .[perex]
-Configurația este locul în care se plasează definițiile serviciilor personalizate. Acest lucru se face în secțiunea `services`.
+Configurația este locul în care instruim containerul DI cu privire la modul de asamblare a serviciilor individuale și la modul de conectare a acestora cu alte dependențe. Nette oferă o modalitate foarte clară și elegantă de a realiza acest lucru.
 
-De exemplu, astfel creăm un serviciu numit `database`, care va fi o instanță a clasei `PDO`:
+Secțiunea `services` din fișierul de configurare NEON este locul în care definim serviciile noastre personalizate și configurațiile lor. Să analizăm un exemplu simplu de definire a unui serviciu numit `database`, care reprezintă o instanță a clasei `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Denumirea serviciilor este utilizată pentru a ne permite să le [referim |#Referencing Services] la acestea. În cazul în care un serviciu nu este menționat, nu este necesar să îl denumim. Prin urmare, folosim doar un punct în loc de un nume:
+Această configurație are ca rezultat următoarea metodă factory în [containerul DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  # serviciu anonim
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-O intrare pe o singură linie poate fi împărțită în mai multe linii pentru a permite adăugarea de chei suplimentare, cum ar fi [configurare |#setup]. Pseudonimul pentru tasta `create:` este `factory:`.
+Numele serviciilor ne permit să facem referire la acestea în alte părți ale fișierului de configurare, folosind formatul `@serviceName`. Dacă nu este nevoie să denumim serviciul, putem folosi pur și simplu un punct:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Apoi, recuperăm serviciul din containerul DI folosind metoda `getService()` după nume sau, mai bine, metoda `getByType()` după tip:
+Pentru a prelua un serviciu din containerul DI, putem utiliza metoda `getService()` cu numele serviciului ca parametru sau metoda `getByType()` cu tipul serviciului:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Crearea unui serviciu .[#toc-creating-a-service]
-================================================
+Crearea de servicii .[#toc-service-creation]
+============================================
 
-Cel mai adesea, creăm un serviciu prin simpla creare a unei instanțe a unei clase:
+Cel mai adesea, creăm un serviciu prin simpla instanțiere a unei clase specifice. De exemplu:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Ceea ce va genera o metodă factory în [containerul DI |container]:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Alternativ, o cheie `arguments` poate fi utilizată pentru a transmite [argumente |#Arguments]:
+Dacă trebuie să extindem configurația cu chei suplimentare, definiția poate fi extinsă în mai multe linii:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-O metodă statică poate crea, de asemenea, un serviciu:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Corespunde codului PHP:
+Cheia `create` are un pseudonim `factory`, ambele versiuni sunt comune în practică. Cu toate acestea, recomandăm utilizarea `create`.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-O metodă statică `My\Database::create()` se presupune că are o valoare de returnare definită pe care containerul DI trebuie să o cunoască. Dacă nu o are, scriem tipul în configurație:
+Argumentele constructorului sau metoda de creare pot fi scrise alternativ în cheia `arguments`:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Nette DI vă oferă facilități de exprimare extrem de puternice pentru a scrie aproape orice. De exemplu, pentru a face [referire |#Referencing Services] la un alt serviciu și a apela metoda acestuia. Pentru simplificare, se folosește `::` în loc de `->`.
+Serviciile nu trebuie să fie create doar prin simpla instanțiere a unei clase; ele pot rezulta, de asemenea, din apelarea unor metode statice sau a unor metode ale altor servicii:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Corespunde codului PHP:
+Rețineți că, pentru simplificare, în loc de `->`, folosim `::`, a se vedea [expresia înseamnă |#expression means]. Aceste metode fabrică sunt generate:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-Apelurile la metode pot fi înlănțuite ca în PHP:
+Containerul DI trebuie să cunoască tipul serviciului creat. Dacă creăm un serviciu folosind o metodă care nu are un tip de returnare specificat, trebuie să menționăm explicit acest tip în configurație:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Corespunde codului PHP:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argumente .[#toc-arguments]
 ===========================
 
-Parametrii numiți pot fi utilizați și pentru a transmite argumente:
+Trecem argumente către constructori și metode într-o manieră foarte asemănătoare cu cea din PHP obișnuit:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # pozițional
-		username: root                      # numit
-		password: secret                    # numit
-	)
-```
-
-Utilizarea virgulelor este opțională atunci când argumentele sunt împărțite pe mai multe linii.
-
-Bineînțeles, putem folosi și [alte servicii |#Referencing Services] sau [parametri |configuration#parameters] ca argumente:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-Corespunde codului PHP:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Dacă primul argument este [autowired |autowiring] și doriți să îl specificați pe al doilea, omiteți-l pe primul cu `_` character, for example `Foo(_, %appDir%)`. Sau, mai bine, treceți doar al doilea argument ca parametru numit, de exemplu `Foo(path: %appDir%)`.
-
-Nette DI și formatul NEON vă oferă facilități expresive extrem de puternice pentru a scrie aproape orice. Astfel, un argument poate fi un obiect nou creat, puteți apela metode statice, metode ale altor servicii sau chiar funcții globale folosind o notație specială:
+Pentru o mai bună lizibilitate, putem lista argumentele pe linii separate. În acest format, utilizarea virgulelor este opțională:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)         # creați un obiect
-		DateTime::createFromFormat('Y-m-d')  # apelați metoda statică
-		@anotherService                      # trecerea unui alt serviciu
-		@http.request::getRemoteAddress()    # apelarea unei alte metode de serviciu
-		::getenv(NetteMode)                  # apelarea unei funcții globale
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-Corespunde codului PHP:
-
-```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('NetteMode')
-	);
-}
-```
-
-
-Funcții speciale .[#toc-special-functions]
-------------------------------------------
-
-Puteți utiliza, de asemenea, funcții speciale în argumente pentru a transforma sau nega valori:
-
-- `not(%arg%)` negarea
-- `bool(%arg%)` cast fără pierderi în bool
-- `int(%arg%)` lossless cast to int
-- `float(%arg%)` lossless cast to float
-- `string(%arg%)` lossless cast to string
+Puteți, de asemenea, să denumiți argumentele, ceea ce vă permite să nu vă faceți griji cu privire la ordinea lor:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-Rescrierea fără pierderi diferă de rescrierea normală din PHP, de exemplu, folosind `(int)`, prin faptul că aruncă o excepție pentru valorile nenumerice.
-
-Mai multe servicii pot fi trecute ca argumente. Un tablou al tuturor serviciilor de un anumit tip (de exemplu, clasă sau interfață) este creat de funcția `typed()`. Funcția va omite serviciile care au cablarea automată dezactivată și pot fi specificate mai multe tipuri separate prin virgulă.
+Dacă doriți să omiteți anumite argumente și să folosiți valorile lor implicite sau să introduceți un serviciu prin [autocablare |autowiring], utilizați un semn de subliniere:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-De asemenea, puteți transmite automat o matrice de servicii utilizând [autowiring |autowiring#Collection of Services].
-
-O matrice a tuturor serviciilor cu o anumită [etichetă |#tags] este creată de funcția `tagged()`. Se pot specifica mai multe etichete separate prin virgulă.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Servicii de referință .[#toc-referencing-services]
-==================================================
-
-Serviciile individuale sunt referite folosind caracterul `@` and name, so for example `@database`:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-Corespunde codului PHP:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Chiar și serviciile anonime pot fi referite folosind un callback, trebuie doar să specificați tipul lor (clasă sau interfață) în loc de numele lor. Cu toate acestea, acest lucru nu este de obicei necesar din cauza [cablării automate |autowiring].
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # sau @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Argumentele pot fi servicii, parametri și multe altele, a se vedea [mijloacele de exprimare |#expression means].
 
 
 Configurare .[#toc-setup]
 =========================
 
-În secțiunea de configurare, enumerăm metodele care trebuie apelate la crearea serviciului:
+În secțiunea `setup`, se definesc metodele care trebuie apelate la crearea serviciului.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Corespunde codului PHP:
+În PHP, acest lucru ar arăta astfel:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-Proprietățile pot fi, de asemenea, setate. Adăugarea unui element la o matrice este, de asemenea, acceptată și trebuie scrisă între ghilimele pentru a nu intra în conflict cu sintaxa NEON:
-
+În plus față de apelurile la metode, puteți, de asemenea, să transmiteți valori la proprietăți. Adăugarea unui element la o matrice este, de asemenea, acceptată, dar trebuie să îl includeți între ghilimele pentru a evita coliziunea cu sintaxa NEON:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Corespunde codului PHP:
+În PHP, acest lucru s-ar traduce prin:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-Cu toate acestea, metodele statice sau metodele altor servicii pot fi, de asemenea, apelate în configurare. Le transmitem serviciul real ca `@self`:
-
+În configurare, puteți apela și metode statice sau metode ale altor servicii. Dacă aveți nevoie să treceți serviciul curent ca argument, utilizați `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Corespunde codului PHP:
+Rețineți că, pentru simplificare, în loc de `->`, folosim `::`, a se vedea [expresia înseamnă |#expression means]. Aceasta generează următoarea metodă de fabrică:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
+Mijloace de exprimare .[#toc-expression-means]
+==============================================
+
+Nette DI ne oferă capacități de exprimare excepțional de bogate, permițându-ne să articulăm aproape orice. În fișierele de configurare, putem utiliza [parametri |configuration#parameters]:
+
+```neon
+# parametru
+%wwwDir%
+
+# valoarea unui parametru sub o cheie de parametru
+%mailer.user%
+
+# parametru în cadrul unui șir de caractere
+'%wwwDir%/images'
+```
+
+De asemenea, putem crea obiecte, apela metode și funcții:
+
+```neon
+# creați un obiect
+DateTime()
+
+# apelarea unei metode statice
+Collator::create(%locale%)
+
+# apelarea unei funcții PHP
+::getenv(DB_USER)
+```
+
+Faceți referire la servicii fie prin numele lor, fie prin tipul lor:
+
+```neon
+# serviciu după nume
+@database
+
+# serviciu după tip
+@Nette\Database\Connection
+```
+
+Folosiți sintaxa de primă clasă a elementelor apelabile: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Utilizați constante:
+
+```neon
+# constantă de clasă
+FilesystemIterator::SKIP_DOTS
+
+# constantă globală obținută prin funcția PHP constant()
+::constant(PHP_VERSION)
+```
+
+Apelurile la metode pot fi înlănțuite, la fel ca în PHP. Pentru simplitate, în loc de `->`, folosim `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Aceste expresii pot fi utilizate oriunde la [crearea serviciilor |#Service Creation], în [argumente |#Arguments], în secțiunea de [configurare |#setup] sau în [parametri |configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Funcții speciale .[#toc-special-functions]
+------------------------------------------
+
+În cadrul fișierelor de configurare, puteți utiliza aceste funcții speciale:
+
+- `not()` pentru negarea valorilor
+- `bool()`, `int()`, `float()`, `string()` pentru turnarea fără pierderi a tipurilor
+- `typed()` pentru a genera o matrice a tuturor serviciilor de un tip specificat
+- `tagged()` pentru a crea o matrice a tuturor serviciilor cu o anumită etichetă
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+În comparație cu tipizarea convențională în PHP, cum ar fi `(int)`, tipizarea fără pierderi va arunca o excepție pentru valorile nenumerice.
+
+Funcția `typed()` creează o matrice cu toate serviciile de un anumit tip (clasă sau interfață). Aceasta exclude serviciile cu cablarea automată dezactivată. Se pot specifica mai multe tipuri, separate prin virgule.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+De asemenea, puteți transmite automat o matrice de servicii de un anumit tip ca argument, utilizând [autowiring |autowiring#Collection of Services].
+
+Funcția `tagged()` creează o matrice a tuturor serviciilor cu o etichetă specificată. Pot fi enumerate mai multe etichete, separate prin virgulă.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
 Cablare automată .[#toc-autowiring]
 ===================================
 
-Cheia autowired poate fi utilizată pentru a exclude un serviciu de la autowiring sau pentru a influența comportamentul acestuia. Pentru mai multe informații, consultați [capitolul despre autowiring |autowiring].
+Tasta `autowired` vă permite să modificați comportamentul de cablare automată pentru un anumit serviciu. Pentru mai multe detalii, consultați [capitolul privind cablarea automată |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo este eliminat din autocablarea
+		autowired: false     # serviciul foo este exclus de la cablarea automată
 ```
 
 
 Etichete .[#toc-tags]
 =====================
 
-Informațiile despre utilizatori pot fi adăugate la serviciile individuale sub formă de etichete:
+Etichetele sunt utilizate pentru a adăuga informații suplimentare la servicii. Puteți atribui una sau mai multe etichete unui serviciu:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Etichetele pot avea, de asemenea, o valoare:
+Etichetele pot avea și valori:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-O matrice de servicii cu anumite etichete poate fi transmisă ca argument cu ajutorul funcției `tagged()`. De asemenea, se pot specifica mai multe etichete separate prin virgulă.
+Pentru a prelua toate serviciile cu anumite etichete, puteți utiliza funcția `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Numele serviciilor pot fi obținute din containerul DI folosind metoda `findByTag()`:
+În containerul DI, puteți obține numele tuturor serviciilor cu o anumită etichetă utilizând metoda `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
 // $names este o matrice care conține numele serviciului și valoarea etichetei.
-// adică ['foo' => 'monolog.logger.event', ...]
+// de exemplu, ['foo' => 'monolog.logger.event', ...]
 ```
 
 
 Modul de injectare .[#toc-inject-mode]
 ======================================
 
-Indicatorul `inject: true` este utilizat pentru a activa trecerea dependențelor prin intermediul variabilelor publice cu adnotarea [inject |best-practices:inject-method-attribute#Inject Attributes] și metodele [inject*() |best-practices:inject-method-attribute#inject Methods].
+Utilizarea indicatorului `inject: true` activează trecerea dependențelor prin intermediul variabilelor publice cu adnotarea [inject |best-practices:inject-method-attribute#Inject Attributes] și metodele [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 În mod implicit, `inject` este activat numai pentru prezentatori.
 
 
-Modificarea serviciilor .[#toc-modification-of-services]
+Modificări ale serviciului .[#toc-service-modifications]
 ========================================================
 
-Există o serie de servicii în containerul DI care au fost adăugate prin încorporare sau prin [extensia dumneavoastră |#di-extensions]. Definițiile acestor servicii pot fi modificate în configurație. De exemplu, pentru serviciul `application.application`, care este în mod implicit un obiect `Nette\Application\Application`, putem modifica clasa:
+Containerul DI conține multe servicii adăugate fie prin [extensii |#extensions] încorporate, fie prin [extensii de utilizator |#extensions]. Puteți modifica definițiile acestor servicii direct în configurație. De exemplu, puteți schimba clasa serviciului `application.application`, care este în mod convențional `Nette\Application\Application`, în altceva:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Steagul `alteration` este informativ și spune că nu facem decât să modificăm un serviciu existent.
+Semnul `alteration` este informativ, indicând că nu facem decât să modificăm un serviciu existent.
 
-De asemenea, putem adăuga o configurare:
+De asemenea, putem completa configurația:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Atunci când rescriem un serviciu, este posibil să dorim să eliminăm argumentele, elementele de configurare sau etichetele inițiale, pentru aceasta existând `reset`:
+Atunci când suprascrieți un serviciu, este posibil să doriți să eliminați argumentele, elementele de configurare sau etichetele originale, și aici `reset` este util:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Un serviciu adăugat prin extensie poate fi, de asemenea, eliminat din container:
+Dacă doriți să eliminați un serviciu adăugat de o extensie, puteți face acest lucru în felul următor:
 
 ```neon
 services:
diff --git a/dependency-injection/ru/autowiring.texy b/dependency-injection/ru/autowiring.texy
index 1bf1746b0c..6c4a828720 100644
--- a/dependency-injection/ru/autowiring.texy
+++ b/dependency-injection/ru/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Затем контейнер DI автоматически передает массив сервисов, соответствующих заданному типу. При этом будут пропущены сервисы, у которых отключено автосвязывание.
 
-Если вы не можете контролировать форму комментария phpDoc, вы можете передать массив сервисов непосредственно в конфигурации, используя [`typed()`|services#Special-Functions].
+Тип в комментарии также может иметь вид `array<int, Class>` или `list<Class>`. Если нет возможности управлять формой комментария phpDoc, то можно передать массив сервисов непосредственно в конфигурации, используя [`typed()` |services#Special Functions].
 
 
 Скалярные аргументы .[#toc-scalar-arguments]
diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy
index a288072f02..db9e0d2c8d 100644
--- a/dependency-injection/ru/configuration.texy
+++ b/dependency-injection/ru/configuration.texy
@@ -67,7 +67,7 @@ parameters:
 ```neon
 decorator:
 	# Для всех сервисов, являющихся экземплярами этого класса или интерфейса
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # вызываем этот метод
 			- $absoluteUrls = true   # и задаем переменную
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Если вы не используете массив `$container->parameters`, можно отключить экспорт параметров. Кроме того, вы можете экспортировать только те теги, через которые вы получаете сервисы, используя метод `$container->findByTag(...)`.
+Если вы не используете массив `$container->getParameters()`, можно отключить экспорт параметров. Кроме того, вы можете экспортировать только те теги, через которые вы получаете сервисы, используя метод `$container->findByTag(...)`.
 Если вы не вызываете этот метод вовсе, можно полностью отключить экспорт тегов, указав значение `false`.
 
 Вы можете значительно уменьшить метаданные для автоматического подключения, указав классы, которые вы используете в качестве параметра в методе `$container->getByType()`.
@@ -191,20 +191,15 @@ return [
 
 ```neon
 search:
-	# вы сами выбираете названия секций
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Обычно, однако, мы не хотим добавлять все классы и интерфейсы, поэтому мы можем отфильтровать их:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# фильтрация по имени файла (string|string[])
 		files:
@@ -220,7 +215,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+файлы: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/ru/extensions.texy b/dependency-injection/ru/extensions.texy
index fea62eaef2..dee2ae9e5d 100644
--- a/dependency-injection/ru/extensions.texy
+++ b/dependency-injection/ru/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialization .[wiki-method]
 ==============================
 
-Configurator вызывается кодом инициализации после [создания контейнера |application:bootstrap#index-php], который создается путем записи в объект `$this->initialization` с помощью [метода addBody() |php-generator:#method-and-function-body].
+Configurator вызывается кодом инициализации после [создания контейнера |application:bootstrap#index-php], который создается путем записи в объект `$this->initialization` с помощью [метода addBody() |php-generator:#method-and-function-bodies].
 
 Мы покажем пример того, как запустить сессию или сервисы, которые имеют тег `run` с помощью кода инициализации:
 
diff --git a/dependency-injection/ru/factory.texy b/dependency-injection/ru/factory.texy
index 315896a1e7..21149c2339 100644
--- a/dependency-injection/ru/factory.texy
+++ b/dependency-injection/ru/factory.texy
@@ -170,39 +170,45 @@ services:
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Поэтому вместо того, чтобы передавать несколько сгенерированных фабрик и аксессоров, мы собираемся передать ещё одну сложную фабрику, которая может делать больше.
 
-Как вариант, вместо нескольких методов можно использовать параметры `create()` и `get()`:
+В качестве альтернативы можно использовать `get()` с параметром вместо нескольких методов:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Затем `MultiFactory::createArticle()` делает то же самое, что и `MultiFactoryAlt::create('article')`. Однако альтернативная нотация имеет тот недостаток, что неясно, какие значения `$name` поддерживаются, и логически невозможно различить разные возвращаемые значения для разных `$name` в интерфейсе.
+В этом случае `MultiFactory::getArticle()` делает то же самое, что и `MultiFactoryAlt::get('article')`. Однако альтернативный синтаксис имеет несколько недостатков. Неясно, какие значения `$name` поддерживаются, и нельзя указать тип возврата в интерфейсе при использовании нескольких различных значений `$name`.
 
 
 Определение списка .[#toc-definition-with-a-list]
 -------------------------------------------------
-А как определить множественную фабрику в конфигурации? Мы создадим три сервиса, которые будут создавать/возвращать, а затем и саму фабрику:
+Этот способ можно использовать для определения нескольких фабрик в конфигурации: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Или в определении фабрики мы можем ссылаться на существующие сервисы с помощью ссылки:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ services:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.context
 	)
diff --git a/dependency-injection/ru/faq.texy b/dependency-injection/ru/faq.texy
index bf7d5b1260..815c0bc076 100644
--- a/dependency-injection/ru/faq.texy
+++ b/dependency-injection/ru/faq.texy
@@ -61,7 +61,7 @@ DI не влияет на производительность приложен
 
 Почему композиция предпочтительнее наследования? .[#toc-why-composition-is-preferred-over-inheritance]
 ------------------------------------------------------------------------------------------------------
-Предпочтительнее использовать композицию, а не наследование, так как она служит цели повторного использования кода без необходимости беспокоиться о нисходящем эффекте изменений. Таким образом, это обеспечивает более свободную связь, где нам не нужно беспокоиться о том, что изменение какого-то кода приведет к тому, что другой зависимый код потребует изменений. Типичным примером является ситуация, называемая [ад конструкторов |passing-dependencies#Constructor hell].
+Предпочтительнее использовать [композицию |nette:introduction-to-object-oriented-programming#composition] вместо [наследования |nette:introduction-to-object-oriented-programming#inheritance], поскольку она позволяет повторно использовать код, не заботясь о последствиях изменений. Таким образом, обеспечивается более тесная связь, когда не нужно беспокоиться о том, что изменение одного кода приведет к необходимости изменения другого, зависимого кода. Типичным примером является ситуация, называемая " [адом конструкторов |passing-dependencies#Constructor hell]".
 
 
 Можно ли использовать Nette DI Container вне Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/ru/global-state.texy b/dependency-injection/ru/global-state.texy
index fd015989bb..3e32260d4e 100644
--- a/dependency-injection/ru/global-state.texy
+++ b/dependency-injection/ru/global-state.texy
@@ -301,4 +301,4 @@ class Foo
 
 Во время этого процесса вы можете обнаружить, что вам нужно разделить класс, потому что он несет более одной ответственности. Не беспокойтесь об этом; стремитесь к принципу одной ответственности.
 
-*Я хотел бы поблагодарить Мишко Хевери, чьи статьи, такие как [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], легли в основу этой главы*.
+*Я хотел бы поблагодарить Мишко Хевери, чьи статьи, такие как [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], легли в основу этой главы*.
diff --git a/dependency-injection/ru/passing-dependencies.texy b/dependency-injection/ru/passing-dependencies.texy
index 31202bcf86..069d13d329 100644
--- a/dependency-injection/ru/passing-dependencies.texy
+++ b/dependency-injection/ru/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Проблема возникает, когда мы хотим изменить конструктор класса `BaseClass`, например, когда добавляется новая зависимость. Тогда мы должны изменить все конструкторы дочерних классов. Что превращает такую модификацию в ад.
 
-Как предотвратить это? Решение заключается в **приоритете композиции над наследованием**.
+Как предотвратить это? Решение заключается в **приоритете [композиции над наследованием** |faq#Why composition is preferred over inheritance].
 
-Поэтому давайте спроектируем код по-другому. Мы будем избегать абстрактных классов `Base*`. Вместо того чтобы `MyClass` получал некоторую функциональность, наследуя от `BaseClass`, эта функциональность будет передаваться ему как зависимость:
+Поэтому давайте спроектируем код по-другому. Мы будем избегать [абстрактных |nette:introduction-to-object-oriented-programming#abstract-classes] классов `Base*`. Вместо того чтобы `MyClass` получал некоторую функциональность, наследуя от `BaseClass`, ему будет передаваться эта функциональность как зависимость:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ The setter call is defined in the DI container configuration in [section setup |
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ $obj->cache = $cache;
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/ru/services.texy b/dependency-injection/ru/services.texy
index 3af9d1f2e7..4d3b112eab 100644
--- a/dependency-injection/ru/services.texy
+++ b/dependency-injection/ru/services.texy
@@ -2,32 +2,32 @@
 ********************
 
 .[perex]
-Конфигурация — это место, где мы размещаем определения пользовательских сервисов. Делается это в секции `services`.
+Конфигурация - это место, где мы указываем DI-контейнеру, как собирать отдельные сервисы и как связывать их с другими зависимостями. Nette предоставляет очень понятный и элегантный способ достижения этой цели.
 
-Например, вот как мы создаем сервис с именем `database`, который будет экземпляром класса `PDO`:
+Секция `services` в конфигурационном файле NEON - это место, где мы определяем наши пользовательские сервисы и их конфигурации. Рассмотрим простой пример определения сервиса с именем `database`, который представляет собой экземпляр класса `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Именование служб используется для того, чтобы мы могли [ссылаться|#Referencing-Services] на них. Если на сервис не ссылаются, нет необходимости давать ему имя. Поэтому вместо имени мы просто используем двоеточие:
+Эта конфигурация приводит к появлению следующего фабричного метода в [контейнере DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  # анонимный сервис
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Однострочная запись может быть разбита на несколько строк, чтобы можно было добавить дополнительные ключи, например [#setup]. Псевдоним для ключа `create:` - `factory:`.
+Имена сервисов позволяют ссылаться на них в других частях конфигурационного файла, используя формат `@serviceName`. Если нет необходимости присваивать сервису имя, можно просто использовать пулевую точку:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Затем мы получаем сервис из контейнера DI, используя метод `getService()` по имени, или, что ещё лучше, метод `getByType()` по типу:
+Для получения сервиса из DI-контейнера можно использовать метод `getService()` с именем сервиса в качестве параметра или метод `getByType()` с типом сервиса:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Создание сервиса .[#toc-creating-a-service]
-===========================================
+Создание сервиса .[#toc-service-creation]
+=========================================
 
-Чаще всего мы создаем сервис, просто создавая экземпляр класса:
+Чаще всего мы создаем сервис, просто инстанцируя определенный класс. Например:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Что создаст фабричный метод в [DI-контейнере|container]:
+Если нам необходимо расширить конфигурацию дополнительными ключами, то определение может быть разложено на несколько строк:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Альтернативно, ключ `arguments` может быть использован для передачи [аргументов|#Arguments]:
+Ключ `create` имеет псевдоним `factory`, оба варианта распространены на практике. Однако мы рекомендуем использовать `create`.
+
+В качестве альтернативы аргументы конструктора или метод создания могут быть записаны в ключе `arguments`:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Статический метод также может создать сервис:
+Сервисы не обязательно должны создаваться только простым инстанцированием класса; они также могут возникать в результате вызова статических методов или методов других сервисов:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Это эквивалентно коду PHP:
+Заметим, что для простоты вместо `->`, мы используем `::`, см. [выражения |#expression means]. Эти фабричные методы генерируются:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Предполагается, что статический метод `My\Database::create()` имеет определенное возвращаемое значение, которое должен знать контейнер DI. Если у него его нет, мы записываем тип в конфигурацию:
+DI-контейнер должен знать тип создаваемого сервиса. Если мы создаем сервис с помощью метода, который не имеет заданного возвращаемого типа, то мы должны явно указать этот тип в конфигурации:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Nette DI предоставляет вам чрезвычайно мощные средства выражения, позволяющие написать практически всё, что угодно. Например, чтобы [обратиться|#Referencing-Services] к другой службе и вызвать её метод. Для простоты вместо `->` используется `::`.
+
+Аргументы .[#toc-arguments]
+===========================
+
+Передача аргументов конструкторам и методам осуществляется аналогично обычному PHP:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Это эквивалентно коду PHP:
+Для лучшей читабельности мы можем перечислять аргументы в отдельных строках. В этом формате использование запятых необязательно:
 
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
-
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-Вызовы методов можно объединять в цепочки, как в PHP:
+Можно также назвать аргументы, и тогда можно не заботиться об их порядке:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Это эквивалентно коду PHP:
+Если вы хотите опустить некоторые аргументы и использовать их значения по умолчанию или вставить функцию с помощью [автоподключения |autowiring], используйте символ подчеркивания:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Аргументами могут быть сервисы, параметры и многое другое, см. [средства выражения |#expression means].
 
-Аргументы .[#toc-arguments]
-===========================
 
-Именованные параметры также могут использоваться для передачи аргументов:
+Настройка .[#toc-setup]
+=======================
+
+В разделе `setup` мы определяем методы, которые должны вызываться при создании сервиса.
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # позиционный
-		username: root                      # именованный
-		password: secret                    # именованный
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Использование запятых необязательно при разбиении аргументов на несколько строк.
+На языке PHP это выглядит следующим образом:
 
-Конечно, мы также можем использовать [другие сервисы|#Referencing-Services] или [параметры|configuration#Parameters] в качестве аргументов:
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
+
+Помимо вызовов методов, можно передавать значения в свойства. Добавление элемента в массив также поддерживается, но его необходимо заключать в кавычки, чтобы избежать столкновения с синтаксисом NEON:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Соответствует коду PHP:
+В PHP это будет выглядеть так:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-Если первый аргумент - [автомонтируемый|autowiring], а вы хотите указать второй, опустите первый с помощью символа `_`, например `Foo(_, %appDir%)`. Или, что ещё лучше, передавайте только второй аргумент в качестве именованного параметра, например: `Foo(path: %appDir%)`.
-
-Nette DI и формат NEON дают вам чрезвычайно мощные выразительные средства, позволяющие написать практически всё, что угодно. Таким образом, аргументом может быть вновь созданный объект, вы можете вызывать статические методы, методы других сервисов или даже глобальные функции, используя специальную нотацию:
+В настройке можно также вызывать статические методы или методы других сервисов. Если необходимо передать текущий сервис в качестве аргумента, используйте `@self`:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)         # создаем объект
-		DateTime::createFromFormat('Y-m-d')  # вызываем статический метод
-		@anotherService                      # передаём другой сервис
-		@http.request::getRemoteAddress()    # вызываем метод другого сервиса
-		::getenv(NetteMode)                  # вызываем глобальную функцию
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Соответствует коду PHP:
+Обратите внимание, что для простоты вместо `->` мы используем `::`, см. [средства выражения |#expression means]. В результате формируется следующий фабричный метод:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-Специальные функции .[#toc-special-functions]
----------------------------------------------
-
-Вы также можете использовать специальные функции в аргументах для приведения или отрицания значений:
+Средства выражения .[#toc-expression-means]
+===========================================
 
-- `not(%arg%)` отрицание
-- `bool(%arg%)` приведение к bool без потерь
-- `int(%arg%)` приведение к int без потерь
-- `float(%arg%)` приведение к плавающему состоянию без потерь
-- `string(%arg%)` приведение к строке без потерь
+Nette DI предоставляет нам исключительно богатые возможности выражения, позволяющие сформулировать практически все, что угодно. В конфигурационных файлах мы можем использовать [параметры |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
-
-Переписывание без потерь отличается от обычного переписывания в PHP, например используя `(int)`, в том, что оно выбрасывает исключение для нечисловых значений.
+# параметр
+%wwwDir%
 
-В качестве аргументов можно передавать несколько сервисов. Массив всех сервисов определенного типа (т. е. класса или интерфейса) создается функцией `typed()`. Функция будет опускать сервисы, у которых отключено автоподключение, при этом можно указать несколько типов, разделенных запятой.
+# значение под ключом параметра
+%mailer.user%
 
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# параметр в строке
+'%wwwDir%/images'
 ```
 
-Вы также можете передать массив сервисов автоматически, используя [автосвязывание|autowiring#Collection-of-Services].
-
-Массив всех сервисов с определенным [тегом|#Tags] создается функцией `tagged()`. Можно указать несколько тегов, разделенных запятой.
+Мы также можем создавать объекты, вызывать методы и функции:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# создать объект
+DateTime()
 
+# вызов статического метода
+Collator::create(%locale%)
 
-Ссылки на сервисы .[#toc-referencing-services]
-==============================================
+# вызвать функцию PHP
+::getenv(DB_USER)
+```
 
-Ссылки на отдельные сервисы используются с помощью символа `@` и имени, например `@database`:
+Ссылайтесь на сервисы либо по их имени, либо по типу:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# услуга по названию
+@database
+
+# услуга по типу
+@Nette\Database\Connection
 ```
 
-Соответствует коду PHP:
+Используйте синтаксис первоклассных вызываемых элементов: .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-Даже на анонимные сервисы можно ссылаться с помощью обратного вызова, просто укажите их тип (класс или интерфейс) вместо имени. Однако обычно в этом нет необходимости из-за [автосвязывания|autowiring].
+Использовать константы:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # или @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# константа класса
+FilesystemIterator::SKIP_DOTS
+
+# глобальная константа, получаемая с помощью PHP-функции constant()
+::constant(PHP_VERSION)
 ```
 
+Вызовы методов, как и в PHP, можно объединять в цепочки. Для простоты вместо `->` мы используем `::`:
 
-Setup
-=====
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
 
-В секции `setup` мы перечисляем методы, которые будут вызываться при создании сервиса:
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Эти выражения можно использовать в любом месте при [создании сервисов |#Service Creation], в [аргументах |#Arguments], в секции [настройки |#setup] или [параметрах |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Соответствует коду PHP:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Специальные функции .[#toc-special-functions]
+---------------------------------------------
 
-Также можно установить свойства. Добавление элемента в массив также поддерживается, и его следует писать в кавычках, чтобы не конфликтовать с синтаксисом NEON:
+В конфигурационных файлах можно использовать эти специальные функции:
 
+- `not()` для отрицания значений
+- `bool()`, `int()`, `float()`, `string()` для приведения типов без потерь
+- `typed()` для создания массива всех сервисов заданного типа
+- `tagged()` для создания массива всех сервисов с заданным тегом
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Соответствует коду PHP:
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-Однако статические методы или методы других сервисов также могут быть вызваны в настройке. Мы передаем им фактический сервис как `@self`:
+По сравнению с обычным приведением типов в PHP, например, `(int)`, при приведении типов без потерь будет возникать исключение для нечисловых значений.
 
+Функция `typed()` создает массив всех сервисов определенного типа (класса или интерфейса). При этом исключаются сервисы с выключенным автоподключением. Можно указать несколько типов, разделяя их запятыми.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Соответствует коду PHP:
+Также можно автоматически передать массив сервисов определенного типа в качестве аргумента при использовании [автоподключения |autowiring#Collection of Services].
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+Функция `tagged()` создает массив всех сервисов с указанным тегом. Можно перечислить несколько тегов, разделяя их запятыми.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-Автосвязывание .[#toc-autowiring]
-=================================
+Автоэлектрика .[#toc-autowiring]
+================================
 
-Ключ `autowired` можно использовать для исключения сервиса из автосвязывания или для влияния на его поведение. Более подробную информацию см. в главе [Автосвязывание|autowiring].
+Ключ `autowired` позволяет модифицировать поведение автоподключения для конкретного сервиса. Более подробная информация приведена в [главе, посвященной автоподключению |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo удаляется из автосвязывания
+		autowired: false     # служба foo исключена из автоподключения
 ```
 
 
 Теги .[#toc-tags]
 =================
 
-Информация о пользователе может быть добавлена к отдельным сервисам в виде тегов:
+Теги используются для добавления дополнительной информации к сервисам. Вы можете назначить сервису один или несколько тегов:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Теги также могут иметь значение:
+Теги также могут иметь значения:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Массив сервисов с определенными тегами может быть передан в качестве аргумента с помощью функции `tagged()`. Можно также указать несколько тегов, разделенных запятой.
+Чтобы получить все услуги с определенными тегами, можно воспользоваться функцией `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Имена служб можно получить из контейнера DI с помощью метода `findByTag()`:
+В контейнере DI можно получить имена всех сервисов с определенным тегом с помощью метода `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
 // $names - массив, содержащий имя сервиса и значение тега
-// например ['foo' => 'monolog.logger.event', ...]
+// например, ['foo' => 'monolog.logger.event', ...].
 ```
 
 
-Режим внедрения .[#toc-inject-mode]
-===================================
+Режим инжекции .[#toc-inject-mode]
+==================================
 
-Флаг `inject: true` используется для активации передачи зависимостей через публичные переменные с помощью аннотации [inject |best-practices:inject-method-attribute#Inject Attributes] и методов [inject*() |best-practices:inject-method-attribute#inject Methods].
+Использование флага `inject: true` активизирует передачу зависимостей через публичные переменные с помощью аннотации [inject |best-practices:inject-method-attribute#Inject Attributes] и методов [inject*() |best-practices:inject-method-attribute#inject Methods].
 
 ```neon
 services:
@@ -398,13 +391,13 @@ services:
 		inject: true
 ```
 
-По умолчанию `inject` активируется только для презентеров.
+По умолчанию `inject` активизируется только для ведущих.
 
 
-Модификация сервисов .[#toc-modification-of-services]
-=====================================================
+Модификации сервиса .[#toc-service-modifications]
+=================================================
 
-В контейнере DI есть ряд сервисов, которые были добавлены встроенным или [вашим расширением|#di-extension]. Определения этих сервисов могут быть изменены в конфигурации. Например, для сервиса `application.application`, который по умолчанию является объектом `Nette\Application\Application`, мы можем изменить класс:
+Контейнер DI содержит множество сервисов, добавленных как встроенными, так и [пользовательскими расширениями |#extensions]. Определения этих сервисов можно изменять непосредственно в конфигурации. Например, можно изменить класс сервиса `application.application`, который условно называется `Nette\Application\Application`, на другой:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Флаг `alteration` является информативным и говорит о том, что мы просто изменяем существующий сервис.
+Флаг `alteration` является информативным и указывает на то, что мы просто модифицируем существующий сервис.
 
-Мы также можем добавить `setup`:
+Мы также можем дополнить настройку:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-При перезаписи сервиса мы можем удалить исходные аргументы, элементы `setup` или теги, для которых `reset` является:
+При перезаписи сервиса может потребоваться удалить исходные аргументы, элементы настройки или теги, и здесь пригодится `reset`:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Сервис, добавленный расширением, также может быть удален из контейнера:
+Если необходимо удалить сервис, добавленный расширением, это можно сделать следующим образом:
 
 ```neon
 services:
diff --git a/dependency-injection/sl/autowiring.texy b/dependency-injection/sl/autowiring.texy
index db5b689b51..fbeccc1741 100644
--- a/dependency-injection/sl/autowiring.texy
+++ b/dependency-injection/sl/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Vsebnik DI nato samodejno posreduje polje storitev, ki ustrezajo dani vrsti. Izpusti storitve, ki imajo izklopljeno samodejno napeljavo.
 
-Če ne morete nadzorovati oblike komentarja phpDoc, lahko polje storitev posredujete neposredno v konfiguraciji z uporabo [`typed()` |services#Special Functions].
+Vrsta v komentarju je lahko tudi v obliki `array<int, Class>` ali `list<Class>`. Če ne morete nadzorovati oblike komentarja phpDoc, lahko posredujete polje storitev neposredno v konfiguraciji z uporabo [`typed()` |services#Special Functions].
 
 
 Skalarni argumenti .[#toc-scalar-arguments]
diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy
index 66f22356d4..f815b42c31 100644
--- a/dependency-injection/sl/configuration.texy
+++ b/dependency-injection/sl/configuration.texy
@@ -67,7 +67,7 @@ Kako množično urediti vse storitve določene vrste? Ali morate poklicati dolo
 ```neon
 decorator:
 	# za vse storitve, ki so primerki tega razreda ali vmesnika.
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)       # pokliče to metodo
 			- $absoluteUrls = true   # in nastavi spremenljivko
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Če ne uporabljate polja `$container->parameters`, lahko onemogočite izvoz parametrov. Poleg tega lahko izvozite samo tiste oznake, prek katerih pridobivate storitve z uporabo metode `$container->findByTag(...)`.
+Če ne uporabljate polja `$container->getParameters()`, lahko onemogočite izvoz parametrov. Poleg tega lahko izvozite samo tiste oznake, prek katerih pridobivate storitve z uporabo metode `$container->findByTag(...)`.
 Če metode sploh ne kličete, lahko izvoz značk popolnoma onemogočite z metodo `false`.
 
 Metapodatke za [samodejno vnašanje |autowiring] lahko bistveno zmanjšate tako, da razrede, ki jih uporabljate, določite kot parameter metode `$container->getByType()`.
@@ -191,20 +191,15 @@ Samo določite, v katerih imenikih (in podimenikih) naj se razredi iščejo:
 
 ```neon
 search:
-	# imena razdelkov izberete sami.
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Običajno ne želimo dodati vseh razredov in vmesnikov, zato jih lahko filtriramo:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# filtriranje po imenu datoteke (niz|recept[])
 		files:
@@ -220,7 +215,7 @@ Lahko pa izberemo razrede, ki dedujejo ali implementirajo vsaj enega od naslednj
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Določite lahko tudi negativna pravila, tj. maske imen razredov ali prednikov, i
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+datoteke: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Za dodane storitve lahko nastavite oznake:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/sl/extensions.texy b/dependency-injection/sl/extensions.texy
index 6deff98ca1..cc56617c46 100644
--- a/dependency-injection/sl/extensions.texy
+++ b/dependency-injection/sl/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialization .[wiki-method]
 ==============================
 
-Konfigurator pokliče inicializacijsko kodo po [ustvarjanju vsebnika |application:bootstrap#index.php], ki se ustvari z zapisom v objekt `$this->initialization` z [metodo addBody() |php-generator:#method-and-function-body].
+Konfigurator pokliče inicializacijsko kodo po [ustvarjanju vsebnika |application:bootstrap#index.php], ki se ustvari z zapisom v objekt `$this->initialization` z [metodo addBody() |php-generator:#method-and-function-bodies].
 
 Prikazali bomo primer, kako z inicializacijsko kodo zaženemo sejo ali zaženemo storitve, ki imajo oznako `run`:
 
diff --git a/dependency-injection/sl/factory.texy b/dependency-injection/sl/factory.texy
index e13c164e8e..6fba37cb35 100644
--- a/dependency-injection/sl/factory.texy
+++ b/dependency-injection/sl/factory.texy
@@ -170,39 +170,45 @@ Do zdaj so lahko tovarne in dostopniki ustvarili ali vrnili samo en predmet. Ust
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Namesto več ustvarjenih tovarn in dostopov lahko posredujete samo eno kompleksno večfazno tovarno.
 
-Namesto več metod lahko uporabite tudi `create()` in `get()` s parametrom:
+Namesto več metod lahko uporabite tudi `get()` s parametrom:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-V tem primeru `MultiFactory::createArticle()` naredi isto kot `MultiFactoryAlt::create('article')`. Vendar ima alternativna sintaksa nekaj pomanjkljivosti. Ni jasno, katere vrednosti `$name` so podprte, v vmesniku pa ni mogoče določiti tipa vrnitve, če uporabljate več različnih vrednosti `$name`.
+V tem primeru `MultiFactory::getArticle()` naredi isto kot `MultiFactoryAlt::get('article')`. Vendar ima alternativna sintaksa nekaj pomanjkljivosti. Ni jasno, katere vrednosti `$name` so podprte, v vmesniku pa ni mogoče določiti tipa vrnitve pri uporabi več različnih vrednosti `$name`.
 
 
 Opredelitev s seznamom .[#toc-definition-with-a-list]
 -----------------------------------------------------
-Hos opredeliti večpredstavnostno zbirko v svoji konfiguraciji? Ustvarimo tri storitve, ki jih bo vrnila večfazarnica, in samo večfazarnico:
+Na ta način lahko v konfiguraciji določite več tovarn: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Lahko pa se v definiciji tovarne sklicujemo na obstoječe storitve s pomočjo reference:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Druga možnost, kako opredeliti večpredstavnostno zbirko, je uporaba [oznak |se
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/sl/faq.texy b/dependency-injection/sl/faq.texy
index 52b344bd7a..f7ca52162b 100644
--- a/dependency-injection/sl/faq.texy
+++ b/dependency-injection/sl/faq.texy
@@ -61,7 +61,7 @@ Ne pozabite, da je prehod na vbrizgavanje odvisnosti naložba v kakovost kode in
 
 Zakaj ima sestava prednost pred dedovanjem? .[#toc-why-composition-is-preferred-over-inheritance]
 -------------------------------------------------------------------------------------------------
-Namesto dedovanja je bolje uporabiti sestavo, saj je tako mogoče kodo ponovno uporabiti, ne da bi bilo treba skrbeti za učinek sprememb. Tako zagotavlja bolj ohlapno vezavo, pri kateri nam ni treba skrbeti, da bi sprememba neke kode povzročila spremembo druge odvisne kode. Tipičen primer je situacija, ki je opredeljena kot [pekel konstruktorjev |passing-dependencies#Constructor hell].
+Namesto [dedovanja |nette:introduction-to-object-oriented-programming#inheritance] je bolje uporabiti [sestavo |nette:introduction-to-object-oriented-programming#composition], saj omogoča ponovno uporabo kode, ne da bi morali skrbeti za posledice sprememb. Tako zagotavlja ohlapnejšo vezavo, pri kateri nam ni treba skrbeti, da bo sprememba neke kode povzročila potrebo po spremembi druge odvisne kode. Značilen primer je situacija, ki se imenuje [konstruktorski pekel |passing-dependencies#Constructor hell].
 
 
 Ali se lahko vsebnik Nette DI Container uporablja zunaj sistema Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/sl/global-state.texy b/dependency-injection/sl/global-state.texy
index 841f1d51ab..6650892f07 100644
--- a/dependency-injection/sl/global-state.texy
+++ b/dependency-injection/sl/global-state.texy
@@ -301,4 +301,4 @@ Ko razmišljate o oblikovanju kode, imejte v mislih, da vsaka stran `static $foo
 
 Med tem postopkom boste morda ugotovili, da morate razred razdeliti, ker ima več kot eno odgovornost. Ne skrbite zaradi tega; prizadevajte si za načelo ene odgovornosti.
 
-*Zahvaljujem se Mišku Heveryju, čigar članki, kot je [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], so podlaga za to poglavje.*
+*Zahvaljujem se Mišku Heveryju, čigar članki, kot je [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], so podlaga za to poglavje.*
diff --git a/dependency-injection/sl/passing-dependencies.texy b/dependency-injection/sl/passing-dependencies.texy
index 451f940105..e9bb7e1997 100644
--- a/dependency-injection/sl/passing-dependencies.texy
+++ b/dependency-injection/sl/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Težava se pojavi, ko želimo spremeniti konstruktor razreda `BaseClass`, na primer ko dodamo novo odvisnost. Takrat moramo spremeniti tudi vse konstruktorje otrok. Zaradi tega je takšna sprememba pekel.
 
-Kako to preprečiti? Rešitev je, da **prednost dajemo kompoziciji pred dedovanjem**.
+Kako to preprečiti? Rešitev je, da dajete prednost [sestavi pred dedovanjem** |faq#Why composition is preferred over inheritance].
 
-Zato kodo oblikujmo drugače. Izogibali se bomo abstraktnim `Base*` razredom. Namesto da bi razred `MyClass` pridobil neko funkcionalnost s podedovanjem od razreda `BaseClass`, mu bo ta funkcionalnost posredovana kot odvisnost:
+Zato kodo oblikujmo drugače. Izognili se bomo [abstraktnim |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` razredom. Namesto da bi razred `MyClass` pridobil določeno funkcionalnost s podedovanjem od razreda `BaseClass`, mu bo ta funkcionalnost posredovana kot odvisnost:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ Klic setterja je opredeljen v konfiguraciji vsebnika DI v [razdelku setup |servi
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Nastavitev spremenljivke je opredeljena v konfiguraciji vsebnika DI v [razdelku
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/sl/services.texy b/dependency-injection/sl/services.texy
index 854a61e05a..c62d1ef123 100644
--- a/dependency-injection/sl/services.texy
+++ b/dependency-injection/sl/services.texy
@@ -2,32 +2,32 @@ Opredelitve storitev
 ********************
 
 .[perex]
-Konfiguracija je mesto, kamor postavimo opredelitve storitev po meri. To storimo v razdelku `services`.
+Konfiguracija je mesto, kjer vsebniku DI naročimo, kako naj sestavi posamezne storitve in kako naj jih poveže z drugimi odvisnostmi. Nette ponuja zelo jasen in eleganten način za doseganje tega cilja.
 
-Tako na primer ustvarimo storitev z imenom `database`, ki bo primerek razreda `PDO`:
+V razdelku `services` v konfiguracijski datoteki NEON opredelimo svoje storitve po meri in njihove konfiguracije. Oglejmo si preprost primer opredelitve storitve z imenom `database`, ki predstavlja primerek razreda `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Poimenovanje storitev se uporablja zato, da [se |#Referencing Services] lahko nanje [sklicujemo |#Referencing Services]. Če se na storitev ne sklicujemo, je ni treba poimenovati. Zato namesto imena uporabimo le točko:
+Rezultat te konfiguracije je naslednja tovarniška metoda v [vsebniku DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  # anonimna storitev
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Enovrstični vnos lahko razdelimo v več vrstic, da lahko dodamo dodatne tipke, kot je [nastavitev |#setup]. Vzdevek za ključ `create:` je `factory:`.
+Imena storitev nam omogočajo sklicevanje nanje v drugih delih konfiguracijske datoteke v obliki `@serviceName`. Če storitve ni treba poimenovati, lahko preprosto uporabimo točko:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Storitev nato prikličemo iz vsebnika DI z metodo `getService()` po imenu ali, še bolje, z metodo `getByType()` po vrsti:
+Za pridobitev storitve iz vsebnika DI lahko uporabimo metodo `getService()` z imenom storitve kot parametrom ali metodo `getByType()` s tipom storitve:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Ustvarjanje storitve .[#toc-creating-a-service]
-===============================================
+Ustvarjanje storitev .[#toc-service-creation]
+=============================================
 
-Storitev najpogosteje ustvarimo tako, da preprosto ustvarimo primerek razreda:
+Najpogosteje ustvarimo storitev tako, da instanciramo določen razred. Na primer:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-To ustvari tovarniško metodo v [vsebniku DI |container]:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Za posredovanje [argumentov |#Arguments] se lahko uporabi tudi ključ `arguments`:
+Če moramo konfiguracijo razširiti z dodatnimi ključi, lahko definicijo razširimo v več vrstic:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-Statična metoda lahko ustvari tudi storitev:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Ustreza kodi PHP:
+Ključ `create` ima vzdevek `factory`, obe različici sta v praksi pogosti. Vendar priporočamo uporabo ključa `create`.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-Predpostavlja se, da ima statična metoda `My\Database::create()` določeno povratno vrednost, ki jo mora vsebnik DI poznati. Če je nima, zapišemo tip v konfiguracijo:
+Argumente konstruktorja ali metodo ustvarjanja lahko alternativno zapišete v ključu `arguments`:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Nette DI vam omogoča izjemno zmogljive izrazne zmogljivosti za zapisovanje skoraj vsega. Na primer za [sklicevanje na |#Referencing Services] drugo storitev in klic njene metode. Zaradi enostavnosti se namesto `->` uporablja `::`.
+Storitve niso nujno ustvarjene samo z enostavno instanciacijo razreda; lahko so tudi posledica klica statičnih metod ali metod drugih storitev:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-Ustreza kodi PHP:
+Upoštevajte, da zaradi enostavnosti namesto `->` uporabljamo `::`, glej [izrazna sredstva |#expression means]. Te tovarniške metode so ustvarjene:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-klice metod je mogoče verižno povezati kot v PHP:
+vsebnik DI mora poznati vrsto ustvarjene storitve. Če ustvarimo storitev z metodo, ki nima določene vrnitvene vrste, moramo to vrsto izrecno navesti v konfiguraciji:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-Ustreza kodi PHP:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argumenti .[#toc-arguments]
 ===========================
 
-Poimenovane parametre lahko uporabite tudi za posredovanje argumentov:
+Argumente konstruktorjem in metodam posredujemo na zelo podoben način kot v običajnem jeziku PHP:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # pozicijski
-		username: root                      # poimenovani
-		password: secret                    # named
-	)
-```
-
-Uporaba vejic ni obvezna, če se argumenti razdelijo v več vrstic.
-
-Seveda lahko kot argumente uporabimo tudi [druge storitve |#Referencing Services] ali [parametre |configuration#parameters]:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-Ustreza kodi PHP:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Če je prvi argument [samodejen |autowiring] in želite navesti drugega, izpustite prvega z `_` character, for example `Foo(_, %appDir%)`. Ali še bolje, samo drugi argument predajte kot poimenovani parameter, npr. `Foo(path: %appDir%)`.
-
-Nette DI in format NEON vam omogočata izjemno močne izrazne možnosti za zapisovanje skoraj vsega. Tako je lahko argument novo ustvarjen objekt, s posebnim zapisom lahko kličete statične metode, metode drugih storitev ali celo globalne funkcije:
+Za boljšo berljivost lahko argumente navedemo v ločenih vrsticah. V tej obliki je uporaba vejic neobvezna:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)         # ustvariti predmet
-		DateTime::createFromFormat('Y-m-d')  # klic statične metode
-		@anotherService                      # posredovanje druge storitve
-		@http.request::getRemoteAddress()    # klic druge metode storitve
-		::getenv(NetteMode)                  # klic globalne funkcije
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-Ustreza kodi PHP:
-
-```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('NetteMode')
-	);
-}
-```
-
-
-Posebne funkcije .[#toc-special-functions]
-------------------------------------------
-
-Posebne funkcije lahko uporabite tudi v argumentih za izločanje ali zanikanje vrednosti:
-
-- `not(%arg%)` zanikanje
-- `bool(%arg%)` brez izgub odlitek v bool
-- `int(%arg%)` brez izgub v int
-- `float(%arg%)` brez izgub v float
-- `string(%arg%)` brez izgube v niz
+Argumente lahko tudi poimenujete, kar vam omogoča, da se ne ukvarjate z njihovim vrstnim redom:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-Brezizgubno prepisovanje se razlikuje od običajnega prepisovanja v PHP, npr. z uporabo `(int)`, po tem, da vrže izjemo za neštevilčne vrednosti.
-
-Kot argumente je mogoče posredovati več storitev. Polje vseh storitev določene vrste (tj. razreda ali vmesnika) ustvari funkcija `typed()`. Funkcija bo izpustila storitve, ki imajo onemogočeno samodejno napeljavo, lahko pa se določi več vrst, ločenih z vejico.
+Če želite določene argumente izpustiti in uporabiti njihove privzete vrednosti ali vstaviti storitev prek [samodejnega napeljevanja |autowiring], uporabite podčrtaj:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-Polje storitev lahko posredujete tudi samodejno z uporabo [samodejnega napeljevanja |autowiring#Collection of Services].
-
-Polje vseh storitev z določeno [oznako |#tags] ustvari funkcija `tagged()`. Navedete lahko več oznak, ločenih z vejico.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Sklicevanje na storitve .[#toc-referencing-services]
-====================================================
-
-Na posamezne storitve se sklicujemo z uporabo znakov `@` and name, so for example `@database`:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-Ustreza kodi PHP:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Tudi na anonimne storitve se lahko sklicujete s povratnim klicem, le namesto imena navedite njihovo vrsto (razred ali vmesnik). Vendar to običajno ni potrebno zaradi [samodejnega povezovanja |autowiring].
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # ali @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Argumenti so lahko storitve, parametri in še veliko več, glejte [izrazna sredstva |#expression means].
 
 
 Nastavitev .[#toc-setup]
 ========================
 
-V razdelku nastavitev so naštete metode, ki jih je treba poklicati pri ustvarjanju storitve:
+V razdelku `setup` opredelimo metode, ki jih je treba poklicati pri ustvarjanju storitve.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Ustreza kodi PHP:
+V jeziku PHP bi bilo to videti takole:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-Nastavite lahko tudi lastnosti. Podprto je tudi dodajanje elementa v polje, ki ga je treba zapisati v narekovajih, da ne bo v nasprotju s sintakso NEON:
-
+Poleg klicev metod lahko lastnostim posredujete tudi vrednosti. Podprto je tudi dodajanje elementa v polje, vendar ga morate zapreti v narekovaje, da ne pride do kolizije s sintakso NEON:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Ustreza kodi PHP:
+V jeziku PHP bi to pomenilo:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-Vendar pa se lahko v nastavitvi kličejo tudi statične metode ali metode drugih storitev. Dejansko storitev jim posredujemo kot `@self`:
-
+V nastavitvi lahko kličete tudi statične metode ali metode drugih storitev. Če morate kot argument posredovati trenutno storitev, uporabite `@self`:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-Ustreza kodi PHP:
+Upoštevajte, da zaradi enostavnosti namesto `->` uporabimo `::`, glejte [izrazna sredstva |#expression means]. To ustvari naslednjo tovarniško metodo:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
+Sredstva za izražanje .[#toc-expression-means]
+==============================================
+
+Nette DI nam zagotavlja izjemno bogate izrazne možnosti, s katerimi lahko izrazimo skoraj vse. V konfiguracijskih datotekah lahko uporabljamo [parametre |configuration#parameters]:
+
+```neon
+# parameter
+%wwwDir%
+
+# vrednost pod ključem parametra
+%mailer.user%
+
+# parameter v nizu
+'%wwwDir%/images'
+```
+
+Prav tako lahko ustvarjamo predmete, kličemo metode in funkcije:
+
+```neon
+# ustvariti predmet
+DateTime()
+
+# klic statične metode
+Collator::create(%locale%)
+
+# klic funkcije PHP
+::getenv(DB_USER)
+```
+
+Na storitve se lahko sklicujemo po imenu ali vrsti:
+
+```neon
+# storitev po imenu
+@database
+
+# storitev po vrsti
+@Nette\Database\Connection
+```
+
+Uporabite sintakso prvega razreda za klicanje: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Uporabite konstante:
+
+```neon
+# razred stalnica
+FilesystemIterator::SKIP_DOTS
+
+# globalna konstanta, pridobljena s funkcijo PHP constant()
+::constant(PHP_VERSION)
+```
+
+Tako kot v PHP lahko klice metod verižite. Zaradi preprostosti namesto `->` uporabimo `::`:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Te izraze lahko pri [ustvarjanju storitev |#Service Creation] uporabite kjer koli, v [argumentih |#Arguments], v [nastavitvenem |#setup] delu ali [parametrih |configuration#parameters]:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Posebne funkcije .[#toc-special-functions]
+------------------------------------------
+
+V konfiguracijskih datotekah lahko uporabite te posebne funkcije:
+
+- `not()` za zanikanje vrednosti
+- `bool()`, `int()`, `float()`, `string()` za brezizgubno ulivanje tipov
+- `typed()` za ustvarjanje polja vseh storitev določenega tipa
+- `tagged()` za ustvarjanje polja vseh storitev z določeno oznako
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+V primerjavi z običajnim tipiziranjem v PHP, kot je `(int)`, bo brezizgubno tipiziranje vrglo izjemo za neštevilčne vrednosti.
+
+Funkcija `typed()` ustvari polje vseh storitev določene vrste (razreda ali vmesnika). Izključuje storitve z izklopljenim samodejnim vgrajevanjem. Določite lahko več vrst, ki jih ločite z vejicami.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+Kot argument lahko samodejno posredujete tudi polje storitev določene vrste z uporabo [samodejnega napeljevanja |autowiring#Collection of Services].
+
+Funkcija `tagged()` ustvari polje vseh storitev z določeno oznako. Navedete lahko več oznak, ki jih ločite z vejicami.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
 Avtomatska napeljava .[#toc-autowiring]
 =======================================
 
-Ključ za samodejno ožičenje lahko uporabite za izključitev storitve iz samodejnega ožičenja ali za vplivanje na njeno obnašanje. Za več informacij glejte [poglavje o samodejnem ožičenju |autowiring].
+Ključ `autowired` omogoča spreminjanje obnašanja samodejnega ožičenja za določeno storitev. Za več podrobnosti glejte [poglavje o samodejnem ožičenju |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false     # foo je odstranjen iz samodejne napeljave
+		autowired: false     # storitev foo je izključena iz samodejnega ožičenja
 ```
 
 
 Oznake .[#toc-tags]
 ===================
 
-Posameznim storitvam je mogoče dodati informacije o uporabniku v obliki oznak:
+Oznake se uporabljajo za dodajanje dodatnih informacij storitvam. Storitvi lahko dodelite eno ali več oznak:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Oznake imajo lahko tudi vrednost:
+Oznake lahko nosijo tudi vrednosti:
 
 ```neon
 services:
@@ -370,14 +363,14 @@ services:
 			logger: monolog.logger.event
 ```
 
-Polje storitev z določenimi oznakami lahko posredujete kot argument s funkcijo `tagged()`. Določite lahko tudi več oznak, ki so ločene z vejico.
+Če želite priklicati vse storitve z določenimi oznakami, lahko uporabite funkcijo `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Imena storitev je mogoče pridobiti iz vsebnika DI z uporabo metode `findByTag()`:
+V vsebniku DI lahko z metodo `findByTag()` pridobite imena vseh storitev z določeno oznako:
 
 ```php
 $names = $container->findByTag('logger');
@@ -386,10 +379,10 @@ $names = $container->findByTag('logger');
 ```
 
 
-Inject Mode .[#toc-inject-mode]
-===============================
+Način vbrizgavanja .[#toc-inject-mode]
+======================================
 
-Z zastavico `inject: true` se aktivira posredovanje odvisnosti prek javnih spremenljivk z opombo [inject |best-practices:inject-method-attribute#Inject Attributes] in metodami [inject*( |best-practices:inject-method-attribute#inject Methods] ).
+Uporaba oznake `inject: true` aktivira posredovanje odvisnosti prek javnih spremenljivk z opombo [inject |best-practices:inject-method-attribute#Inject Attributes] in metodami [inject*( |best-practices:inject-method-attribute#inject Methods] ).
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Privzeto je funkcija `inject` aktivirana samo za predstavnike.
 
 
-Spreminjanje storitev .[#toc-modification-of-services]
-======================================================
+Spremembe storitev .[#toc-service-modifications]
+================================================
 
-V vsebniku DI so številne storitve, ki jih je dodala vgrajena ali [vaša razširitev |#di-extensions]. Definicije teh storitev lahko spremenite v konfiguraciji. Na primer, za storitev `application.application`, ki je privzeto objekt `Nette\Application\Application`, lahko spremenimo razred:
+Vsebnik DI vsebuje številne storitve, ki so dodane z vgrajenimi ali [uporabniškimi razširitvami |#extensions]. Definicije teh storitev lahko spreminjate neposredno v konfiguraciji. Tako lahko na primer spremenite razred storitve `application.application`, ki je običajno `Nette\Application\Application`, v drug razred:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Oznaka `alteration` je informativna in pove, da samo spreminjamo obstoječo storitev.
+Oznaka `alteration` je informativna in pomeni, da zgolj spreminjamo obstoječo storitev.
 
-Dodamo lahko tudi nastavitev:
+Nastavitev lahko tudi dopolnimo:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Pri ponovnem pisanju storitve bomo morda želeli odstraniti prvotne argumente, elemente nastavitev ali oznake, za kar je namenjen naslov `reset`:
+Pri prepisovanju storitve boste morda želeli odstraniti prvotne argumente, nastavitvene elemente ali oznake, pri čemer vam pride prav `reset`:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Storitev, ki je bila dodana z razširitvijo, lahko tudi odstranimo iz vsebnika:
+Če želite odstraniti storitev, ki jo je dodala razširitev, lahko to storite na naslednji način:
 
 ```neon
 services:
diff --git a/dependency-injection/tr/autowiring.texy b/dependency-injection/tr/autowiring.texy
index 4677539383..59333e2592 100644
--- a/dependency-injection/tr/autowiring.texy
+++ b/dependency-injection/tr/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 DI kapsayıcısı daha sonra verilen türle eşleşen bir dizi hizmeti otomatik olarak geçirir. Otomatik kablolamanın kapalı olduğu hizmetleri atlar.
 
-Eğer phpDoc yorumunun biçimini kontrol edemiyorsanız, yapılandırmada doğrudan bir dizi hizmet iletebilirsiniz [`typed()` |services#Special Functions].
+Yorumdaki tür şu biçimde de olabilir `array<int, Class>` veya `list<Class>`. Eğer phpDoc yorumunun biçimini kontrol edemiyorsanız, yapılandırmada doğrudan bir dizi hizmet iletebilirsiniz [`typed()` |services#Special Functions].
 
 
 Skaler Argümanlar .[#toc-scalar-arguments]
diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy
index 322cb2075a..8861ae66a8 100644
--- a/dependency-injection/tr/configuration.texy
+++ b/dependency-injection/tr/configuration.texy
@@ -67,7 +67,7 @@ Belirli bir türdeki tüm hizmetleri toplu olarak nasıl düzenleyebilirim? Beli
 ```neon
 decorator:
 	# bu sınıfın veya arayüzün örneği olan tüm hizmetler için
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # bu yöntemi çağır
 			- $absoluteUrls = true # ve değişkeni ayarlayın
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-`$container->parameters` dizisini kullanmıyorsanız, parametre dışa aktarımını devre dışı bırakabilirsiniz. Ayrıca, yalnızca `$container->findByTag(...)` yöntemini kullanarak hizmet aldığınız etiketleri dışa aktarabilirsiniz.
+`$container->getParameters()` dizisini kullanmıyorsanız, parametre dışa aktarımını devre dışı bırakabilirsiniz. Ayrıca, yalnızca `$container->findByTag(...)` yöntemini kullanarak hizmet aldığınız etiketleri dışa aktarabilirsiniz.
 Yöntemi hiç çağırmazsanız, `false` ile etiket dışa aktarımını tamamen devre dışı bırakabilirsiniz.
 
 Kullandığınız sınıfları `$container->getByType()` yöntemine parametre olarak belirterek [otomatik kablolama |autowiring] için meta verileri önemli ölçüde azaltabilirsiniz.
@@ -191,20 +191,15 @@ Sınıfların hangi dizinlerde (ve alt dizinlerde) aranması gerektiğini belirt
 
 ```neon
 search:
-	# bölüm adlarını kendiniz seçersiniz
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Ancak genellikle, tüm sınıfları ve arayüzleri eklemek istemeyiz, bu yüzden onları filtreleyebiliriz:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# dosya adına göre filtreleme (string|string[])
 		files:
@@ -220,7 +215,7 @@ Ya da aşağıdaki sınıflardan en az birini miras alan veya uygulayan sınıfl
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ Ayrıca negatif kurallar da tanımlayabilirsiniz, yani sınıf adı maskeleri ve
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+dosyalar: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ Eklenen hizmetler için etiketler belirlenebilir:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/tr/extensions.texy b/dependency-injection/tr/extensions.texy
index a3036620d4..d58ba90564 100644
--- a/dependency-injection/tr/extensions.texy
+++ b/dependency-injection/tr/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $başlatma .[wiki-method]
 ========================
 
-Yapılandırıcı, [addBody() yöntemi |php-generator:#method-and-function-body] kullanılarak bir `$this->initialization` nesnesine yazılarak oluşturulan [konteyner oluşturulduktan |application:bootstrap#index.php] sonra başlatma kodunu çağırır.
+Yapılandırıcı, [addBody() yöntemi |php-generator:#method-and-function-bodies] kullanılarak bir `$this->initialization` nesnesine yazılarak oluşturulan [konteyner oluşturulduktan |application:bootstrap#index.php] sonra başlatma kodunu çağırır.
 
 Bir oturumun nasıl başlatılacağına veya başlatma kodunu kullanarak `run` etiketine sahip hizmetlerin nasıl başlatılacağına dair bir örnek göstereceğiz:
 
diff --git a/dependency-injection/tr/factory.texy b/dependency-injection/tr/factory.texy
index b9552dc9e2..60de28c2be 100644
--- a/dependency-injection/tr/factory.texy
+++ b/dependency-injection/tr/factory.texy
@@ -170,39 +170,45 @@ Multifactory/Accessor .[#toc-multifactory-accessor]
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Birden fazla oluşturulmuş fabrika ve erişimci geçirmek yerine, yalnızca bir karmaşık çoklu fabrika geçirebilirsiniz.
 
-Alternatif olarak, birden fazla yöntem yerine bir parametre ile `create()` ve `get()` adreslerini kullanabilirsiniz:
+Alternatif olarak, birden fazla yöntem yerine bir parametre ile `get()` adresini kullanabilirsiniz:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Bu durumda, `MultiFactory::createArticle()`, `MultiFactoryAlt::create('article')` ile aynı şeyi yapar. Ancak, alternatif sözdiziminin birkaç dezavantajı vardır. Hangi `$name` değerlerinin desteklendiği açık değildir ve birden fazla farklı `$name` değeri kullanıldığında dönüş türü arayüzde belirtilemez.
+Bu durumda, `MultiFactory::getArticle()`, `MultiFactoryAlt::get('article')` ile aynı şeyi yapar. Ancak, alternatif sözdiziminin birkaç dezavantajı vardır. Hangi `$name` değerlerinin desteklendiği açık değildir ve birden fazla farklı `$name` değeri kullanıldığında dönüş türü arayüzde belirtilemez.
 
 
 Liste ile Tanımlama .[#toc-definition-with-a-list]
 --------------------------------------------------
-Yapılandırmanızda bir multifactory tanımlamak için ne yapmalısınız? Multifactory tarafından döndürülecek üç servis ve multifactory'nin kendisini oluşturalım:
+Bu yol, yapılandırmada birden fazla fabrika tanımlamak için kullanılabilir: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Veya fabrika tanımında, bir referans kullanarak mevcut hizmetlere atıfta bulunabiliriz:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ Bir multifactory'nin nasıl tanımlanacağına dair bir başka seçenek de [etik
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.explorer
 	)
diff --git a/dependency-injection/tr/faq.texy b/dependency-injection/tr/faq.texy
index cb6cb89752..359c8192e3 100644
--- a/dependency-injection/tr/faq.texy
+++ b/dependency-injection/tr/faq.texy
@@ -61,7 +61,7 @@ Dependency Injection'a geçmenin kod kalitesine ve uygulamanın uzun vadeli sür
 
 Neden kalıtım yerine kompozisyon tercih edilir? .[#toc-why-composition-is-preferred-over-inheritance]
 -----------------------------------------------------------------------------------------------------
-Değişimin damlama etkisi konusunda endişelenmeye gerek kalmadan kodun yeniden kullanılabilirliği amacına hizmet ettiği için kalıtım yerine bileşimin kullanılması tercih edilir. Böylece, bazı kodların değiştirilmesinin diğer bazı bağımlı kodların değişmesine neden olması konusunda endişelenmemizi gerektirmeyen daha gevşek bir bağlantı sağlar. Tipik bir örnek, [kurucu cehennemi |passing-dependencies#Constructor hell] olarak tanımlanan durumdur.
+[Kalıtım |nette:introduction-to-object-oriented-programming#inheritance] yerine [bileşimin |nette:introduction-to-object-oriented-programming#composition] kullanılması tercih edilir çünkü değişikliklerin sonuçları hakkında endişelenmek zorunda kalmadan kodun yeniden kullanılmasına hizmet eder. Böylece, bazı kodların değiştirilmesinin diğer bağımlı kodların değiştirilmesine neden olacağından endişelenmemize gerek kalmayan daha gevşek bir bağlantı sağlar. Tipik bir örnek, [kurucu cehennemi |passing-dependencies#Constructor hell] olarak adlandırılan bir durumdur.
 
 
 Nette DI Container Nette dışında kullanılabilir mi? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/tr/global-state.texy b/dependency-injection/tr/global-state.texy
index 72c7d53aa1..1cbfcdb6c6 100644
--- a/dependency-injection/tr/global-state.texy
+++ b/dependency-injection/tr/global-state.texy
@@ -301,4 +301,4 @@ Kod tasarımını düşünürken, her `static $foo` adresinin bir sorunu temsil
 
 Bu süreç sırasında, birden fazla sorumluluğu olduğu için bir sınıfı bölmeniz gerektiğini fark edebilirsiniz. Bu konuda endişelenmeyin; tek sorumluluk ilkesi için çaba gösterin.
 
-*[Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] gibi makaleleri bu bölümün temelini oluşturan Miško Hevery'ye teşekkür ederim.*
+*[Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] gibi makaleleri bu bölümün temelini oluşturan Miško Hevery'ye teşekkür ederim.*
diff --git a/dependency-injection/tr/passing-dependencies.texy b/dependency-injection/tr/passing-dependencies.texy
index 6cb6795534..7846ea3410 100644
--- a/dependency-injection/tr/passing-dependencies.texy
+++ b/dependency-injection/tr/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Sorun, `BaseClass` sınıfının kurucusunu değiştirmek istediğimizde, örneğin yeni bir bağımlılık eklendiğinde ortaya çıkar. O zaman tüm alt sınıfların kurucularını da değiştirmemiz gerekir. Bu da böyle bir değişikliği cehenneme çevirir.
 
-Bu nasıl önlenebilir? Çözüm **kalıtım yerine bileşime öncelik vermektir**.
+Bu nasıl önlenebilir? Çözüm [**kalıtım yerine bileşime |faq#Why composition is preferred over inheritance] öncelik [vermektir** |faq#Why composition is preferred over inheritance].
 
-Öyleyse kodu farklı bir şekilde tasarlayalım. Soyut `Base*` sınıflarından kaçınacağız. `MyClass` , `BaseClass`'dan miras alarak bazı işlevler elde etmek yerine, bu işlevleri bir bağımlılık olarak aktaracaktır:
+Öyleyse kodu farklı bir şekilde tasarlayalım. [Soyut |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` sınıflarından kaçınacağız. `MyClass` , `BaseClass`'dan miras alarak bazı işlevler elde etmek yerine, bu işlevselliği bir bağımlılık olarak geçirecektir:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ Setter çağrısı, [kurulum bölümündeki |services#Setup] DI konteyner yapıl
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ Değişkenin ayarı, [kurulum bölümündeki |services#Setup] DI konteyner yapı
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/tr/services.texy b/dependency-injection/tr/services.texy
index a4b3fb86c4..d12eee4856 100644
--- a/dependency-injection/tr/services.texy
+++ b/dependency-injection/tr/services.texy
@@ -2,32 +2,32 @@ Hizmet Tanımları
 ****************
 
 .[perex]
-Yapılandırma, özel hizmetlerin tanımlarını yerleştirdiğimiz yerdir. Bu `services` bölümünde yapılır.
+Yapılandırma, DI konteynerine tek tek hizmetlerin nasıl bir araya getirileceği ve diğer bağımlılıklarla nasıl bağlanacağı konusunda talimat verdiğimiz yerdir. Nette bunu başarmak için çok açık ve zarif bir yol sunar.
 
-Örneğin, `PDO` sınıfının bir örneği olacak olan `database` adlı bir hizmeti bu şekilde oluşturuyoruz:
+NEON yapılandırma dosyasındaki `services` bölümü, özel hizmetlerimizi ve yapılandırmalarını tanımladığımız yerdir. `PDO` sınıfının bir örneğini temsil eden `database` adlı bir hizmetin tanımlanmasına ilişkin basit bir örneğe bakalım:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Hizmetlerin isimlendirilmesi, onlara [referans |#Referencing Services] vermemizi sağlamak için kullanılır. Bir hizmete referans verilmiyorsa, onu adlandırmaya gerek yoktur. Bu yüzden isim yerine sadece bir madde işareti kullanırız:
+Bu yapılandırma [DI konteynerinde |container] aşağıdaki fabrika yöntemiyle sonuçlanır:
 
-```neon
-services:
-	- PDO('sqlite::memory:')  #  anonymous service
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Tek satırlık bir giriş, [kurulum |#setup] gibi ek anahtarların eklenmesine izin vermek için birden fazla satıra bölünebilir. `create:` tuşu için takma ad `factory:` şeklindedir.
+Hizmet adları, `@serviceName` biçimini kullanarak yapılandırma dosyasının diğer bölümlerinde bunlara başvurmamızı sağlar. Hizmeti adlandırmaya gerek yoksa, sadece bir madde işareti kullanabiliriz:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Daha sonra `getService()` yöntemini isme göre ya da daha iyisi `getByType()` yöntemini türe göre kullanarak hizmeti DI konteynerinden alırız:
+DI konteynerinden bir hizmeti almak için, parametre olarak hizmet adıyla birlikte `getService()` yöntemini veya hizmet türüyle birlikte `getByType()` yöntemini kullanabiliriz:
 
 ```php
 $database = $container->getService('database');
@@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Hizmet Oluşturma .[#toc-creating-a-service]
-===========================================
+Hizmet Oluşturma .[#toc-service-creation]
+=========================================
 
-Çoğu zaman, sadece bir sınıfın örneğini oluşturarak bir hizmet yaratırız:
+En yaygın olarak, sadece belirli bir sınıfı örnekleyerek bir hizmet oluştururuz. Örneğin:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Bu da [DI konteynerinde |container] bir fabrika yöntemi oluşturacaktır:
-
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
-```
-
-Alternatif olarak, [argümanları |#Arguments] iletmek için bir anahtar `arguments` kullanılabilir:
+Yapılandırmayı ek anahtarlarla genişletmemiz gerekirse, tanım birden fazla satıra genişletilebilir:
 
 ```neon
 services:
 	database:
-		create: PDO
-		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
-```
-
-Statik bir yöntem de bir hizmet oluşturabilir:
-
-```neon
-services:
-	database: My\Database::create(root, secret)
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-PHP koduna karşılık gelir:
+ `create` anahtarının bir takma adı vardır `factory`, her iki sürüm de pratikte yaygındır. Ancak biz `create` adresini kullanmanızı öneririz.
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return My\Database::create('root', 'secret');
-}
-```
-
-Statik bir yöntemin `My\Database::create()` DI konteynerinin bilmesi gereken tanımlı bir dönüş değerine sahip olduğu varsayılır. Eğer yoksa, türü yapılandırmaya yazarız:
+Kurucu argümanları veya oluşturma yöntemi alternatif olarak `arguments` anahtarına yazılabilir:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
-		type: PDO
+		create: PDO
+		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Nette DI size neredeyse her şeyi yazmanız için son derece güçlü ifade olanakları sunar. Örneğin, başka bir servise [başvurmak |#Referencing Services] ve onun metodunu çağırmak için. Basitlik için `->` yerine `::` kullanılır.
+Hizmetler sadece bir sınıfın basit bir şekilde örneklenmesiyle oluşturulmak zorunda değildir; statik yöntemlerin veya diğer hizmetlerin yöntemlerinin çağrılmasıyla da ortaya çıkabilirler:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
+	database: DatabaseFactory::create()
 	router: @routerFactory::create()
 ```
 
-PHP koduna karşılık gelir:
+Basitlik için `->` yerine `::` kullandığımızı unutmayın, [ifade araçlarına |#expression means] bakın. Bu fabrika yöntemleri oluşturulur:
 
 ```php
-public function createServiceRouterFactory(): App\Router\Factory
+public function createServiceDatabase(): PDO
 {
-	return new App\Router\Factory;
+	return DatabaseFactory::create();
 }
 
-public function createServiceRouter(): Router
+public function createServiceRouter(): RouteList
 {
 	return $this->getService('routerFactory')->create();
 }
 ```
 
-PHP'de olduğu gibi yöntem çağrıları zincirleme olarak birbirine eklenebilir:
+DI konteynerinin oluşturulan hizmetin türünü bilmesi gerekir. Belirtilen bir dönüş türüne sahip olmayan bir yöntem kullanarak bir hizmet oluşturursak, yapılandırmada bu türden açıkça bahsetmeliyiz:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
-```
-
-PHP koduna karşılık gelir:
-
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+	database:
+		create: DatabaseFactory::create()
+		type: PDO
 ```
 
 
 Argümanlar .[#toc-arguments]
 ============================
 
-Adlandırılmış parametreler argümanları iletmek için de kullanılabilir:
+Normal PHP'ye çok benzer bir şekilde kuruculara ve yöntemlere argümanlar aktarırız:
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test'  # konumsal
-		username: root                      # named
-		password: secret                    # named
-	)
-```
-
-Argümanları birden fazla satıra bölerken virgül kullanımı isteğe bağlıdır.
-
-Elbette, [diğer hizmetleri |#Referencing Services] veya [parametreleri |configuration#parameters] de argüman olarak kullanabiliriz:
-
-```neon
-services:
-	- Foo(@anotherService, %appDir%)
-```
-
-PHP koduna karşılık gelir:
-
-```php
-public function createService01(): Foo
-{
-	return new Foo($this->getService('anotherService'), '...');
-}
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-İlk bağımsız değişken [otomatik olarak bağlanmışsa |autowiring] ve ikincisini belirtmek istiyorsanız, ilkini `_` character, for example `Foo(_, %appDir%)` ile atlayın. Ya da daha iyisi, yalnızca ikinci bağımsız değişkeni [adlandırılmış |autowiring] bir parametre olarak iletin, örneğin `Foo(path: %appDir%)`.
-
-Nette DI ve NEON formatı size neredeyse her şeyi yazmanız için son derece güçlü ifade olanakları sağlar. Böylece bir argüman yeni oluşturulmuş bir nesne olabilir, statik metotları, diğer servislerin metotlarını ve hatta özel gösterim kullanarak global fonksiyonları çağırabilirsiniz:
+Daha iyi okunabilirlik için, argümanları ayrı satırlarda listeleyebiliriz. Bu formatta virgül kullanımı isteğe bağlıdır:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)          # nesne oluştur
-		DateTime::createFromFormat('Y-m-d')   # statik yöntemi çağırın
-		@anotherService                       # başka bir hizmet geçirme
-		@http.request::getRemoteAddress()     # başka bir hizmet yöntemini çağırma
-		::getenv(NetteMode)                   # global bir fonksiyon çağırın
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
 	)
 ```
 
-PHP koduna karşılık gelir:
-
-```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('NetteMode')
-	);
-}
-```
-
-
-Özel Fonksiyonlar .[#toc-special-functions]
--------------------------------------------
-
-Değerleri atamak veya olumsuzlamak için argümanlarda özel fonksiyonlar da kullanabilirsiniz:
-
-- `not(%arg%)` olumsuzlama
-- `bool(%arg%)` bool'a kayıpsız döküm
-- `int(%arg%)` int'e kayıpsız döküm
-- `float(%arg%)` float'a kayıpsız döküm
-- `string(%arg%)` dizeye kayıpsız döküm
+Argümanlara isim de verebilirsiniz, böylece sıraları konusunda endişelenmenize gerek kalmaz:
 
 ```neon
 services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
 	)
 ```
 
-Kayıpsız yeniden yazım, normal PHP yeniden yazımından farklıdır, örneğin `(int)`, sayısal olmayan değerler için bir istisna atar.
-
-Birden fazla hizmet argüman olarak aktarılabilir. Belirli bir türdeki (yani, sınıf veya arayüz) tüm hizmetlerin bir dizisi `typed()` işlevi tarafından oluşturulur. İşlev, otomatik kablolamanın devre dışı bırakıldığı hizmetleri atlar ve virgülle ayrılmış birden fazla tür belirtilebilir.
+Belirli bağımsız değişkenleri atlamak ve varsayılan değerlerini kullanmak veya [otomatik |autowiring] bağlantı yoluyla bir hizmet eklemek istiyorsanız, bir alt çizgi kullanın:
 
 ```neon
 services:
-	- BarsDependent( typed(Bar) )
+	foo: Foo(_, %appDir%)
 ```
 
-[Otomatik kablolamayı |autowiring#Collection of Services] kullanarak bir dizi hizmeti otomatik olarak da geçirebilirsiniz.
-
-Belirli bir [etikete |#tags] sahip tüm hizmetlerin bir dizisi `tagged()` işlevi tarafından oluşturulur. Virgülle ayrılmış birden fazla etiket belirtilebilir.
-
-```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
-
-
-Referanslama Hizmetleri .[#toc-referencing-services]
-====================================================
-
-Bireysel hizmetlere `@` and name, so for example `@database` karakteri kullanılarak atıfta bulunulur:
-
-```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
-
-PHP koduna karşılık gelir:
-
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
-```
-
-Anonim hizmetlere bile bir geri arama kullanılarak başvurulabilir, sadece adları yerine türlerini (sınıf veya arayüz) belirtin. Ancak, [otomatik |autowiring] bağlantı nedeniyle bu genellikle gerekli değildir.
-
-```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # or @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
-```
+Bağımsız değişkenler hizmetler, parametreler ve çok daha fazlası olabilir, [ifade araçlarına |#expression means] bakın.
 
 
 Kurulum .[#toc-setup]
 =====================
 
-Kurulum bölümünde, hizmet oluşturulurken çağrılacak yöntemleri listeliyoruz:
+ `setup` bölümünde, hizmet oluşturulurken çağrılması gereken yöntemleri tanımlıyoruz.
 
 ```neon
 services:
@@ -274,7 +152,7 @@ services:
 			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-PHP koduna karşılık gelir:
+PHP'de bu şöyle görünecektir:
 
 ```php
 public function createServiceDatabase(): PDO
@@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO
 }
 ```
 
-Özellikler de ayarlanabilir. Bir diziye eleman eklemek de desteklenir ve NEON sözdizimiyle çakışmaması için tırnak içinde yazılmalıdır:
-
+Yöntem çağrılarına ek olarak, özelliklere değer de aktarabilirsiniz. Bir diziye eleman eklemek de desteklenir, ancak NEON sözdizimiyle çakışmasını önlemek için bunu tırnak içine almanız gerekir:
 
 ```neon
 services:
@@ -297,7 +174,7 @@ services:
 			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-PHP koduna karşılık gelir:
+PHP'de bu şu anlama gelir:
 
 ```php
 public function createServiceFoo(): Foo
@@ -309,8 +186,7 @@ public function createServiceFoo(): Foo
 }
 ```
 
-Ancak, statik yöntemler veya diğer hizmetlerin yöntemleri de kurulumda çağrılabilir. Onlara asıl servisi `@self` olarak iletiyoruz:
-
+Kurulumda, statik yöntemleri veya diğer hizmetlerin yöntemlerini de çağırabilirsiniz. Geçerli hizmeti argüman olarak geçirmeniz gerekiyorsa, `@self` adresini kullanın:
 
 ```neon
 services:
@@ -321,7 +197,7 @@ services:
 			- @anotherService::setFoo(@self)
 ```
 
-PHP koduna karşılık gelir:
+Basitlik için `->` yerine `::` kullandığımızı unutmayın, [ifade araçlarına |#expression means] bakın. Bu, aşağıdaki fabrika yöntemini oluşturur:
 
 ```php
 public function createServiceFoo(): Foo
@@ -334,23 +210,140 @@ public function createServiceFoo(): Foo
 ```
 
 
+İfade Araçları .[#toc-expression-means]
+=======================================
+
+Nette DI bize son derece zengin ifade yetenekleri sunarak neredeyse her şeyi ifade etmemize olanak tanır. Yapılandırma dosyalarında [parametreler |configuration#parameters] kullanabiliriz:
+
+```neon
+# parametresi
+%wwwDir%
+
+# bir parametre anahtarı altındaki değer
+%mailer.user%
+
+# bir dize içindeki parametre
+'%wwwDir%/images'
+```
+
+Ayrıca nesneler oluşturabilir, yöntemler ve fonksiyonlar çağırabiliriz:
+
+```neon
+# bir nesne oluşturun
+DateTime()
+
+# statik bir yöntem çağırma
+Collator::create(%locale%)
+
+# bir PHP işlevini çağırır
+::getenv(DB_USER)
+```
+
+Hizmetlere ya adlarıyla ya da türlerine göre atıfta bulunun:
+
+```neon
+# isme göre hizmet
+@database
+
+# türe göre hi̇zmet
+@Nette\Database\Connection
+```
+
+Birinci sınıf çağrılabilir sözdizimi kullanın: .{data-version:3.2.0}
+
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
+```
+
+Sabitleri kullanın:
+
+```neon
+# sınıf sabiti
+FilesystemIterator::SKIP_DOTS
+
+# constant() PHP işlevi tarafından elde edilen küresel sabit
+::constant(PHP_VERSION)
+```
+
+Metot çağrıları PHP'de olduğu gibi zincirleme yapılabilir. Basitlik için `->` yerine `::` kullanacağız:
+
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
+
+Bu ifadeler [hizmetler oluşturulurken |#Service Creation] herhangi bir yerde, [argümanlarda |#Arguments], [kurulum |#setup] bölümünde veya [parametrelerde |configuration#parameters] kullanılabilir:
+
+```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
+services:
+	database:
+		create: DatabaseFactory::create( @anotherService::getDsn() )
+		setup:
+			- initialize( ::getenv('DB_USER') )
+```
+
+
+Özel Fonksiyonlar .[#toc-special-functions]
+-------------------------------------------
+
+Yapılandırma dosyaları içinde bu özel işlevleri kullanabilirsiniz:
+
+- Değer olumsuzlama için `not()`
+- Kayıpsız tip dökümü için `bool()`, `int()`, `float()`, `string()`
+- `typed()` belirtilen türdeki tüm hizmetlerin bir dizisini oluşturmak için
+- `tagged()` belirli bir etikete sahip tüm hizmetlerin bir dizisini oluşturmak için
+
+```neon
+services:
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
+```
+
+PHP'deki `(int)` gibi geleneksel tip atamayla karşılaştırıldığında, kayıpsız tip atama sayısal olmayan değerler için bir istisna oluşturur.
+
+ `typed()` işlevi, belirli bir türdeki (sınıf veya arayüz) tüm hizmetlerin bir dizisini oluşturur. Otomatik kablolaması kapalı olan hizmetleri hariç tutar. Virgülle ayrılarak birden fazla tür belirtilebilir.
+
+```neon
+services:
+	- BarsDependent( typed(Bar) )
+```
+
+ [Otomatik kab |autowiring#Collection of Services]lolamayı kullanarak belirli bir türdeki bir dizi hizmeti otomatik olarak argüman olarak da iletebilirsiniz.
+
+ `tagged()` işlevi, belirtilen etikete sahip tüm hizmetlerin bir dizisini oluşturur. Birden fazla etiket virgülle ayrılarak listelenebilir.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
+```
+
+
 Otomatik Kablolama .[#toc-autowiring]
 =====================================
 
-Otomatik bağlama anahtarı, bir hizmeti otomatik bağlamanın dışında tutmak veya davranışını etkilemek için kullanılabilir. Daha fazla bilgi için otomatik kablolama [bölümüne |autowiring] bakın.
+ `autowired` tuşu, belirli bir hizmet için otomatik kablolama davranışını değiştirmenize olanak tanır. Daha fazla ayrıntı için otomatik kablolama [bölümüne |autowiring] bakın.
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # foo otomatik bağlantıdan kaldırılır
+		autowired: false     # foo hizmeti otomatik kablolamanın dışında tutulur
 ```
 
 
 Etiketler .[#toc-tags]
 ======================
 
-Kullanıcı bilgileri tek tek hizmetlere etiket şeklinde eklenebilir:
+Etiketler hizmetlere ek bilgi eklemek için kullanılır. Bir hizmete bir veya daha fazla etiket atayabilirsiniz:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Etiketler bir değere de sahip olabilir:
+Etiketler değer de taşıyabilir:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Belirli etiketlere sahip bir dizi hizmet, `tagged()` işlevi kullanılarak argüman olarak aktarılabilir. Virgülle ayrılmış birden fazla etiket de belirtilebilir.
+Belirli etiketlere sahip tüm hizmetleri almak için `tagged()` işlevini kullanabilirsiniz:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Hizmet adları `findByTag()` yöntemi kullanılarak DI konteynerinden elde edilebilir:
+DI konteynerinde, `findByTag()` yöntemini kullanarak belirli bir etikete sahip tüm hizmetlerin adlarını elde edebilirsiniz:
 
 ```php
 $names = $container->findByTag('logger');
 // $names, hizmet adını ve etiket değerini içeren bir dizidir
-// i.e. ['foo' => 'monolog.logger.event', ...]
+// örneğin ['foo' => 'monolog.logger.event', ...]
 ```
 
 
 Enjeksiyon Modu .[#toc-inject-mode]
 ===================================
 
-`inject: true` bayrağı, bağımlılıkların [inject |best-practices:inject-method-attribute#Inject Attributes] ek açıklaması ve [inject*() |best-practices:inject-method-attribute#inject Methods] yöntemleri ile genel değişkenler aracılığıyla aktarılmasını etkinleştirmek için kullanılır.
+ `inject: true` bayrağının kullanılması, bağımlılıkların [inject |best-practices:inject-method-attribute#Inject Attributes] ek açıklaması ve [inject*() |best-practices:inject-method-attribute#inject Methods] yöntemleri ile genel değişkenler aracılığıyla aktarılmasını etkinleştirir.
 
 ```neon
 services:
@@ -401,10 +394,10 @@ services:
 Varsayılan olarak, `inject` yalnızca sunum yapanlar için etkinleştirilir.
 
 
-Hizmetlerin Değiştirilmesi .[#toc-modification-of-services]
-===========================================================
+Hizmet Değişiklikleri .[#toc-service-modifications]
+===================================================
 
-DI konteynerinde yerleşik veya [uzantınız |#di-extensions] tarafından eklenen bir dizi hizmet vardır. Bu hizmetlerin tanımları yapılandırmada değiştirilebilir. Örneğin, varsayılan olarak bir nesne olan `application.application` hizmeti için `Nette\Application\Application` sınıfını değiştirebiliriz:
+DI konteyneri, yerleşik veya [kullanıcı uzantıları |#extensions] tarafından eklenen birçok hizmet içerir. Bu hizmetlerin tanımlarını doğrudan yapılandırma içinde değiştirebilirsiniz. Örneğin, geleneksel olarak `Nette\Application\Application` olan `application.application` hizmetinin sınıfını başka bir şeyle değiştirebilirsiniz:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-`alteration` bayrağı bilgilendiricidir ve sadece mevcut bir hizmeti değiştirdiğimizi söyler.
+ `alteration` bayrağı bilgilendiricidir ve yalnızca mevcut bir hizmeti değiştirdiğimizi gösterir.
 
-Ayrıca bir kurulum da ekleyebiliriz:
+Kurulumu da tamamlayabiliriz:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Bir hizmeti yeniden yazarken, orijinal argümanları, kurulum öğelerini veya etiketleri kaldırmak isteyebiliriz, `reset` bunun içindir:
+Bir hizmetin üzerine yazarken, orijinal argümanları, kurulum öğelerini veya etiketleri kaldırmak isteyebilirsiniz, işte bu noktada `reset` kullanışlı hale gelir:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Uzantı ile eklenen bir hizmet konteynerden de kaldırılabilir:
+Bir uzantı tarafından eklenen bir hizmeti kaldırmak isterseniz, bunu şu şekilde yapabilirsiniz:
 
 ```neon
 services:
diff --git a/dependency-injection/uk/autowiring.texy b/dependency-injection/uk/autowiring.texy
index 908a454513..356325153f 100644
--- a/dependency-injection/uk/autowiring.texy
+++ b/dependency-injection/uk/autowiring.texy
@@ -105,7 +105,7 @@ class ShipManager
 
 Потім контейнер DI автоматично передає масив сервісів, що відповідають заданому типу. При цьому будуть пропущені сервіси, у яких відключено автозв'язування.
 
-Якщо ви не можете контролювати форму коментаря phpDoc, ви можете передати масив сервісів безпосередньо в конфігурації, використовуючи [`typed()` |services#Special-Functions].
+Тип у коментарі також може мати вигляд `array<int, Class>` або `list<Class>`. Якщо ви не можете контролювати форму коментаря phpDoc, ви можете передати масив сервісів безпосередньо в конфігурації за допомогою [`typed()` |services#Special Functions].
 
 
 Скалярні аргументи .[#toc-scalar-arguments]
diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy
index da99a35c9d..e29d6c661a 100644
--- a/dependency-injection/uk/configuration.texy
+++ b/dependency-injection/uk/configuration.texy
@@ -67,7 +67,7 @@ parameters:
 ```neon
 decorator:
 	# Для всіх сервісів, які є екземплярами цього класу або інтерфейсу
-	App\Presenters\BasePresenter:
+	App\UI\BasePresenter:
 		setup:
 			- setProjectId(10)     # викликаємо цей метод
 			- $absoluteUrls = true # і задаємо змінну
@@ -122,7 +122,7 @@ di:
 			- Symfony\Component\Console\Application
 ```
 
-Якщо ви не використовуєте масив `$container->parameters`, можна вимкнути експорт параметрів. Крім того, ви можете експортувати тільки ті теги, через які ви отримуєте сервіси, використовуючи метод `$container->findByTag(...)`.
+Якщо ви не використовуєте масив `$container->getParameters()`, можна вимкнути експорт параметрів. Крім того, ви можете експортувати тільки ті теги, через які ви отримуєте сервіси, використовуючи метод `$container->findByTag(...)`.
 Якщо ви не викликаєте цей метод зовсім, можна повністю відключити експорт тегів, вказавши значення `false`.
 
 Ви можете значно зменшити метадані для автоматичного підключення, вказавши класи, які ви використовуєте як параметр у методі `$container->getByType()`.
@@ -191,20 +191,15 @@ return [
 
 ```neon
 search:
-	# ви самі вибираєте назви секцій
-	myForms:
-		in: %appDir%/Forms
-
-	model:
-		in: %appDir%/Model
+	-	in: %appDir%/Forms
+	-	in: %appDir%/Model
 ```
 
 Зазвичай, однак, ми не хочемо додавати всі класи та інтерфейси, тому ми можемо відфільтрувати їх:
 
 ```neon
 search:
-	myForms:
-		in: %appDir%/Forms
+	-	in: %appDir%/Forms
 
 		# фільтрація за ім'ям файлу (string|string[])
 		files:
@@ -220,7 +215,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		extends:
 			- App\*Form
 		implements:
@@ -231,8 +226,9 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		exclude:
+файли: ...
 			classes: ...
 			extends: ...
 			implements: ...
@@ -242,7 +238,7 @@ search:
 
 ```neon
 search:
-	myForms:
+	-	in: %appDir%
 		tags: ...
 ```
 
diff --git a/dependency-injection/uk/extensions.texy b/dependency-injection/uk/extensions.texy
index eba51856f6..b865d00aa4 100644
--- a/dependency-injection/uk/extensions.texy
+++ b/dependency-injection/uk/extensions.texy
@@ -170,7 +170,7 @@ class BlogExtension extends Nette\DI\CompilerExtension
 $initialization .[wiki-method]
 ==============================
 
-Configurator викликається кодом ініціалізації після [створення контейнера |application:bootstrap#index-php], який створюється шляхом запису в об'єкт `$this->initialization` за допомогою [методу addBody() |php-generator:#method-and-function-body].
+Configurator викликається кодом ініціалізації після [створення контейнера |application:bootstrap#index-php], який створюється шляхом запису в об'єкт `$this->initialization` за допомогою [методу addBody() |php-generator:#method-and-function-bodies].
 
 Ми покажемо приклад того, як запустити сесію або сервіси, які мають тег `run` за допомогою коду ініціалізації:
 
diff --git a/dependency-injection/uk/factory.texy b/dependency-injection/uk/factory.texy
index e4f50df1e7..a5c0dc0806 100644
--- a/dependency-injection/uk/factory.texy
+++ b/dependency-injection/uk/factory.texy
@@ -170,39 +170,45 @@ services:
 interface MultiFactory
 {
 	function createArticle(): Article;
-	function createFoo(): Model\Foo;
 	function getDb(): PDO;
 }
 ```
 
 Тому замість того, щоб передавати кілька згенерованих фабрик і аксесорів, ми збираємося передати ще одну складну фабрику, яка може робити більше.
 
-Як варіант, замість кількох методів можна використовувати параметри `create()` і `get()`:
+Крім того, ви можете використовувати `get()` з параметром замість декількох методів:
 
 ```php
 interface MultiFactoryAlt
 {
-	function create($name);
 	function get($name): PDO;
 }
 ```
 
-Потім `MultiFactory::createArticle()` робить те саме, що і `MultiFactoryAlt::create('article')`. Однак альтернативна нотація має той недолік, що незрозуміло, які значення `$name` підтримуються, і логічно неможливо розрізнити різні значення, що повертаються, для різних `$name` в інтерфейсі.
+У цьому випадку `MultiFactory::getArticle()` робить те ж саме, що і `MultiFactoryAlt::get('article')`. Однак альтернативний синтаксис має кілька недоліків. Незрозуміло, які значення `$name` підтримуються, і неможливо вказати тип повернення в інтерфейсі при використанні декількох різних значень `$name`.
 
 
 Визначення списку .[#toc-definition-with-a-list]
 ------------------------------------------------
-А як визначити множинну фабрику в конфігурації? Ми створимо три сервіси, які будуть створювати/повертати, а потім і саму фабрику:
+Цей спосіб можна використовувати для визначення декількох фабрик у конфігурації: .{data-version:3.2.0}
+
+```neon
+services:
+	- MultiFactory(
+		article: Article                      # defines createArticle()
+		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
+	)
+```
+
+Або у визначенні фабрики ми можемо посилатися на існуючі сервіси за допомогою посилання:
 
 ```neon
 services:
 	article: Article
-	- Model\Foo
 	- PDO(%dsn%, %user%, %password%)
 	- MultiFactory(
-		article: @article  # createArticle()
-		foo: @Model\Foo    # createFoo()
-		db: @\PDO          # getDb()
+		article: @article    # defines createArticle()
+		db: @\PDO            # defines getDb()
 	)
 ```
 
@@ -214,7 +220,7 @@ services:
 
 ```neon
 services:
-	- App\Router\RouterFactory::createRouter
+	- App\Core\RouterFactory::createRouter
 	- App\Model\DatabaseAccessor(
 		db1: @database.db1.context
 	)
diff --git a/dependency-injection/uk/faq.texy b/dependency-injection/uk/faq.texy
index c04c4b1a9e..130d1a6617 100644
--- a/dependency-injection/uk/faq.texy
+++ b/dependency-injection/uk/faq.texy
@@ -61,7 +61,7 @@ DI не впливає на продуктивність програми або
 
 Чому композиція краща за успадкування? .[#toc-why-composition-is-preferred-over-inheritance]
 --------------------------------------------------------------------------------------------
-Краще використовувати композицію, ніж успадкування, оскільки вона слугує для повторного використання коду без необхідності турбуватися про ефект "просочування" змін. Таким чином, це забезпечує більш вільний зв'язок, коли нам не потрібно турбуватися про те, що зміна одного коду спричинить зміну іншого залежного коду, який також потребує змін. Типовим прикладом є ситуація, яку називають [пеклом конструктора |passing-dependencies#Constructor hell].
+Краще використовувати [композицію |nette:introduction-to-object-oriented-programming#composition] замість [успадкування |nette:introduction-to-object-oriented-programming#inheritance], оскільки вона дозволяє повторно використовувати код, не турбуючись про наслідки змін. Таким чином, це забезпечує більш слабкий зв'язок, коли нам не потрібно турбуватися про те, що зміна одного коду призведе до необхідності зміни іншого залежного коду. Типовим прикладом є ситуація, яку називають пеклом [конструктора |passing-dependencies#Constructor hell].
 
 
 Чи можна використовувати Nette DI Container за межами Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette]
diff --git a/dependency-injection/uk/global-state.texy b/dependency-injection/uk/global-state.texy
index 489daa66b6..092a16313b 100644
--- a/dependency-injection/uk/global-state.texy
+++ b/dependency-injection/uk/global-state.texy
@@ -301,4 +301,4 @@ class Foo
 
 Під час цього процесу ви можете виявити, що вам потрібно розділити клас, оскільки він має більше однієї відповідальності. Не турбуйтеся про це; прагніть до принципу єдиної відповідальності.
 
-*Я хотів би подякувати Мішко Хевері, чиї статті, такі як [Flaw: Brittle Global State та Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], лягли в основу цієї глави. Я хотів би подякувати Мішко Хевері.*
+*Я хотів би подякувати Мішко Хевері, чиї статті, такі як [Flaw: Brittle Global State та Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], лягли в основу цієї глави. Я хотів би подякувати Мішко Хевері.*
diff --git a/dependency-injection/uk/passing-dependencies.texy b/dependency-injection/uk/passing-dependencies.texy
index 5badf00eb0..6797c329ae 100644
--- a/dependency-injection/uk/passing-dependencies.texy
+++ b/dependency-injection/uk/passing-dependencies.texy
@@ -96,9 +96,9 @@ final class MyClass extends BaseClass
 
 Проблема виникає, коли ми хочемо змінити конструктор класу `BaseClass`, наприклад, коли додається нова залежність. Тоді нам доведеться модифікувати всі конструктори дочірніх класів. Що перетворює таку модифікацію на справжнє пекло.
 
-Як цього уникнути? Рішення полягає в тому, щоб **приоритизувати композицію над успадкуванням**.
+Як цьому запобігти? Рішення полягає в тому, щоб **надати пріоритет [композиції над успадкуванням** |faq#Why composition is preferred over inheritance].
 
-Отже, давайте проектувати код по-іншому. Уникаймо абстрактних класів `Base*`. Замість того, щоб `MyClass` отримував певну функціональність шляхом успадкування від `BaseClass`, він отримає цю функціональність як залежність:
+Тож давайте спроектуємо код по-іншому. Ми будемо уникати [абстрактних |nette:introduction-to-object-oriented-programming#abstract-classes] класів `Base*`. Замість того, щоб `MyClass` отримував певну функціональність шляхом успадкування від `BaseClass`, він отримає цю функціональність як залежність:
 
 ```php
 final class SomeFunctionality
@@ -168,8 +168,7 @@ class MyClass
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- setCache
 ```
@@ -196,8 +195,7 @@ $obj->cache = $cache;
 
 ```neon
 services:
-	-
-		create: MyClass
+	-	create: MyClass
 		setup:
 			- $cache = @\Cache
 ```
diff --git a/dependency-injection/uk/services.texy b/dependency-injection/uk/services.texy
index 10bb015505..496bed2785 100644
--- a/dependency-injection/uk/services.texy
+++ b/dependency-injection/uk/services.texy
@@ -2,32 +2,32 @@
 *******************
 
 .[perex]
-Конфігурація - це місце, де ми розміщуємо визначення користувацьких сервісів. Робиться це в секції `services`.
+Конфігурація - це місце, де ми вказуємо DI контейнеру, як зібрати окремі сервіси і як з'єднати їх з іншими залежностями. Nette надає дуже чіткий та елегантний спосіб досягти цього.
 
-Наприклад, ось як ми створюємо сервіс з іменем `database`, який буде екземпляром класу `PDO`:
+Секція `services` у файлі конфігурації NEON - це місце, де ми визначаємо наші кастомні сервіси та їхні конфігурації. Давайте розглянемо простий приклад визначення сервісу з ім'ям `database`, який представляє екземпляр класу `PDO`:
 
 ```neon
 services:
 	database: PDO('sqlite::memory:')
 ```
 
-Іменування служб використовується для того, щоб ми могли [посилатися |#Referencing-Services] на них. Якщо на сервіс не посилаються, немає необхідності давати йому ім'я. Тому замість імені ми просто використовуємо двокрапку:
+Ця конфігурація призводить до наступного заводського методу в контейнері [DI |container]:
 
-```neon
-services:
-	- PDO('sqlite::memory:') # анонімний сервіс
+```php
+public function createServiceDatabase(): PDO
+{
+	return new PDO('sqlite::memory:');
+}
 ```
 
-Однорядковий запис може бути розбитий на кілька рядків, щоб можна було додати додаткові ключі, наприклад [setup |#setup]. Псевдонім для ключа `create:` - `factory:`.
+Назви сервісів дозволяють нам посилатися на них в інших частинах конфігураційного файлу, використовуючи формат `@serviceName`. Якщо немає необхідності називати службу, ми можемо просто використовувати маркер:
 
 ```neon
 services:
-	database:
-		create: PDO('sqlite::memory:')
-		setup: ...
+	- PDO('sqlite::memory:')
 ```
 
-Потім ми отримуємо сервіс із контейнера DI, використовуючи метод `getService()` за ім'ям, або, що ще краще, метод `getByType()` за типом:
+Щоб отримати сервіс з контейнера DI, ми можемо використовувати метод `getService()` з назвою сервісу як параметром або метод `getByType()` з типом сервісу:
 
 ```php
 $database = $container->getService('database');
@@ -35,26 +35,28 @@ $database = $container->getByType(PDO::class);
 ```
 
 
-Створення сервісу .[#toc-creating-a-service]
-============================================
+Створення сервісу .[#toc-service-creation]
+==========================================
 
-Найчастіше ми створюємо сервіс, просто створюючи екземпляр класу:
+Найчастіше ми створюємо сервіс, просто створюючи екземпляр певного класу. Наприклад:
 
 ```neon
 services:
 	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Що створить фабричний метод у [DI-контейнері |container]:
+Якщо нам потрібно розширити конфігурацію за допомогою додаткових ключів, визначення можна розгорнути на кілька рядків:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
-}
+```neon
+services:
+	database:
+		create: PDO('sqlite::memory:')
+		setup: ...
 ```
 
-Альтернативно, ключ `arguments` може бути використаний для передачі [аргументів |#Arguments]:
+Ключ `create` має псевдонім `factory`, обидві версії поширені на практиці. Однак ми рекомендуємо використовувати `create`.
+
+Аргументи конструктора або метод створення можна також записати в ключі `arguments`:
 
 ```neon
 services:
@@ -63,294 +65,285 @@ services:
 		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
 ```
 
-Статичний метод також може створити сервіс:
+Сервіси не обов'язково створювати простим екземпляром класу; вони також можуть бути результатом виклику статичних методів або методів інших сервісів:
 
 ```neon
 services:
-	database: My\Database::create(root, secret)
+	database: DatabaseFactory::create()
+	router: @routerFactory::create()
 ```
 
-Це еквівалентно коду PHP:
+Зауважте, що для простоти замість `->` ми використовуємо `::`, див. [засоби вираження |#expression means]. Ці фабричні методи генеруються:
 
 ```php
 public function createServiceDatabase(): PDO
 {
-	return My\Database::create('root', 'secret');
+	return DatabaseFactory::create();
+}
+
+public function createServiceRouter(): RouteList
+{
+	return $this->getService('routerFactory')->create();
 }
 ```
 
-Передбачається, що статичний метод `My\Database::create()` має певне значення, що повертається, яке повинен знати контейнер DI. Якщо у нього його немає, ми записуємо тип у конфігурацію:
+Контейнер DI повинен знати тип створюваного сервісу. Якщо ми створюємо сервіс за допомогою методу, який не має визначеного типу повернення, ми повинні явно вказати цей тип у конфігурації:
 
 ```neon
 services:
 	database:
-		create: My\Database::create(root, secret)
+		create: DatabaseFactory::create()
 		type: PDO
 ```
 
-Nette DI надає вам надзвичайно потужні засоби вираження, що дозволяють написати практично все, що завгодно. Наприклад, щоб [звернутися |#Referencing-Services] до іншої служби і викликати її метод. Для простоти замість `->` використовується `::`.
+
+Аргументи .[#toc-arguments]
+===========================
+
+Ми передаємо аргументи конструкторам і методам у спосіб, дуже схожий на звичайний PHP:
 
 ```neon
 services:
-	routerFactory: App\Router\Factory
-	router: @routerFactory::create()
+	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
 ```
 
-Це еквівалентно коду PHP:
+Для кращої читабельності ми можемо перераховувати аргументи в окремих рядках. У цьому форматі використання ком не є обов'язковим:
 
-```php
-public function createServiceRouterFactory(): App\Router\Factory
-{
-	return new App\Router\Factory;
-}
-
-public function createServiceRouter(): Router
-{
-	return $this->getService('routerFactory')->create();
-}
+```neon
+services:
+	database: PDO(
+		'mysql:host=127.0.0.1;dbname=test'
+		root
+		secret
+	)
 ```
 
-Виклики методів можна об'єднувати в ланцюжки, як у PHP:
+Ви також можете назвати аргументи, що дозволить вам не турбуватися про їх порядок:
 
 ```neon
 services:
-	foo: FooFactory::build()::get()
+	database: PDO(
+		username: root
+		password: secret
+		dsn: 'mysql:host=127.0.0.1;dbname=test'
+	)
 ```
 
-Це еквівалентно коду PHP:
+Якщо ви хочете пропустити певні аргументи і використовувати їхні значення за замовчуванням або вставити сервіс за допомогою [автопідключення |autowiring], використовуйте символ підкреслення:
 
-```php
-public function createServiceFoo()
-{
-	return FooFactory::build()->get();
-}
+```neon
+services:
+	foo: Foo(_, %appDir%)
 ```
 
+Аргументами можуть бути сервіси, параметри та багато іншого, див. розділ [Засоби вираження |#expression means].
 
-Аргументи .[#toc-arguments]
-===========================
 
-Іменовані параметри також можуть використовуватися для передачі аргументів:
+Налаштування .[#toc-setup]
+==========================
+
+У розділі `setup` ми визначаємо методи, які слід викликати при створенні сервісу.
 
 ```neon
 services:
-	database: PDO(
-		'mysql:host=127.0.0.1;dbname=test' # позиційний
-		username: root                     # іменований
-		password: secret                   # іменований
-	)
+	database:
+		create: PDO(%dsn%, %user%, %password%)
+		setup:
+			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
 ```
 
-Використання ком необов'язкове при розбитті аргументів на кілька рядків.
+На PHP це буде виглядати так:
 
-Звичайно, ми також можемо використовувати [інші сервіси |#Referencing-Services] або [параметри |configuration#Parameters] як аргументи:
+```php
+public function createServiceDatabase(): PDO
+{
+	$service = new PDO('...', '...', '...');
+	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	return $service;
+}
+```
+
+Крім викликів методів, ви також можете передавати значення властивостям. Додавання елемента до масиву також підтримується, але його потрібно брати в лапки, щоб уникнути конфлікту з синтаксисом NEON:
 
 ```neon
 services:
-	- Foo(@anotherService, %appDir%)
+	foo:
+		create: Foo
+		setup:
+			- $value = 123
+			- '$onClick[]' = [@bar, clickHandler]
 ```
 
-Відповідає коду PHP:
+У PHP це матиме вигляд:
 
 ```php
-public function createService01(): Foo
+public function createServiceFoo(): Foo
 {
-	return new Foo($this->getService('anotherService'), '...');
+	$service = new Foo;
+	$service->value = 123;
+	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+	return $service;
 }
 ```
 
-Якщо перший аргумент - [автомонтований |autowiring], а ви хочете вказати другий, опустіть перший за допомогою символу `_`, например `Foo(_, %appDir%)`. Або, що ще краще, передавайте тільки другий аргумент як іменований параметр, наприклад: `Foo(path: %appDir%)`.
-
-Nette DI і формат NEON дають вам надзвичайно потужні виразні засоби, що дозволяють написати практично все, що завгодно. Таким чином, аргументом може бути новостворений об'єкт, ви можете викликати статичні методи, методи інших сервісів або навіть глобальні функції, використовуючи спеціальну нотацію:
+У налаштуванні ви також можете викликати статичні методи або методи інших сервісів. Якщо вам потрібно передати поточний сервіс як аргумент, використовуйте `@self`:
 
 ```neon
 services:
-	analyser: My\Analyser(
-		FilesystemIterator(%appDir%)        # створюємо об'єкт
-		DateTime::createFromFormat('Y-m-d') # викликаємо статичний метод
-		@anotherService                     # передаємо інший сервіс
-		@http.request::getRemoteAddress()   # викликаємо метод іншого сервісу
-		::getenv(NetteMode)                 # викликаємо глобальну функцію
-	)
+	foo:
+		create: Foo
+		setup:
+			- My\Helpers::initializeFoo(@self)
+			- @anotherService::setFoo(@self)
 ```
 
-Відповідає коду PHP:
+Зауважте, що для простоти замість `->` ми використовуємо `::`, див. [засоби вираження |#expression means]. Це генерує наступний заводський метод:
 
 ```php
-public function createServiceAnalyser(): My\Analyser
+public function createServiceFoo(): Foo
 {
-	return new My\Analyser(
-		new FilesystemIterator('...'),
-		DateTime::createFromFormat('Y-m-d'),
-		$this->getService('anotherService'),
-		$this->getService('http.request')->getRemoteAddress(),
-		getenv('NetteMode')
-	);
+	$service = new Foo;
+	My\Helpers::initializeFoo($service);
+	$this->getService('anotherService')->setFoo($service);
+	return $service;
 }
 ```
 
 
-Спеціальні функції .[#toc-special-functions]
---------------------------------------------
-
-Ви також можете використовувати спеціальні функції в аргументах для приведення або заперечення значень:
+Засоби вираження .[#toc-expression-means]
+=========================================
 
-- `not(%arg%)` заперечення
-- `bool(%arg%)` приведення до bool без втрат
-- `int(%arg%)` приведення до int без втрат
-- `float(%arg%)` приведення до плаваючого стану без втрат
-- `string(%arg%)` приведення до рядка без втрат
+Nette DI надає нам надзвичайно багаті можливості для вираження, що дозволяє сформулювати майже все, що завгодно. У конфігураційних файлах ми можемо використовувати [параметри |configuration#parameters]:
 
 ```neon
-services:
-	- Foo(
-		id: int(::getenv('ProjectId'))
-		productionMode: not(%debugMode%)
-	)
-```
+# параметр
+%wwwDir%
 
-Переписування без втрат відрізняється від звичайного переписування в PHP, наприклад використовуючи `(int)`, у тому, що воно викидає виняток для нечислових значень.
+# значення під ключем параметра
+%mailer.user%
 
-Як аргументи можна передавати кілька сервісів. Масив усіх сервісів певного типу (тобто класу або інтерфейсу) створюється функцією `typed()`. Функція буде опускати сервіси, у яких відключено автопідключення, при цьому можна вказати кілька типів, розділених комою.
-
-```neon
-services:
-	- BarsDependent( typed(Bar) )
+# параметр у рядку
+'%wwwDir%/images'
 ```
 
-Ви також можете передати масив сервісів автоматично, використовуючи [автозв'язування |autowiring#Collection-of-Services].
-
-Масив усіх сервісів із певним [тегом |#Tags] створюється функцією `tagged()`. Можна вказати кілька тегів, розділених комою.
+Ми також можемо створювати об'єкти, викликати методи та функції:
 
 ```neon
-services:
-	- LoggersDependent( tagged(logger) )
-```
+# створити об'єкт
+DateTime()
 
+# викликати статичний метод
+Collator::create(%locale%)
 
-Посилання на сервіси .[#toc-referencing-services]
-=================================================
+# виклик функції PHP
+::getenv(DB_USER)
+```
 
-Посилання на окремі сервіси використовуються за допомогою символу `@` и имени, например `@database`:
+Звертайтеся до сервісів за назвою або за типом:
 
 ```neon
-services:
-	- create: Foo(@database)
-	  setup:
-			- setCacheStorage(@cache.storage)
+# послуга за назвою
+@database
+
+# послуга за типом
+@Nette\Database\Connection
 ```
 
-Відповідає коду PHP:
+Використовуйте першокласний синтаксис викликів: .{data-version:3.2.0}
 
-```php
-public function createService01(): Foo
-{
-	$service = new Foo($this->getService('database'));
-	$service->setCacheStorage($this->getService('cache.storage'));
-	return $service;
-}
+```neon
+# creating a callback, equivalent to [@user, logout]
+@user::logout(...)
 ```
 
-Навіть на анонімні сервіси можна посилатися за допомогою зворотного виклику, просто вкажіть їхній тип (клас або інтерфейс) замість імені. Однак зазвичай у цьому немає потреби через [автозв'язування |autowiring].
+Використовуйте константи:
 
 ```neon
-services:
-	- create: Foo(@Nette\Database\Connection)  # или @\PDO
-	  setup:
-			- setCacheStorage(@cache.storage)
+# константа класу
+FilesystemIterator::SKIP_DOTS
+
+# глобальна константа, отримана функцією PHP constant()
+::constant(PHP_VERSION)
 ```
 
+Виклики методів можна об'єднувати в ланцюжок, так само як і в PHP. Для простоти, замість `->` ми використовуємо `::`:
 
-Setup .[#toc-setup]
-===================
+```neon
+DateTime()::format('Y-m-d')
+# PHP: (new DateTime())->format('Y-m-d')
+
+@http.request::getUrl()::getHost()
+# PHP: $this->getService('http.request')->getUrl()->getHost()
+```
 
-У секції `setup` ми перераховуємо методи, які будуть викликатися під час створення сервісу:
+Ці вирази можна використовувати будь-де при [створенні сервісів |#Service Creation], в [аргументах |#Arguments], в розділі [налаштувань |#setup] або [параметрах |configuration#parameters]:
 
 ```neon
+parameters:
+	ipAddress: @http.request::getRemoteAddress()
+
 services:
 	database:
-		create: PDO(%dsn%, %user%, %password%)
+		create: DatabaseFactory::create( @anotherService::getDsn() )
 		setup:
-			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+			- initialize( ::getenv('DB_USER') )
 ```
 
-Відповідає коду PHP:
 
-```php
-public function createServiceDatabase(): PDO
-{
-	$service = new PDO('...', '...', '...');
-	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-	return $service;
-}
-```
+Спеціальні функції .[#toc-special-functions]
+--------------------------------------------
 
-Також можна встановити властивості. Додавання елемента в масив також підтримується, і його слід писати в лапках, щоб не конфліктувати із синтаксисом NEON:
+У файлах конфігурації ви можете використовувати ці спеціальні функції:
 
+- `not()` для заперечення значення
+- `bool()`, `int()`, `float()`, `string()` для приведення типів без втрат
+- `typed()` для створення масиву всіх сервісів заданого типу
+- `tagged()` для створення масиву всіх сервісів із заданим тегом
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- $value = 123
-			- '$onClick[]' = [@bar, clickHandler]
-```
-
-Відповідає коду PHP:
-
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	$service->value = 123;
-	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
-	return $service;
-}
+	- Foo(
+		id: int(::getenv('ProjectId'))
+		productionMode: not(%debugMode%)
+	)
 ```
 
-Однак статичні методи або методи інших сервісів також можуть бути викликані в налаштуванні. Ми передаємо їм фактичний сервіс як `@self`:
+У порівнянні зі звичайним приведенням типів у PHP, наприклад, `(int)`, приведення типів без втрат згенерує виключення для нечислових значень.
 
+Функція `typed()` створює масив усіх сервісів певного типу (класу або інтерфейсу). Вона виключає сервіси з вимкненим автопідключенням. Можна вказати декілька типів, розділених комами.
 
 ```neon
 services:
-	foo:
-		create: Foo
-		setup:
-			- My\Helpers::initializeFoo(@self)
-			- @anotherService::setFoo(@self)
+	- BarsDependent( typed(Bar) )
 ```
 
-Відповідає коду PHP:
+Ви також можете автоматично передати масив сервісів певного типу як аргумент за допомогою [автопідключення |autowiring#Collection of Services].
 
-```php
-public function createServiceFoo(): Foo
-{
-	$service = new Foo;
-	My\Helpers::initializeFoo($service);
-	$this->getService('anotherService')->setFoo($service);
-	return $service;
-}
+Функція `tagged()` створює масив усіх сервісів із зазначеним тегом. Можна перерахувати декілька тегів, розділених комами.
+
+```neon
+services:
+	- LoggersDependent( tagged(logger) )
 ```
 
 
-Автозв'язування .[#toc-autowiring]
-==================================
+Автопроводка .[#toc-autowiring]
+===============================
 
-Ключ `autowired` можна використовувати для виключення сервісу з автозв'язування або для впливу на його поведінку. Детальнішу інформацію див. у розділі [Автозв'язування |autowiring].
+За допомогою ключа `autowired` ви можете змінити поведінку автопідключення для певного сервісу. Для більш детальної інформації дивіться [розділ про автопідключення |autowiring].
 
 ```neon
 services:
 	foo:
 		create: Foo
-		autowired: false # foo видаляється з автозв'язування
+		autowired: false     # сервіс foo виключено з автопідключення
 ```
 
 
 Теги .[#toc-tags]
 =================
 
-Інформація про користувача може бути додана до окремих сервісів у вигляді тегів:
+Теги використовуються для додавання додаткової інформації до послуг. Ви можете призначити послузі один або декілька тегів:
 
 ```neon
 services:
@@ -360,7 +353,7 @@ services:
 			- cached
 ```
 
-Теги також можуть мати значення:
+Мітки також можуть мати значення:
 
 ```neon
 services:
@@ -370,26 +363,26 @@ services:
 			logger: monolog.logger.event
 ```
 
-Масив сервісів з певними тегами може бути переданий як аргумент за допомогою функції `tagged()`. Можна також вказати кілька тегів, розділених комою.
+Щоб отримати всі сервіси з певними тегами, ви можете скористатися функцією `tagged()`:
 
 ```neon
 services:
 	- LoggersDependent( tagged(logger) )
 ```
 
-Імена служб можна отримати з контейнера DI за допомогою методу `findByTag()`:
+У контейнері DI ви можете отримати назви всіх сервісів з певним тегом за допомогою методу `findByTag()`:
 
 ```php
 $names = $container->findByTag('logger');
-// $names - масив, що містить ім'я сервісу і значення тега
-// наприклад ['foo' => 'monolog.logger.event', ...]
+// $names - масив, що містить назву сервісу та значення тегу
+// наприклад, ['foo' => 'monolog.logger.event', ...]
 ```
 
 
-Режим впровадження .[#toc-inject-mode]
+Режим впорскування .[#toc-inject-mode]
 ======================================
 
-Прапор `inject: true` використовується для активації передавання залежностей через публічні змінні за допомогою анотації [inject |best-practices:inject-method-attribute#Inject Attributes] і методів [inject*() |best-practices:inject-method-attribute#inject Methods].
+Використання прапора `inject: true` активує передачу залежностей через загальнодоступні змінні з анотацією [inject |best-practices:inject-method-attribute#Inject Attributes] та методами [inject*( |best-practices:inject-method-attribute#inject Methods] ).
 
 ```neon
 services:
@@ -398,13 +391,13 @@ services:
 		inject: true
 ```
 
-За замовчуванням `inject` активується тільки для презентерів.
+За замовчуванням прапорець `inject` активовано лише для доповідачів.
 
 
-Модифікація сервісів .[#toc-modification-of-services]
-=====================================================
+Модифікації сервісу .[#toc-service-modifications]
+=================================================
 
-У контейнері DI є низка сервісів, які були додані вбудованим або [вашим розширенням |#di-extension]. Визначення цих сервісів можуть бути змінені в конфігурації. Наприклад, для сервісу `application.application`, який за замовчуванням є об'єктом `Nette\Application\Application`, ми можемо змінити клас:
+Контейнер DI містить багато сервісів, доданих за допомогою вбудованих або [користувацьких розширень |#extensions]. Ви можете змінювати визначення цих сервісів безпосередньо в конфігурації. Наприклад, ви можете змінити клас сервісу `application.application`, який умовно називається `Nette\Application\Application`, на щось інше:
 
 ```neon
 services:
@@ -413,9 +406,9 @@ services:
 		alteration: true
 ```
 
-Прапор `alteration` є інформативним і говорить про те, що ми просто змінюємо існуючий сервіс.
+Прапорець `alteration` є інформативним, вказуючи на те, що ми просто змінюємо існуючий сервіс.
 
-Ми також можемо додати `setup`:
+Ми також можемо доповнити налаштування:
 
 ```neon
 services:
@@ -426,7 +419,7 @@ services:
 			- '$onStartup[]' = [@resource, init]
 ```
 
-Під час перезапису сервісу ми можемо видалити вихідні аргументи, елементи `setup` або теги, для яких `reset` є:
+При перезаписуванні сервісу ви можете захотіти видалити оригінальні аргументи, елементи налаштувань або теги, і саме тут у нагоді стане `reset`:
 
 ```neon
 services:
@@ -439,7 +432,7 @@ services:
 			- tags
 ```
 
-Сервіс, доданий розширенням, також може бути видалено з контейнера:
+Якщо ви хочете видалити сервіс, доданий розширенням, ви можете зробити це так:
 
 ```neon
 services:
diff --git a/forms/bg/controls.texy b/forms/bg/controls.texy
index 9b6407375b..97246f2c9e 100644
--- a/forms/bg/controls.texy
+++ b/forms/bg/controls.texy
@@ -5,8 +5,8 @@
 Преглед на вградените контроли на формуляра.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Добавя текстово поле с един ред (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Ако потребителят не попълни полето, се връща празен низ `''`, или използвайте `setNullable()`, за да върнете `null`.
 
@@ -20,13 +20,10 @@ $form->addText('name', 'Имя:')
 
 Максималната дължина може да бъде ограничена с помощта на `setMaxLength()`. Функцията [addFilter() |validation#Modifying-Input-Values] позволява да се промени стойността, въведена от потребителя.
 
-Използвайте `setHtmlType()`, за да промените [типа на |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] входния елемент на `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Препоръчваме да използвате [addInteger |#addInteger] и [addEmail |#addEmail] вместо `number` и `email`, тъй като те осигуряват валидиране от страна на сървъра.
+Можете да промените визуалния характер на текстово поле до типове като `search`, `tel` или `url`, като използвате `setHtmlType()`, както е показано в [спецификацията |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Не забравяйте, че промяната на типа е само визуална и не изпълнява функции за валидиране. За типа `url` е подходящо да добавите специфично [правило за URL |validation#Text inputs].
 
-```php
-$form->addText('color', 'Выберите цвет:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'недопустимое значение', '[0-9a-f]{6}');
-```
+.[note]
+За други типове входни данни, като `number`, `range`, `email`, `date`, `datetime-local`, `time` и `color`, използвайте специализирани методи като [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] и [addColor |#addColor], които осигуряват валидиране от страна на сървъра. Типовете `month` и `week` все още не се поддържат напълно от всички браузъри.
 
 Един елемент може да бъде зададен на така наречената "празна стойност", която е нещо подобно на стойността по подразбиране, но ако потребителят не я презапише, тя връща празен низ или `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Добавя поле за въвеждане на цяло число (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Връща цяло число или `null`, ако потребителят не е въвел нищо.
 
 ```php
-$form->addInteger('level', 'Уровень:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'The year must be in the range %d to %d.', [1900, 2023 |1900, 2023]);
+```
+
+Елементът се визуализира като `<input type="numeric">`. Като използвате метода `setHtmlType()`, можете да промените типа на `range` за показване като плъзгач или на `text`, ако предпочитате стандартно текстово поле без специалното поведение на `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]);
+->addRule($form::Range, 'Нивото трябва да е в диапазона от %d до %d.', [0, 100 |0, 100]);
 ```
 
+Елементът се визуализира като `<input type="numeric">`. Като използвате метода `setHtmlType()`, можете да промените типа на `range` за показване като плъзгач или на `text`, ако предпочитате стандартно текстово поле без специалното поведение на `numeric`.
+
+Nette и браузърът Chrome приемат както запетая, така и точка като десетични разделители. За да направите тази функционалност достъпна във Firefox, се препоръчва да зададете атрибута `lang` или за конкретния елемент, или за цялата страница, например, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Добавя валидирано поле за имейл адрес (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Ако потребителят не е попълнил полето, се връща празен низ `''` или използвайте `setNullable()`, за да върнете `null`.
 
@@ -78,8 +92,8 @@ $form->addEmail('email', 'Имейл:');
 Максималната дължина може да бъде ограничена с помощта на `setMaxLength()`. Функцията [addFilter() |validation#Modifying-Input-Values] ви позволява да промените стойността, въведена от потребителя. Можете да зададете така наречената "празна стойност", като използвате `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Добавя поле за парола (клас [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'Я согласен с условиями')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Добавя списък с квадратчета за избор на няколко елемента (клас [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Връща масив от ключове на избрани елементи. Методът `getSelectedItems()` връща стойности вместо ключове.
 
@@ -125,9 +139,15 @@ $form->addCheckboxList('colors', 'Цвета:', [
 
 При задаване на стойности по подразбиране се проверява също дали те са един от предлаганите елементи, в противен случай се прави изключение. Тази проверка може да бъде деактивирана с помощта на `checkDefaultValue(false)`.
 
+Ако изпращате формуляр чрез метода `GET`, можете да изберете по-компактен метод за прехвърляне на данни, който спестява от размера на низ от заявки. Това се активира чрез задаване на HTML атрибут на формуляра:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Добавя радио бутони (клас [RadioList |api:Nette\Forms\Controls\RadioList]). Връща ключа на избрания елемент или `null`, ако потребителят не е избрал нищо. Методът `getSelectedItem()` връща стойност вместо ключ.
 
@@ -148,8 +168,8 @@ $form->addRadioList('gender', 'Пол:', $sex);
 При настройката по подразбиране се проверява дали това е един от предлаганите елементи, в противен случай се подава изключение. Тази проверка може да бъде деактивирана с помощта на `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Добавя поле за избор (клас [SelectBox |api:Nette\Forms\Controls\SelectBox]). Връща ключа на избрания елемент или `null`, ако потребителят не е избрал нищо. Методът `getSelectedItem()` връща стойност вместо ключ.
 
@@ -193,8 +213,8 @@ $form->addSelect('country', 'Страна:', $countries)
 При настройката по подразбиране се проверява дали това е един от предлаганите елементи, в противен случай се подава изключение. Тази проверка може да бъде деактивирана с помощта на `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Добавя поле за множествен избор (клас [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Връща масив от ключове на избрани елементи. Методът `getSelectedItems()` връща стойности вместо ключове.
 
@@ -246,8 +266,81 @@ $form->addMultiUpload('files', 'Файлы:')
 Правилата `MimeType` и `Image` идентифицират желания тип файл или изображение чрез неговия подпис. Целостта на целия файл не се проверява. Можете да разберете дали дадено изображение е повредено, например като се опитате да [го изтеглите |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Добавя поле, което позволява на потребителя лесно да въвежда дата, състояща се от година, месец и ден (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+За стойност по подразбиране приема или обекти, реализиращи `DateTimeInterface`, низ с време, или число, представляващо времеви печат на UNIX. Същото се отнася и за аргументите на правилата `Min`, `Max` или `Range`, които определят минималната и максималната допустима дата.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+По подразбиране програмата връща обект `DateTimeImmutable`. Използвайки метода `setFormat()`, можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или времева марка:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Добавя поле, което позволява на потребителя лесно да въвежда време, състоящо се от часове, минути и по избор секунди (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+За стойност по подразбиране то приема или обекти, реализиращи `DateTimeInterface`, низ с време, или число, представляващо UNIX времеви печат. Използва се само информацията за времето от тези входове; датата се игнорира. Същото се отнася и за аргументите на правилата `Min`, `Max` или `Range`, които определят минималното и максималното разрешено време. Ако зададената минимална стойност е по-висока от максималната, се създава времеви диапазон, обхващащ полунощ.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+По подразбиране той връща обект `DateTimeImmutable` (с дата 1 януари, година 1). Чрез метода `setFormat()` можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Добавя поле, което позволява на потребителя лесно да въвежда както дата, така и час, състоящи се от година, месец, ден, часове, минути и по желание секунди (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+За стойност по подразбиране то приема или обекти, реализиращи `DateTimeInterface`, низ с време, или число, представляващо UNIX timestamp. Същото се отнася и за аргументите на правилата `Min`, `Max` или `Range`, които определят минималната и максималната допустима дата.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+По подразбиране програмата връща обект `DateTimeImmutable`. Използвайки метода `setFormat()`, можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или времева марка:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Добавя поле за избор на цвят (клас [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Цветът е низ във формат `#rrggbb`. Ако потребителят не направи избор, върнатият цвят по подразбиране е черен `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Добавя скрито поле (клас [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Използвайте `setNullable()`, за да го модифицирате така, че да връща `null` вместо празен низ. Функцията [addFilter() |validation#Modifying-Input-Values] ви позволява да промените представената стойност.
 
+Въпреки че елементът е скрит, важно е да осъзнаете**, че стойността му все още може да бъде променена или подправена от нападател. Винаги проверявайте и валидирайте обстойно всички получени стойности от страна на сървъра, за да предотвратите рисковете за сигурността, свързани с манипулиране на данни.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Поднять зарплату')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Добавя бутон за изпращане като изображение (клас [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ $sub2->addEmail('email', 'Имейл:');
 
 
 пропуснати стойности .[#toc-omitted-values]
--------------------------------------------
+===========================================
 
 Ако не се интересувате от стойността, въведена от потребителя, можем да използваме `setOmitted()`, за да я пропуснем в резултата, предоставен от метода `$form->getValues()` или предаден на обработващите програми. Това е подходящо за различни пароли за валидиране, полета за защита от спам и др.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Повторите пароль:')
 
 
 Деактивиране на входните елементи .[#toc-disabling-inputs]
-----------------------------------------------------------
+==========================================================
 
-За да деактивирате въвеждането, можете да се обадите на `setDisabled()`. Такова поле не може да се редактира от потребителя.
+Входовете могат да бъдат деактивирани с помощта на `setDisabled()`. Деактивиран вход не може да се редактира от потребителя.
 
 ```php
 $form->addText('username', 'Имя пользователя:')
 	->setDisabled();
 ```
 
-Обърнете внимание, че браузърът изобщо не изпраща забранените полета към сървъра, така че те дори няма да бъдат открити в данните, върнати от функцията `$form->getValues()`.
+Деактивираните входове не се изпращат към сървъра от браузъра, така че няма да ги намерите в данните, върнати от функцията `$form->getValues()`. Ако обаче зададете `setOmitted(false)`, Nette ще включи стойността им по подразбиране в тези данни.
 
-Ако задавате стойност по подразбиране за дадено поле, трябва да го направите само след като сте го деактивирали:
+Когато се извика `setDisabled()`, **стойността на входа се изтрива** от съображения за сигурност. Ако задавате стойност по подразбиране, е необходимо да го направите след нейното деактивиране:
 
 ```php
 $form->addText('username', 'Имя пользователя:')
@@ -409,6 +504,8 @@ $form->addText('username', 'Имя пользователя:')
 	->setDefaultValue($userName);
 ```
 
+Алтернатива на забранените входове са полетата с атрибут HTML `readonly`, които се изпращат на сървъра от браузъра. Въпреки че полето е само за четене, **важно е да се разбере**, че стойността му все пак може да бъде променена или подправена от нападател.
+
 
 Потребителски контроли .[#toc-custom-controls]
 ==============================================
@@ -428,8 +525,8 @@ $form->addComponent(new DateInput('Дата:'), 'date');
 ```php
 use Nette\Forms\Container;
 
-// метод addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// метод addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Не менее 5 номеров', '[0-9]{5}');
 });
diff --git a/forms/bg/in-presenter.texy b/forms/bg/in-presenter.texy
index ae2285540f..9bd06c24b4 100644
--- a/forms/bg/in-presenter.texy
+++ b/forms/bg/in-presenter.texy
@@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded'];
 
 От гледна точка на водещия формулярът е общ компонент. Затова той се третира като компонент и се включва в презентатора чрез [метода factory |application:components#Factory-Methods]. Това ще изглежда по следния начин:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 А визуализирането в шаблона се извършва с помощта на тага `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Регистрация</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ $form->addText('name', 'Имя:')
 Вмъкнете го в шаблона за оформление:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ако разгледате изходния код на страницата с формуляра, можете да забележите, че Nette вмъква задължителни полета в елементи с клас CSS `required`. Опитайте се да добавите следния стил към шаблона и тагът "Име" ще бъде червен. Елегантно маркираме задължителните полета за потребителите:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-От PHP 8.0 можете да използвате този елегантен запис, който използва конструктор:
+Като алтернатива можете да използвате конструктора:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Свойствата на класа за данни също могат да бъдат енуми и те ще бъдат автоматично картографирани. .{data-version:3.2.4}
+
 Как казвате на Nette да връща данни като обекти от този клас? По-лесно е, отколкото си мислите. Всичко, което трябва да направите, е да посочите класа като параметър от тип `$data` в обработващото устройство:
 
 ```php
@@ -294,6 +296,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Можете да генерирате предложение за класа данни на формуляра, като използвате метода `Nette\Forms\Blueprint::dataClass($form)`, който ще го отпечата на страницата на браузъра. След това можете просто да щракнете, за да изберете и копирате кода в проекта си. .{data-version:3.1.15}
+
 
 Множество бутони за изпращане .[#toc-multiple-submit-buttons]
 =============================================================
diff --git a/forms/bg/rendering.texy b/forms/bg/rendering.texy
index a9347307a8..12412514f2 100644
--- a/forms/bg/rendering.texy
+++ b/forms/bg/rendering.texy
@@ -11,6 +11,8 @@
 
 [Системата за шаблони Latte |latte:] улеснява значително изчертаването на форми и техните елементи. Първо ще ви покажем как да визуализирате формулярите ръчно, елемент по елемент, за да получите пълен контрол върху кода. По-късно ще ви покажем как да [автоматизирате |#Automatic-Rendering] такова визуализиране.
 
+Можете да имате предложение за шаблон Latte за формуляра, генериран чрез метода `Nette\Forms\Blueprint::latte($form)`, който ще го изведе на страницата на браузъра. След това просто трябва да изберете кода с едно щракване и да го копирате в проекта си. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form
 ```
 
 
-Код на офертата `{formPrint}` .[#toc-formprint]
------------------------------------------------
-
-Можете да генерирате подобен код Latte за формата, като използвате тага `{formPrint}`. Ако го поставите в шаблон, ще видите черновия код вместо обичайното визуализиране. След това просто го изберете и го копирайте в проекта си.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ protected function createComponentSignInForm(): Form
 Специални случаи .[#toc-special-cases]
 --------------------------------------
 
-Ако трябва да покажете само вътрешното съдържание на формуляра, без да `<form>` & `</form>` HTML тагове, например в AJAX заявка, можете да отваряте и затваряте формуляра, като използвате `{formContext} … {/formContext}`. В логически смисъл той работи подобно на `{form}`, като тук ви позволява да използвате други тагове, за да рисувате елементи на формата, но в същото време не рисува нищо.
+Ако трябва да визуализирате само вътрешната част на формуляра без HTML тагове `<form>`например при изпращане на фрагменти, скрийте ги с помощта на атрибута `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Имя пользователя: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Тагът `formContainer` помага за визуализиране на входните данни в контейнера на формата.
@@ -434,6 +430,8 @@ $form->addText('city', 'Город:');
 $form->addSelect('country', 'Страна:', $countries);
 ```
 
+Рендърът рисува първо групите, а след това елементите, които не принадлежат към никоя група.
+
 
 Поддръжка на Bootstrap .[#toc-bootstrap-support]
 ------------------------------------------------
@@ -444,7 +442,7 @@ $form->addSelect('country', 'Страна:', $countries);
 Атрибути на HTML .[#toc-html-attributes]
 ========================================
 
-Можете да задавате всякакви HTML атрибути за контролите на формуляра, като използвате `setHtmlAttribute(string $name, $value = true)`:
+За задаване на произволни HTML атрибути за елементите на формата използвайте метода `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // извикване на JS функцията submit() при промяна
 
 
-//прилага се за <form>
+// За задаване на атрибути на самия <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Задаване на типа на влизане:
+Посочване на типа на елемента:
 
 ```php
 $form->addText('tel', 'Ваш телефон:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Ваш телефон:')
 	->setHtmlAttribute('placeholder', 'Пожалуйста, заполните ваш телефон');
 ```
 
-Можем да зададем HTML атрибут за отделните елементи в списъците с радиоклипове или квадратчета с различни стойности за всеки от тях.
-Обърнете внимание на двоеточието след `style:`, за да се гарантира, че стойността е избрана от ключа:
+.[warning]
+Задаването на типа и другите атрибути служи само за визуални цели. Проверката на коректността на въведените данни трябва да се извърши на сървъра, което можете да осигурите чрез избор на подходящ [контрол на формата | controls] и задаване на [правила за валидиране | validation].
+
+За отделните елементи в списъците с радиостанции или квадратчета можем да зададем HTML атрибут с различни стойности за всеки от тях.
+Обърнете внимание на двоеточието след `style:`, което гарантира, че стойността се избира въз основа на ключа:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ $form->addCheckboxList('colors', 'Цвета:', $colors)
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Въпросителният знак може да се използва за булев HTML атрибут (който няма стойност, например `readonly`):
+За задаване на булеви атрибути, като например `readonly`, можем да използваме означението с въпросителен знак:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // използвайте масив за няколко ключа, например ['r', 'g']
 ```
@@ -541,9 +541,6 @@ $html->class('distinctive'); // <label class="distinctive">
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/bg/standalone.texy b/forms/bg/standalone.texy
index 5c2c5fc550..a3caeceff0 100644
--- a/forms/bg/standalone.texy
+++ b/forms/bg/standalone.texy
@@ -107,7 +107,7 @@ $form->addText('name', 'Имя:')
 Добавете го към страницата:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ако разгледате изходния код на страницата с формуляра, можете да забележите, че Nette вмъква задължителни полета в елементи с клас CSS `required`. Опитайте се да добавите следния стил към шаблона и тагът "Име" ще бъде червен. Елегантно маркираме задължителните полета за потребителите:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-От PHP 8.0 можете да използвате този елегантен запис, който използва конструктор:
+Като алтернатива можете да използвате конструктора:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Свойствата на класа за данни също могат да бъдат енуми и те ще бъдат автоматично картографирани. .{data-version:3.2.4}
+
 Как да кажем на Nette да ни връща данни като обекти от този клас? По-лесно е, отколкото си мислите. Всичко, което трябва да направите, е да посочите името на класа или обекта, който искате да хидратирате, като параметър:
 
 ```php
@@ -258,6 +260,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Можете да генерирате предложение за класа данни на формуляра, като използвате метода `Nette\Forms\Blueprint::dataClass($form)`, който ще го отпечата на страницата на браузъра. След това можете просто да щракнете, за да изберете и копирате кода в проекта си. .{data-version:3.1.15}
+
 
 Множество бутони за изпращане .[#toc-multiple-submit-buttons]
 =============================================================
diff --git a/forms/bg/validation.texy b/forms/bg/validation.texy
index 742c787c3c..2f5a38cc3b 100644
--- a/forms/bg/validation.texy
+++ b/forms/bg/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Пароль:')
 	->addRule($form::MinLength, 'Пароль должен состоять не менее чем из %d символов', 8);
 ```
 
-Nette разполага с редица вградени правила, чиито имена са константи от класа `Nette\Forms\Form`:
+**Правилата за валидиране се проверяват само ако потребителят е попълнил елемента.**
 
-Можем да използваме следните правила за всички контроли:
+Nette се предлага с редица предварително дефинирани правила, чиито имена са константи от класа `Nette\Forms\Form`. Можем да прилагаме тези правила към всички елементи:
 
 | константа | описание | аргументи
 |-------
@@ -38,7 +38,11 @@ Nette разполага с редица вградени правила, чии
 | `IsNotIn` | стойността не е равна на нито един елемент от масива | `array`
 | `Valid` | записът преминава валидиране (за [Условие |#Условия]) | -
 
-За контролите `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` могат да се използват и следните правила:
+
+Въвеждане на текст .[#toc-text-inputs]
+--------------------------------------
+
+За елементите `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` могат да се приложат и някои от следните правила:
 
 | `MinLength` | минимална дължина на реда `int`
 | `MaxLength` | максимална дължина на реда `int`
@@ -57,9 +61,23 @@ Nette разполага с редица вградени правила, чии
 Правилата `Integer`, `Numeric` и `Float` автоматично преобразуват стойността в цяло число (или съответно в число с плаваща запетая). Освен това правилото `URL` приема и адрес без схема (напр. `nette.org`) и допълва схемата (`https://nette.org`).
 Изразите в `Pattern` и `PatternInsensitive` трябва да са валидни за цялата стойност, т.е. все едно са обвити в `^` и `$`.
 
+
+Брой на елементите .[#toc-number-of-items]
+------------------------------------------
+
+За елементите `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` можете да използвате и следните правила, за да ограничите броя на избраните елементи или качените файлове:
+
+| `MinLength` | минимален брой | `int`
+| `MaxLength` | максимален брой | `int`
+| `Length` | брой в диапазон или точен брой | двойки `[int, int]` или `int`
+
+
+Качване на файлове
+------------------
+
 Следните правила могат да се използват и за контроли `addUpload()`, `addMultiUpload()`:
 
-| `MaxFileSize` | максимален размер на файла | `int`
+| `MaxFileSize` | максимален размер на файла в байтове | `int`
 | `MimeType` | Тип MIME, приема заместващи символи (`'video/*'`) | `string\|string[]`
 | `Image` | изтегленият файл е JPEG, PNG, GIF, WebP | -
 | `Pattern` | името на файла отговаря на регулярен израз | `string`
@@ -67,15 +85,9 @@ Nette разполага с редица вградени правила, чии
 
 За `MimeType` и `Image` се изисква разширението на PHP `fileinfo`. Правилният тип на файла или изображението се определя от неговия подпис. Целостта на целия файл не се проверява. Можете да проверите дали дадено изображение е повредено, например като се опитате да [го заредите |http:request#toImage].
 
-За контролите `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` могат да се използват и следните правила, за да се ограничи броят на избраните елементи, съответно изтеглените файлове:
-
-| `MinLength` | минимален брой | `int`
-| `MaxLength` | максимален брой | `int`
-| `Length` | сума в диапазон или точна сума | параграф `[int, int]` или `int`
-
 
 Съобщения за грешки .[#toc-error-messages]
-------------------------------------------
+==========================================
 
 Всички предварително дефинирани правила, с изключение на `Pattern` и `PatternInsensitive`, имат съобщение за грешка по подразбиране, така че можете да ги пропуснете. Въпреки това, като предавате и формулирате всички отделни съобщения, ще направите формуляра по-удобен за ползване.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 В Nette е много лесно да се реагира на изпълнението или неизпълнението на дадено условие от страна на JavaScript, като се използва методът `toggle()`, вж. раздел [Динамичен JavaScript |#Динамический JavaScript].
 
 
-Връзки между контролите .[#toc-references-between-controls]
-===========================================================
+Препратка към друг елемент .[#toc-reference-to-another-element]
+===============================================================
 
-Аргумент на правило или условие може да бъде препратка към друг елемент. Например можете динамично да потвърдите, че `text` има толкова знаци, колкото са посочени в полето `length`:
+Като аргумент за правило или условие можете да предадете и друг елемент от формуляра. Тогава правилото ще използва стойността, въведена по-късно от потребителя в браузъра. Това може да се използва например за динамично потвърждаване, че елементът `password` съдържа същия низ като елемента `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ $form->addText('zip', 'postcode:')
 Можете да вградите скрипта директно в HTML страница от CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Или копирайте локално в обща папка на проекта (например от `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/cs/controls.texy b/forms/cs/controls.texy
index ff382a7ed6..adb1a405bf 100644
--- a/forms/cs/controls.texy
+++ b/forms/cs/controls.texy
@@ -5,8 +5,8 @@ Formulářové prvky
 Přehled standardních formulářových prvků.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Přidá jednořádkové textové políčko (třída [TextInput |api:Nette\Forms\Controls\TextInput]). Pokud uživatel pole nevyplní, vrací prázdný řetězec `''`, nebo pomocí `setNullable()` lze určit, aby vracel `null`.
 
@@ -20,13 +20,10 @@ Automaticky validuje UTF-8, ořezává levo- a pravostranné mezery a odstraňuj
 
 Maximální délku lze omezit pomocí `setMaxLength()`. Pozměnit uživatelem vloženou hodnotu umožňuje [addFilter()|validation#Úprava vstupu].
 
-Pomocí `setHtmlType()` lze změnit [charakter|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vstupního prvku na `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Místo typů `number` a `email` doporučujeme použít [#addInteger] a [#addEmail], které disponují validací na straně serveru.
+Pomocí `setHtmlType()` lze změnit vizuální charakter textového pole na typy jako `search`, `tel` nebo `url` viz [specifikace|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Pamatujte, že změna typu je pouze vizuální a nezastupuje funkci validace. Pro typ `url` je vhodné přidat specifické validační [pravidlo URL|validation#Textové vstupy].
 
-```php
-$form->addText('color', 'Vyberte barvu:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Pro další typy vstupů, jako `number`, `range`, `email`, `date`, `datetime-local`, `time` a `color`, použijte specializované metody jako [#addInteger], [#addFloat], [#addEmail] [#addDate], [#addTime], [#addDateTime] a [#addColor], které zajišťují serverovou validaci. Typy `month` a `week` zatím nejsou plně podporovány ve všech prohlížečích.
 
 Prvku lze nastavit tzv. empty-value, což je něco jako výchozí hodnota, ale pokud ji uživatel nezmění, vrátí prvek prázdný řetězec či `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Přidá políčko pro zadání celočíselného čísla (třída [TextInput |api:Nette\Forms\Controls\TextInput]). Vrací buď integer, nebo `null`, pokud uživatel nic nezadá.
 
 ```php
-$form->addInteger('level', 'Úroveň:')
+$form->addInteger('year', 'Rok:')
+	->addRule($form::Range, 'Rok musí být v rozsahu od %d do %d.', [1900, 2023]);
+```
+
+Prvek se vykresluje jako `<input type="numeric">`. Použitím metody `setHtmlType()` lze změnit typ na `range` pro zobrazení v podobě posuvníku, nebo na `text`, pokud preferujete standardní textové pole bez speciálního chování typu `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Přidá políčko pro zadání desetinného čísla (třída [TextInput |api:Nette\Forms\Controls\TextInput]). Vrací buď float, nebo `null`, pokud uživatel nic nezadá.
+
+```php
+$form->addFloat('level', 'Úroveň:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Úroveň musí být v rozsahu mezi %d a %d.', [0, 100]);
+	->addRule($form::Range, 'Úroveň musí být v rozsahu od %d do %d.', [0, 100]);
 ```
 
+Prvek se vykresluje jako `<input type="numeric">`. Použitím metody `setHtmlType()` lze změnit typ na `range` pro zobrazení v podobě posuvníku, nebo na `text`, pokud preferujete standardní textové pole bez speciálního chování typu `numeric`.
+
+Nette a prohlížeč Chrome akceptují jako oddělovač desetinných míst jak čárku, tak tečku. Aby byla tato funkcionalita dostupná i ve Firefoxu, je doporučeno nastavit atribut `lang` buď pro daný prvek nebo pro celou stránku, například `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Přidá políčko pro zadání e-mailové adresy (třída [TextInput |api:Nette\Forms\Controls\TextInput]). Pokud uživatel pole nevyplní, vrací prázdný řetězec `''`, nebo pomocí `setNullable()` lze určit, aby vracel `null`.
 
@@ -78,8 +92,8 @@ Ověří, zda je hodnota platná e-mailová adresa. Neověřuje se, zda doména
 Maximální délku lze omezit pomocí `setMaxLength()`. Pozměnit uživatelem vloženou hodnotu umožňuje [addFilter()|validation#Úprava vstupu]. Lze nastavit tzv. empty-value pomocí `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Přidá políčko pro zadání hesla (třída [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'Souhlasím s podmínkami')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Přidá zaškrtávací políčka pro výběr více položek (třída [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Vrací pole klíčů vybraných položek. Metoda `getSelectedItems()` vrací hodnoty místo klíčů.
 
@@ -125,9 +139,15 @@ Prvek automaticky kontroluje, že nedošlo k podvržení a že vybrané položky
 
 Při nastavení výchozích vybraných položek také kontroluje, že jde o jedny z nabízených, jinak vyhodí výjimku. Tuto kontrolu lze vypnout pomocí `checkDefaultValue(false)`.
 
+Pokud odesíláte formulář metodou `GET`, můžete zvolit kompaktnější způsob přenosu dat, který šetří velikost query stringu. Aktivuje se nastavením HTML atributu formuláře:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Přidá přepínací tlačítka (třída [RadioList |api:Nette\Forms\Controls\RadioList]). Vrací klíč vybrané položky, nebo `null`, pokud uživatel nic nevybral. Metoda `getSelectedItem()` vrací hodnotu místo klíče.
 
@@ -148,8 +168,8 @@ Prvek automaticky kontroluje, že nedošlo k podvržení a že vybraná položka
 Při nastavení výchozí vybrané položky také kontroluje, že jde o jednou z nabízených, jinak vyhodí výjimku. Tuto kontrolu lze vypnout pomocí `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Přidá select box (třída [SelectBox |api:Nette\Forms\Controls\SelectBox]). Vrací klíč vybrané položky, nebo `null`, pokud uživatel nic nevybral. Metoda `getSelectedItem()` vrací hodnotu místo klíče.
 
@@ -193,8 +213,8 @@ Prvek automaticky kontroluje, že nedošlo k podvržení a že vybraná položka
 Při nastavení výchozí vybrané položky také kontroluje, že jde o jednou z nabízených, jinak vyhodí výjimku. Tuto kontrolu lze vypnout pomocí `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Přidá select box pro výběr více položek (třída [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Vrací pole klíčů vybraných položek. Metoda `getSelectedItems()` vrací hodnoty místo klíčů.
 
@@ -246,8 +266,81 @@ Nikdy nevěřte originálním názvům souborů vráceným metodou `FileUpload::
 Pravidla `MimeType` a `Image` detekují požadovaný typ na základě signatury souboru a neověřují jeho integritu. Zda není obrázek poškozený lze zjistit například pokusem o jeho [načtení|http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Přidá políčko, které umožní uživateli snadno zadat datum skládající se z roku, měsíce a dne (třída [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Jako výchozí hodnotu akceptuje buď objekty implementující rozhraní `DateTimeInterface`, řetězec s časem, nebo číslo představující UNIX timestamp. Totéž platí pro argumenty pravidel `Min`, `Max` nebo `Range`, jež definují minimální a maximální povolený datum.
+
+```php
+$form->addDate('date', 'Datum:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'Datum musí být minimálně měsíc staré.', new DateTime('-1 month'));
+```
+
+Standardně vrací objekt `DateTimeImmutable`, metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] či timestamp:
+
+```php
+$form->addDate('date', 'Datum:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Přidá políčko, které umožní uživateli snadno zadat čas skládající se z hodin, minut a volitelně i sekund (třída [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Jako výchozí hodnotu akceptuje buď objekty implementující rozhraní `DateTimeInterface`, řetězec s časem, nebo číslo představující UNIX timestamp. Z těchto vstupů je využita pouze časová informace, datum je ignorováno. Totéž platí pro argumenty pravidel `Min`, `Max` nebo `Range`, jež definují minimální a maximální povolený čas. Pokud je nastavená minimální hodnota vyšší než maximální, vytvoří se časový rozsah přesahující půlnoc.
+
+```php
+$form->addTime('time', 'Čas:', withSeconds: true)
+	->addRule($form::Range, 'Čas musí být v rozsahu od %d do %d.', ['12:30', '13:30']);
+```
+
+Standardně vrací objekt `DateTimeImmutable` (s datem 1. ledna roku 1), metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Čas:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Přidá políčko, které umožní uživateli snadno zadat datum a čas skládající se z roku, měsíce, dne, hodin, minut a volitelně i sekund (třída [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Jako výchozí hodnotu akceptuje buď objekty implementující rozhraní `DateTimeInterface`, řetězec s časem, nebo číslo představující UNIX timestamp. Totéž platí pro argumenty pravidel `Min`, `Max` nebo `Range`, jež definují minimální a maximální povolený datum.
+
+```php
+$form->addDateTime('datetime', 'Datum a čas:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'Datum musí být minimálně měsíc staré.', new DateTime('-1 month'));
+```
+
+Standardně vrací objekt `DateTimeImmutable`, metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] či timestamp:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Přidá políčko pro výběr barvy (třída [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Barva je řetězec ve tvaru `#rrggbb`. Pokud uživatel volbu neprovede, vrátí se černá barva `#000000`.
+
+```php
+$form->addColor('color', 'Barva:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Přidá skryté pole (třída [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Pomocí `setNullable()` lze nastavit, aby vracel `null` místo prázdného řetězce. Pozměnit odeslanou hodnotu umožňuje [addFilter()|validation#Úprava vstupu].
 
+Ačkoli je prvek skrytý, je **důležité si uvědomit**, že hodnota může být stále modifikována nebo podvržena útočníkem. Vždy důkladně ověřujte a validujte všechny přijaté hodnoty na serverové straně, aby se předešlo bezpečnostním rizikům spojeným s manipulací dat.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Zvýšit plat')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Přidá odesílací tlačítko v podobě obrázku (třída [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addIntege
 
 
 Vynechání hodnoty
------------------
+=================
 
 Pokud nás uživatelem vyplněná hodnota nezajímá, můžeme ji pomocí `setOmitted()` vynechat z výsledku metody `$form->getValues()` nebo z dat předávaných do handlerů. To se hodí pro různá hesla pro kontrolu, antispamové prvky atd.
 
@@ -390,7 +485,7 @@ $form->addPassword('passwordVerify', 'Heslo pro kontrolu:')
 
 
 Deaktivace prvků
-----------------
+================
 
 Prvky lze deaktivovat pomocí `setDisabled()`. Takový prvek nemůže uživatel editovat.
 
@@ -399,9 +494,9 @@ $form->addText('username', 'Uživatelské jméno:')
 	->setDisabled();
 ```
 
-Upozorňujeme, že disablované prvky prohlížeč vůbec neodesílá na server, tedy je ani nenajdete v datech vrácených funkcí `$form->getValues()`.
+Disablované prvky prohlížeč vůbec neodesílá na server, tedy je ani nenajdete v datech vrácených funkcí `$form->getValues()`. Pokud však nastavíte `setOmitted(false)`, Nette do těchto dat zahrne jejich výchozí hodnotu.
 
-Pokud prvku nastavujete výchozí hodnotu, je tak nutné učinit až po jeho deaktivaci:
+Při volání `setDisabled()` se z bezpečnostních důvodů **smaže hodnota prvku**. Pokud nastavujete výchozí hodnotu, je tak nutné učinit až po jeho deaktivaci:
 
 ```php
 $form->addText('username', 'Uživatelské jméno:')
@@ -409,6 +504,8 @@ $form->addText('username', 'Uživatelské jméno:')
 	->setDefaultValue($userName);
 ```
 
+Alternativou disablovaných prvků jsou prvky s HTML atributem `readonly`, které prohlížeč na server posílá. Ačkoliv je prvek pouze pro čtení, je **důležité si uvědomit**, že jeho hodnota může být stále modifikována nebo podvržena útočníkem.
+
 
 Vlastní prvky
 =============
@@ -428,8 +525,8 @@ Existuje způsob, jak definovat nové metody formuláře sloužící k přidáv
 ```php
 use Nette\Forms\Container;
 
-// přidáme metodu addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// přidáme metodu addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Alespoň 5 čísel', '[0-9]{5}');
 });
diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy
index f3174f1c0a..567aa346c6 100644
--- a/forms/cs/in-presenter.texy
+++ b/forms/cs/in-presenter.texy
@@ -30,7 +30,7 @@ Formulář v presenteru je objekt třídy `Nette\Application\UI\Form`, její př
 
 Z pohledu presenteru je formulář běžná komponenta. Proto se s ním jako s komponentou zachází a začleníme ji do presenteru pomocí [tovární metody |application:components#Tovární metody]. Bude to vypadat takto:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 A v šabloně formulář vykreslíme značkou `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registrace</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Formulář se vždy validuje na straně serveru, ale také se generuje JavaScrip
 Vložte jej do šablony layoutu:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Pokud se podíváte do zdrojového kódu stránky s formulářem, můžete si všimnout, že Nette povinné prvky vkládá do elementů s CSS třídou `required`. Zkuste přidat do šablony následující stylopis a popiska „Jméno“ bude červená. Elegantně tak uživatelům vyznačíme povinné prvky:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Od PHP 8.0 můžete použít tento elegantní zápis, který využívá konstruktor:
+Alternativně můžete využít konstruktor:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Property datové třídy mohou být také enumy a dojde k jejich automatickému namapování. .{data-version:3.2.4}
+
 Jak říci Nette, aby nám data vracel jako objekty této třídy? Snadněji než si myslíte. Stačí pouze třídu uvést jako typ parametru `$data` v obslužné metodě:
 
 ```php
@@ -294,6 +296,8 @@ Mapování pak z typu property `$person` pozná, že má kontejner mapovat na t
 $person->setMappedType(PersonFormData::class);
 ```
 
+Návrh datové třídy formuláře si můžete nechat vygenerovat pomocí metody `Nette\Forms\Blueprint::dataClass($form)`, která ji vypíše do stránky prohlížeče. Kód pak stačí kliknutím označit a zkopírovat do projektu. .{data-version:3.1.15}
+
 
 Více tlačítek
 =============
diff --git a/forms/cs/rendering.texy b/forms/cs/rendering.texy
index ec272f49fb..cbc7c450fe 100644
--- a/forms/cs/rendering.texy
+++ b/forms/cs/rendering.texy
@@ -11,6 +11,8 @@ Vykreslení pomocí Latte
 
 [Šablonovací sytém Latte|latte:] zásadně usnadňuje vykreslení formulářů a jejich prvků. Nejprve si ukážeme, jak formuláře vykreslovat ručně po jednotlivých prvcích a tím získat plnou kontrolu nad kódem. Později si ukážeme, jak lze takové vykreslování [zautomatizovat |#Automatické vykreslování].
 
+Návrh Latte šablony formuláře si můžete nechat vygenerovat pomocí metody `Nette\Forms\Blueprint::latte($form)`, která jej vypíše do stránky prohlížeče. Kód pak stačí kliknutím označit a zkopírovat do projektu. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Složitější formulářové prvky, jako je RadioList nebo CheckboxList, lze ta
 ```
 
 
-Návrh kódu `{formPrint}` .[#toc-formprint]
-------------------------------------------
-
-Podobný Latte kód pro formulář si můžete nechat vygenerovat pomocí značky `{formPrint}`. Pokud ji umístíte do šablony, místo běžného vykreslení se zobrazí návrh kódu. Ten pak stačí označit a zkopírovat do projektu.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Blok přitom stačí importovat na jediném místě a to na začátku šablony l
 Speciální případy
 -----------------
 
-Pokud potřebujete vykreslit jen vnitřní část formuláře bez HTML značek `<form>` & `</form>`, například při AJAXovém požadavku, můžete formulář otevří a uzavřít do `{formContext} … {/formContext}`. Funguje podobně jako `<form n:form>` či `{form}` v logickém smyslu, tady umožní používat ostatní značky pro kreslení prvků formuláře, ale přitom nic nevykreslí.
+Pokud potřebujete vykreslit jen vnitřní část formuláře bez HTML značek `<form>`, například při posílání snippetů, skryjte je pomocí atributu `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 S vykreslením prvků uvnitř formulářového kontejneru pomůže tag `{formContainer}`.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Renderer nejprve vykresluje skupiny a teprve poté prvky, které do žádné skupiny nepatří.
+
 
 Podpora pro Bootstrap
 ---------------------
@@ -444,7 +442,7 @@ Podpora pro Bootstrap
 HTML atributy
 =============
 
-Formulářovým prvkům můžeme nastavovat libovolné HTML atributy pomocí `setHtmlAttribute(string $name, $value = true)`:
+Pro nastavení libovolných HTML atributů formulářových prvků použijeme metodu `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Číslo:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Řazení dle:', ['ceny', 'názvu'])
 	->setHtmlAttribute('onchange', 'submit()'); // při změně odeslat
 
 
-// chceme-li to samé udělat pro <form>
+// Pro nastavení atributů samotného <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Nastavení typu:
+Specifikace typu prvku:
 
 ```php
 $form->addText('tel', 'Váš telefon:')
@@ -466,6 +464,9 @@ $form->addText('tel', 'Váš telefon:')
 	->setHtmlAttribute('placeholder', 'napište telefon');
 ```
 
+.[warning]
+Nastavení typu a dalších atributů slouží jen pro vizuální účely. Ověření správnosti vstupů musí probíhat na serveru, což zajístíte volbou vhodného [formulářového prvku|controls] a uvedením [validačních pravidel|validation].
+
 Jednotlivým položkám v radio nebo checkbox listech můžeme nastavit HTML atribut s rozdílnými hodnotami pro každou z nich.
 Povšimněte si dvojtečky za `style:`, která zajistí volbu hodnoty podle klíče:
 
@@ -484,10 +485,9 @@ Vypíše:
 <label><input type="checkbox" name="colors[]" value="b">modrá</label>
 ```
 
-Pokud jde o logický HTML atribut (který nemá hodnotu, např. `readonly`), můžeme použít zápis s otazníkem:
+Pro nastavení logických atributů, jako je `readonly`, můžeme použít zápis s otazníkem:
 
 ```php
-$colors = ['r' => 'červená', 'g' => 'zelená', 'b' => 'modrá'];
 $form->addCheckboxList('colors', 'Barvy:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // pro více klíču použijte pole, např. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ U prvků Checkbox, CheckboxList a RadioList můžete ovlivnit předlohu elementu
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
@@ -579,7 +576,7 @@ U [validačních pravidel|validation] se translatoru předávají i specifické
 
 ```php
 $form->addPassword('password', 'Heslo:')
-	->addCondition($form::MinLength, 'Heslo musí mít alespoň %d znaků', 8);
+	->addRule($form::MinLength, 'Heslo musí mít alespoň %d znaků', 8);
 ```
 
 se volá translator s těmito parametry:
diff --git a/forms/cs/standalone.texy b/forms/cs/standalone.texy
index 965c271724..624622a713 100644
--- a/forms/cs/standalone.texy
+++ b/forms/cs/standalone.texy
@@ -107,7 +107,7 @@ Formulář se vždy validuje na straně serveru, ale také se generuje JavaScrip
 Vložte jej do stránky:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Pokud se podíváte do zdrojového kódu stránky s formulářem, můžete si všimnout, že Nette povinné prvky vkládá do elementů s CSS třídou `required`. Zkuste přidat do šablony následující stylopis a popiska „Jméno“ bude červená. Elegantně tak uživatelům vyznačíme povinné prvky:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Od PHP 8.0 můžete použít tento elegantní zápis, který využívá konstruktor:
+Alternativně můžete využít konstruktor:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Property datové třídy mohou být také enumy a dojde k jejich automatickému namapování. .{data-version:3.2.4}
+
 Jak říci Nette, aby nám data vracel jako objekty této třídy? Snadněji než si myslíte. Stačí pouze název třídy nebo objekt k hydrataci uvést jako parametr:
 
 ```php
@@ -258,6 +260,8 @@ Mapování pak z typu property `$person` pozná, že má kontejner mapovat na t
 $person->setMappedType(PersonFormData::class);
 ```
 
+Návrh datové třídy formuláře si můžete nechat vygenerovat pomocí metody `Nette\Forms\Blueprint::dataClass($form)`, která ji vypíše do stránky prohlížeče. Kód pak stačí kliknutím označit a zkopírovat do projektu. .{data-version:3.1.15}
+
 
 Více tlačítek
 =============
diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy
index 39017bbaf4..b8ef19407e 100644
--- a/forms/cs/validation.texy
+++ b/forms/cs/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Heslo:')
 	->addRule($form::MinLength, 'Heslo musí mít alespoň %d znaků', 8);
 ```
 
-Nette přichází s celou řadu předdefinovaných pravidel, jejichž názvy jsou konstanty třídy `Nette\Forms\Form`.
+**Validační pravidla se ověřují pouze v případě, že uživatel prvek vyplnil.**
 
-U všech prvků můžeme použít tyto pravidla:
+Nette přichází s celou řadu předdefinovaných pravidel, jejichž názvy jsou konstanty třídy `Nette\Forms\Form`. U všech prvků můžeme použít tyto pravidla:
 
 | konstanta | popis | typ argumentu
 |-------
@@ -38,7 +38,11 @@ U všech prvků můžeme použít tyto pravidla:
 | `IsNotIn` | hodnota se nerovná žádné položce v poli | `array`
 | `Valid` | je prvek vyplněn správně? (pro [#podmínky]) | -
 
-U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` lze použít i následující pravidla:
+
+Textové vstupy
+--------------
+
+U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` lze použít i některá následující pravidla:
 
 | `MinLength` | minimální délka textu | `int`
 | `MaxLength` | maximální délka textu | `int`
@@ -57,9 +61,23 @@ U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addIntege
 Validační pravidla `Integer`, `Numeric` a `Float` rovnou převádí hodnotu na integer resp. float. A dále pravidlo `URL` akceptuje i adresu bez schématu (např. `nette.org`) a schéma doplní (`https://nette.org`).
 Výraz v `Pattern` a `PatternIcase` musí platit pro celou hodnotu, tj. jako by byl obalen znaky `^` a `$`.
 
+
+Počet položek
+-------------
+
+U prvků `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lze použít i následující pravidla pro omezení počtu vybraných položek resp. uploadovaných souborů:
+
+| `MinLength` | minimální počet  | `int`
+| `MaxLength` | maximální počet  | `int`
+| `Length` | počet v rozsahu nebo přesný počet | dvojice `[int, int]` nebo `int`
+
+
+Upload souborů
+--------------
+
 U prvků `addUpload()`, `addMultiUpload()` lze použít i následující pravidla:
 
-| `MaxFileSize` | maximální velikost souboru | `int`
+| `MaxFileSize` | maximální velikost souboru v bajtech | `int`
 | `MimeType` | MIME type, povoleny zástupné znaky (`'video/*'`) | `string\|string[]`
 | `Image` | obrázek JPEG, PNG, GIF, WebP, AVIF | -
 | `Pattern` | jméno souboru vyhovuje regulárnímu výrazu | `string`
@@ -67,15 +85,9 @@ U prvků `addUpload()`, `addMultiUpload()` lze použít i následující pravidl
 
 `MimeType` a `Image` vyžadují PHP rozšíření `fileinfo`. Že je soubor či obrázek požadovaného typu detekují na základě jeho signatury a **neověřují integritu celého souboru.** Zda není obrázek poškozený lze zjistit například pokusem o jeho [načtení|http:request#toImage].
 
-U prvků `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lze použít i následující pravidla pro omezení počtu vybraných položek resp. uploadovaných souborů:
-
-| `MinLength` | minimální počet  | `int`
-| `MaxLength` | maximální počet  | `int`
-| `Length` | počet v rozsahu nebo přesný počet | dvojice `[int, int]` nebo `int`
-
 
 Chybové hlášky
---------------
+==============
 
 Všechny předdefinované pravidla s výjimkou `Pattern` a `PatternInsensitive` mají výchozí chybovou hlášku, takže ji lze vynechat. Nicméně uvedením a formulací všech hlášek na míru uděláte formulář uživatelsky přívětivější.
 
@@ -140,18 +152,18 @@ $form->addText(/* ... */)
 		->addRule(/* ... */);
 ```
 
-V Nette lze velmi snadno reagovat na splnění či nesplnění podmíny i na straně JavaScriptu pomocí metody `toggle()`, viz [#dynamický JavaScript].
+V Nette lze velmi snadno reagovat na splnění či nesplnění podmínky i na straně JavaScriptu pomocí metody `toggle()`, viz [#dynamický JavaScript].
 
 
-Reference mezi prvky
-====================
+Reference na jiný prvek
+=======================
 
-Jako argument pravidla či podmínky lze uvádět referenci na jiný prvek. Takto lze např. dynamicky validovat, že prvek `text` má tolik znaků, jako je hodnota prvku `length`:
+Jako argument pravidla či podmínky lze předat i jiný prvek formuláře. Pravidlo potom použije hodnotu vloženou později uživatelem v prohlížeči. Takto lze např. dynamicky validovat, že prvek `password` obsahuje stejný řetězec jako prvek `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Heslo');
+$form->addPassword('password_confirm', 'Potvrďte heslo')
+    ->addRule($form::Equal, 'Zadaná hesla se neshodují', $form['password']);
 ```
 
 
@@ -160,7 +172,7 @@ Vlastní pravidla a podmínky
 
 Občas se dostaneme do situace, kdy nám vestavěná validační pravidla v Nette nestačí a potřebujeme data od uživatele validovat po svém. V Nette je to velmi jednoduché!
 
-Metodám `addRule()` či `addCondition()` lze první parametr předat libovolný callback. Ten přijímá jako první parametr samotný prvek a vrací boolean hodnotu určující, zda validace proběhla v pořádku. Při přidávání pravidla pomocí `addRule()` je možné zadat i další argumenty, ty jsou pak předány jako druhý parametr.
+Metodám `addRule()` či `addCondition()` lze jako první parametr předat libovolný callback. Ten přijímá jako první parametr samotný prvek a vrací boolean hodnotu určující, zda validace proběhla v pořádku. Při přidávání pravidla pomocí `addRule()` je možné zadat i další argumenty, ty jsou pak předány jako druhý parametr.
 
 Vlastní sadu validátorů tak můžeme vytvořit jako třídu se statickými metodami:
 
@@ -281,7 +293,7 @@ Tím skriptem je `netteForms.js` a je dostupný z více možných zdrojů:
 Skript můžete vložit přímo do HTML stránky ze CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Nebo zkopírovat lokálně do veřejné složky projektu (např. z `vendor/nette/forms/src/assets/netteForms.min.js`):
@@ -352,7 +364,7 @@ $details->addInteger('age')
 $details->addInteger('age2')
 	->setRequired('age2');
 
-$form->addSubmit('send1'); // Validuje celý formuláře
+$form->addSubmit('send1'); // Validuje celý formulář
 $form->addSubmit('send2')
 	->setValidationScope([]); // Nevaliduje vůbec
 $form->addSubmit('send3')
diff --git a/forms/de/controls.texy b/forms/de/controls.texy
index bc3e9ac752..f39891b8eb 100644
--- a/forms/de/controls.texy
+++ b/forms/de/controls.texy
@@ -5,8 +5,8 @@ Formular-Steuerelemente
 Übersicht über die eingebauten Formularsteuerelemente.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Fügt ein einzeiliges Textfeld hinzu (Klasse [TextInput |api:Nette\Forms\Controls\TextInput]). Wenn der Benutzer das Feld nicht ausfüllt, wird eine leere Zeichenkette `''` zurückgegeben, oder verwenden Sie `setNullable()`, um dies zu ändern und `null` zurückzugeben.
 
@@ -20,13 +20,10 @@ Es validiert automatisch UTF-8, schneidet linke und rechte Leerzeichen ab und en
 
 Die maximale Länge kann mit `setMaxLength()` begrenzt werden. Mit [addFilter() |validation#Modifying Input Values] können Sie den vom Benutzer eingegebenen Wert ändern.
 
-Verwenden Sie `setHtmlType()`, um das [Zeichen |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] des Eingabeelements in `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color` zu ändern. Anstelle der Typen `number` und `email` empfehlen wir die Verwendung von [addInteger |#addInteger] und [addEmail |#addEmail], die eine serverseitige Validierung ermöglichen.
+Sie können das visuelle Zeichen eines Textfeldes in Typen wie `search`, `tel` oder `url` ändern, indem Sie `setHtmlType()` verwenden, wie in der [Spezifikation |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] angegeben. Denken Sie daran, dass die Änderung des Typs nur visuell ist und keine Validierungsfunktionen ausführt. Für den Typ `url` ist es sinnvoll, eine spezielle [URL-Regel |validation#Text inputs] hinzuzufügen.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Für andere Eingabetypen wie `number`, `range`, `email`, `date`, `datetime-local`, `time` und `color` verwenden Sie spezielle Methoden wie [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] und [addColor |#addColor], die eine serverseitige Validierung gewährleisten. Die Typen `month` und `week` werden noch nicht von allen Browsern vollständig unterstützt.
 
 Für das Element kann der sogenannte empty-value gesetzt werden, der so etwas wie der Standardwert ist, aber, wenn der Benutzer ihn nicht überschreibt, einen leeren String oder `null` zurückgibt.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Fügt Eingabefeld für Ganzzahl (Klasse [TextInput |api:Nette\Forms\Controls\TextInput]) hinzu. Gibt entweder eine Ganzzahl oder `null` zurück, wenn der Benutzer nichts eingibt.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('Jahr', 'Jahr:')
+	->addRule($form::Range, 'Das Jahr muss im Bereich %d bis %d liegen.', [1900, 2023 |1900, 2023]);
+```
+
+Das Element wird wiedergegeben als `<input type="numeric">`. Mit der Methode `setHtmlType()` können Sie den Typ in `range` für die Anzeige als Schieberegler oder in `text` ändern, wenn Sie ein Standardtextfeld ohne das spezielle Verhalten von `numeric` bevorzugen.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('Ebene', 'Ebene:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'Das Niveau muss im Bereich %d bis %d liegen.', [0, 100 |0, 100]);
 ```
 
+Das Element wird wiedergegeben als `<input type="numeric">`. Mit der Methode `setHtmlType()` können Sie den Typ in `range` für die Anzeige als Schieberegler oder in `text` ändern, wenn Sie ein Standardtextfeld ohne das spezielle Verhalten von `numeric` bevorzugen.
+
+Nette und der Chrome-Browser akzeptieren sowohl ein Komma als auch einen Punkt als Dezimaltrennzeichen. Um diese Funktionalität in Firefox verfügbar zu machen, empfiehlt es sich, das Attribut `lang` entweder für das spezifische Element oder für die gesamte Seite zu setzen, zum Beispiel, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Fügt ein E-Mail-Adressfeld mit Gültigkeitsprüfung hinzu (Klasse [TextInput |api:Nette\Forms\Controls\TextInput]). Wenn der Benutzer das Feld nicht ausfüllt, wird eine leere Zeichenkette `''` zurückgegeben, oder verwenden Sie `setNullable()`, um dies zu ändern und `null` zurückzugeben.
 
@@ -78,8 +92,8 @@ $form->addEmail('email', 'Email:');
 Die maximale Länge kann mit `setMaxLength()` begrenzt werden. Mit [addFilter() |validation#Modifying Input Values] können Sie den vom Benutzer eingegebenen Wert ändern. Mit `setEmptyValue()` können Sie den sogenannten Leerwert setzen.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Fügt Passwortfeld hinzu (Klasse [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Fügt eine Liste von Kontrollkästchen zur Auswahl mehrerer Elemente hinzu (Klasse [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Gibt das Array der Schlüssel der ausgewählten Elemente zurück. Die Methode `getSelectedItems()` gibt Werte anstelle von Schlüsseln zurück.
 
@@ -125,9 +139,15 @@ Das Element überprüft automatisch, dass keine Fälschung vorliegt und dass die
 
 Wenn Standardwerte gesetzt werden, wird auch geprüft, ob sie zu den angebotenen Artikeln gehören, andernfalls wird eine Ausnahme geworfen. Diese Prüfung kann mit `checkDefaultValue(false)` ausgeschaltet werden.
 
+Wenn Sie ein Formular mit der Methode `GET` absenden, können Sie eine kompaktere Datenübertragungsmethode wählen, die die Größe des Abfrage-Strings einspart. Dies wird durch die Einstellung des HTML-Attributs des Formulars aktiviert:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Fügt Optionsfelder hinzu (Klasse [RadioList |api:Nette\Forms\Controls\RadioList]). Gibt den Schlüssel des ausgewählten Elements zurück, oder `null`, wenn der Benutzer nichts ausgewählt hat. Die Methode `getSelectedItem()` gibt einen Wert statt eines Schlüssels zurück.
 
@@ -148,8 +168,8 @@ Das Element überprüft automatisch, dass keine Fälschung vorliegt und dass das
 Wenn der Standardwert eingestellt ist, wird auch geprüft, ob es sich um einen der angebotenen Einträge handelt, andernfalls wird eine Ausnahme ausgelöst. Diese Prüfung kann mit `checkDefaultValue(false)` ausgeschaltet werden.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Fügt ein Auswahlfeld hinzu (Klasse [SelectBox |api:Nette\Forms\Controls\SelectBox]). Gibt den Schlüssel des ausgewählten Elements zurück, oder `null`, wenn der Benutzer nichts ausgewählt hat. Die Methode `getSelectedItem()` gibt einen Wert statt eines Schlüssels zurück.
 
@@ -193,8 +213,8 @@ Das Element prüft automatisch, dass keine Fälschung vorliegt und dass das ausg
 Wenn der Standardwert eingestellt ist, wird auch geprüft, ob es sich um einen der angebotenen Einträge handelt, andernfalls wird eine Ausnahme ausgelöst. Diese Prüfung kann mit `checkDefaultValue(false)` ausgeschaltet werden.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Fügt ein Auswahlfeld mit mehreren Auswahlmöglichkeiten hinzu (Klasse [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Gibt das Array der Schlüssel der ausgewählten Elemente zurück. Die Methode `getSelectedItems()` gibt Werte anstelle von Schlüsseln zurück.
 
@@ -246,8 +266,81 @@ Vertrauen Sie nicht auf die von der Methode `FileUpload::getName()` zurückgegeb
 Die Regeln `MimeType` und `Image` erkennen den gewünschten Typ einer Datei oder eines Bildes anhand ihrer Signatur. Die Integrität der gesamten Datei wird nicht geprüft. Sie können herausfinden, ob ein Bild nicht beschädigt ist, indem Sie beispielsweise versuchen, [es zu laden |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Fügt ein Feld hinzu, das es dem Benutzer ermöglicht, auf einfache Weise ein Datum bestehend aus Jahr, Monat und Tag einzugeben (Klasse [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Für den Standardwert akzeptiert es entweder Objekte, die `DateTimeInterface` implementieren, eine Zeichenkette mit der Uhrzeit oder eine Zahl, die einen UNIX-Zeitstempel darstellt. Dasselbe gilt für die Regelargumente `Min`, `Max` oder `Range`, die das minimal und maximal zulässige Datum festlegen.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Standardmäßig wird ein `DateTimeImmutable` Objekt zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] oder einen Zeitstempel angeben:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Fügt ein Feld hinzu, das dem Benutzer die einfache Eingabe der Zeit in Stunden, Minuten und optional Sekunden ermöglicht (Klasse [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Als Standardwert akzeptiert es entweder Objekte, die `DateTimeInterface` implementieren, einen String mit der Zeit oder eine Zahl, die einen UNIX-Zeitstempel darstellt. Es wird nur die Zeitinformation aus diesen Eingaben verwendet; das Datum wird ignoriert. Dasselbe gilt für die Regelargumente `Min`, `Max` oder `Range`, die die minimal und maximal zulässige Zeit festlegen. Wenn der Mindestwert höher ist als der Höchstwert, wird ein Zeitbereich bis Mitternacht erstellt.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Standardmäßig wird ein Objekt `DateTimeImmutable` (mit dem Datum des 1. Januar, Jahr 1) zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] angeben:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Fügt ein Feld hinzu, das es dem Benutzer ermöglicht, auf einfache Weise sowohl Datum als auch Uhrzeit einzugeben, bestehend aus Jahr, Monat, Tag, Stunden, Minuten und optional Sekunden (Klasse [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Als Standardwert akzeptiert es entweder Objekte, die `DateTimeInterface` implementieren, einen String mit der Zeit oder eine Zahl, die einen UNIX-Zeitstempel darstellt. Dasselbe gilt für die Regelargumente `Min`, `Max` oder `Range`, die das minimal und maximal zulässige Datum festlegen.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Standardmäßig wird ein `DateTimeImmutable` Objekt zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] oder einen Zeitstempel angeben:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Fügt ein Farbauswahlfeld (Klasse [ColorPicker |api:Nette\Forms\Controls\ColorPicker]) hinzu. Die Farbe ist ein String im Format `#rrggbb`. Wenn der Benutzer keine Auswahl trifft, wird als Standardfarbe Schwarz zurückgegeben `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Fügt ein verstecktes Feld (Klasse [HiddenField |api:Nette\Forms\Controls\HiddenField]) hinzu.
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Verwenden Sie `setNullable()`, um die Rückgabe von `null` anstelle eines leeren Strings zu ändern. Mit [addFilter() |validation#Modifying Input Values] können Sie den übergebenen Wert ändern.
 
+Obwohl das Element verborgen ist, ist es **wichtig zu wissen**, dass sein Wert immer noch von einem Angreifer geändert oder gefälscht werden kann. Überprüfen und validieren Sie immer alle empfangenen Werte auf der Serverseite gründlich, um Sicherheitsrisiken im Zusammenhang mit Datenmanipulationen zu vermeiden.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Fügt einen Submit-Button in Form eines Bildes hinzu (Klasse [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Die folgenden Methoden können für die Elemente `addText()`, `addPassword()`, `
 
 
 Ausgelassene Werte .[#toc-omitted-values]
------------------------------------------
+=========================================
 
 Wenn Sie an dem vom Benutzer eingegebenen Wert nicht interessiert sind, können wir `setOmitted()` verwenden, um ihn aus dem Ergebnis auszulassen, das von der Methode `$form->getValues​()` geliefert oder an Handler übergeben wird. Dies eignet sich für verschiedene Passwörter zur Überprüfung, Antispam-Felder usw.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Deaktivieren von Eingaben .[#toc-disabling-inputs]
---------------------------------------------------
+==================================================
 
-Um eine Eingabe zu deaktivieren, können Sie `setDisabled()` aufrufen. Ein solches Feld kann vom Benutzer nicht bearbeitet werden.
+Eingänge können mit `setDisabled()` deaktiviert werden. Ein deaktivierter Eingang kann vom Benutzer nicht bearbeitet werden.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Beachten Sie, dass der Browser die deaktivierten Felder gar nicht an den Server sendet, so dass Sie sie nicht einmal in den von der Funktion `$form->getValues()` zurückgegebenen Daten finden werden.
+Deaktivierte Eingaben werden vom Browser nicht an den Server gesendet, so dass sie in den von der Funktion `$form->getValues()` zurückgegebenen Daten nicht zu finden sind. Wenn Sie jedoch `setOmitted(false)` einstellen, wird Nette den Standardwert in diese Daten aufnehmen.
 
-Wenn Sie einen Standardwert für ein Feld festlegen, dürfen Sie dies erst tun, nachdem Sie das Feld deaktiviert haben:
+Wenn `setDisabled()` aufgerufen wird, wird **der Wert der Eingabe aus Sicherheitsgründen gelöscht**. Wenn Sie einen Standardwert setzen, müssen Sie dies nach seiner Deaktivierung tun:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Eine Alternative zu deaktivierten Eingaben sind Felder mit dem HTML-Attribut `readonly`, die vom Browser an den Server gesendet werden. Obwohl das Feld nur lesbar ist, ist es **wichtig zu wissen**, dass sein Wert trotzdem von einem Angreifer geändert oder gefälscht werden kann.
+
 
 Benutzerdefinierte Steuerelemente .[#toc-custom-controls]
 =========================================================
@@ -428,8 +525,8 @@ Es gibt eine Möglichkeit, neue Formularmethoden zu definieren, um benutzerdefin
 ```php
 use Nette\Forms\Container;
 
-// fügt Methode addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// fügt Methode addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Mindestens 5 Zahlen', '[0-9]{5}');
 });
diff --git a/forms/de/in-presenter.texy b/forms/de/in-presenter.texy
index 41f8158caf..87ee850cff 100644
--- a/forms/de/in-presenter.texy
+++ b/forms/de/in-presenter.texy
@@ -30,7 +30,7 @@ Das Formular im Presenter ist ein Objekt der Klasse `Nette\Application\UI\Form`,
 
 Aus der Sicht des Präsentators ist das Formular eine gemeinsame Komponente. Daher wird es als Komponente behandelt und mit der [Factory-Methode |application:components#Factory Methods] in den Presenter eingebunden. Das sieht dann wie folgt aus:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Und das Rendern in der Vorlage erfolgt mit dem Tag `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Das Formular wird immer serverseitig validiert, aber es wird auch eine JavaScrip
 Fügen Sie es in die Layout-Vorlage ein:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Wenn Sie in den Quellcode der Seite mit dem Formular schauen, werden Sie feststellen, dass Nette die erforderlichen Felder in Elemente mit einer CSS-Klasse `required` einfügt. Versuchen Sie, den folgenden Stil in die Vorlage einzufügen, und die Bezeichnung "Name" wird rot sein. Auf elegante Weise markieren wir die erforderlichen Felder für die Benutzer:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Ab PHP 8.0 können Sie diese elegante Notation verwenden, die einen Konstruktor benutzt:
+Alternativ können Sie auch den Konstruktor verwenden:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Eigenschaften der Datenklasse können auch Enums sein und werden automatisch zugeordnet. .{data-version:3.2.4}
+
 Wie sagt man Nette, dass es Daten als Objekte dieser Klasse zurückgeben soll? Einfacher als Sie denken. Alles, was Sie tun müssen, ist, die Klasse als Typ des `$data` Parameters im Handler anzugeben:
 
 ```php
@@ -294,6 +296,8 @@ Das Mapping weiß dann anhand des Eigenschaftstyps `$person`, dass es den Contai
 $person->setMappedType(PersonFormData::class);
 ```
 
+Mit der Methode `Nette\Forms\Blueprint::dataClass($form)` können Sie einen Vorschlag für die Datenklasse eines Formulars erzeugen, der auf der Browserseite ausgedruckt wird. Sie können dann einfach auf den Code klicken, um ihn auszuwählen und in Ihr Projekt zu kopieren. .{data-version:3.1.15}
+
 
 Mehrere Submit-Buttons .[#toc-multiple-submit-buttons]
 ======================================================
diff --git a/forms/de/rendering.texy b/forms/de/rendering.texy
index ca24a4ae2f..99142cfb7e 100644
--- a/forms/de/rendering.texy
+++ b/forms/de/rendering.texy
@@ -11,6 +11,8 @@ Rendering mit Latte .[#toc-rendering-with-latte]
 
 Das [Latte-Templating-System |latte:] erleichtert das Rendern von Formularen und ihren Elementen grundlegend. Wir werden zunächst zeigen, wie man Formulare manuell, Element für Element, rendern kann, um die volle Kontrolle über den Code zu erhalten. Später werden wir zeigen, wie man dieses Rendering [automatisieren |#Automatic rendering] kann.
 
+Mit der Methode `Nette\Forms\Blueprint::latte($form)` können Sie sich den Vorschlag einer Lattenvorlage für das Formular generieren lassen, der dann auf der Browser-Seite ausgegeben wird. Dann brauchen Sie den Code nur noch mit einem Klick auszuwählen und in Ihr Projekt zu kopieren. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Komplexere Formularelemente, wie z. B. RadioList oder CheckboxList, können Elem
 ```
 
 
-Code-Vorschlag `{formPrint}` .[#toc-formprint]
-----------------------------------------------
-
-Sie können einen ähnlichen Latte-Code für ein Formular mit dem Tag `{formPrint}` erzeugen. Wenn Sie ihn in eine Vorlage einfügen, sehen Sie den Code-Entwurf anstelle des normalen Renderings. Wählen Sie ihn dann einfach aus und kopieren Sie ihn in Ihr Projekt.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Sie brauchen den Block nur noch an einer Stelle zu importieren, nämlich am Anfa
 Besondere Fälle .[#toc-special-cases]
 -------------------------------------
 
-Wenn Sie nur den inneren Inhalt eines Formulars darstellen müssen, ohne `<form>` & `</form>` HTML-Tags, z. B. in einer AJAX-Anfrage, können Sie das Formular mit `{formContext} … {/formContext}` öffnen und schließen. Es funktioniert im logischen Sinne ähnlich wie `{form}`, hier erlaubt es Ihnen, andere Tags zu verwenden, um Formularelemente zu zeichnen, aber gleichzeitig zeichnet es nichts.
+Wenn Sie nur den inneren Teil des Formulars ohne HTML-Tags darstellen wollen `<form>`darstellen wollen, z. B. beim Senden von Snippets, blenden Sie diese mit dem Attribut `n:tag-if` aus:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Das Tag `formContainer` hilft beim Rendern von Eingaben innerhalb eines Formular-Containers.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Der Renderer zeichnet zuerst die Gruppen und dann die Elemente, die zu keiner Gruppe gehören.
+
 
 Bootstrap-Unterstützung .[#toc-bootstrap-support]
 -------------------------------------------------
@@ -444,7 +442,7 @@ Sie können [Beispiele |https://github.com/nette/forms/tree/master/examples] fü
 HTML-Attribute .[#toc-html-attributes]
 ======================================
 
-Mit `setHtmlAttribute(string $name, $value = true)` können Sie beliebige HTML-Attribute für Formularsteuerelemente festlegen:
+Um beliebige HTML-Attribute für Formularelemente zu setzen, verwenden Sie die Methode `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Zahl:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Sortieren nach:', ['Preis', 'Name'])
 	->setHtmlAttribute('onchange', 'submit()'); // ruft JS-Funktion submit() bei Änderung auf
 
 
-// Anwendung auf <form>
+// Zum Festlegen von Attributen der <form> selbst
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Einstellung des Eingabetyps:
+Angabe der Art des Elements:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-Wir können HTML-Attribute für einzelne Elemente in Radio- oder Checkbox-Listen mit unterschiedlichen Werten für jedes dieser Elemente festlegen.
-Beachten Sie den Doppelpunkt nach `style:`, um sicherzustellen, dass der Wert nach Schlüssel ausgewählt wird:
+.[warning]
+Das Setzen des Typs und anderer Attribute dient nur der visuellen Darstellung. Die Überprüfung der Korrektheit der Eingabe muss auf dem Server erfolgen, was Sie durch die Wahl eines geeigneten [Formularsteuerelements | controls] und die Festlegung von [Validierungsregeln | validation] sicherstellen können.
+
+Für einzelne Elemente in Radio- oder Checkbox-Listen können wir ein HTML-Attribut mit unterschiedlichen Werten für jedes dieser Elemente setzen.
+Beachten Sie den Doppelpunkt nach `style:`, der sicherstellt, dass der Wert anhand des Schlüssels ausgewählt wird:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Für ein logisches HTML-Attribut (das keinen Wert hat, wie `readonly`) können Sie ein Fragezeichen verwenden:
+Für das Setzen von booleschen Attributen, wie z. B. `readonly`, können wir die Notation mit einem Fragezeichen verwenden:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // use array for multiple keys, e.g. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ Für Checkbox-, CheckboxList- und RadioList-Elemente können Sie die Elementvorl
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/de/standalone.texy b/forms/de/standalone.texy
index a0574fe054..4ad0a3b358 100644
--- a/forms/de/standalone.texy
+++ b/forms/de/standalone.texy
@@ -107,7 +107,7 @@ Das Formular wird immer serverseitig validiert, aber es wird auch eine JavaScrip
 Fügen Sie es in die Seite ein:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Wenn Sie sich den Quellcode der Seite mit dem Formular ansehen, werden Sie feststellen, dass Nette die erforderlichen Felder in Elemente mit einer CSS-Klasse `required` einfügt. Versuchen Sie, der Vorlage den folgenden Stil hinzuzufügen, und die Bezeichnung "Name" wird rot sein. Auf elegante Weise markieren wir die erforderlichen Felder für die Benutzer:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Ab PHP 8.0 können Sie diese elegante Notation verwenden, die einen Konstruktor benutzt:
+Alternativ können Sie auch den Konstruktor verwenden:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Eigenschaften der Datenklasse können auch Enums sein und werden automatisch zugeordnet. .{data-version:3.2.4}
+
 Wie kann man Nette anweisen, Daten als Objekte dieser Klasse zurückzugeben? Einfacher als Sie denken. Alles, was Sie tun müssen, ist, den Namen der Klasse oder des zu hydrierenden Objekts als Parameter anzugeben:
 
 ```php
@@ -258,6 +260,8 @@ Das Mapping weiß dann anhand des Eigenschaftstyps `$person`, dass es den Contai
 $person->setMappedType(PersonFormData::class);
 ```
 
+Mit der Methode `Nette\Forms\Blueprint::dataClass($form)` können Sie einen Vorschlag für die Datenklasse eines Formulars erzeugen, der auf der Browserseite ausgedruckt wird. Sie können dann einfach auf den Code klicken, um ihn auszuwählen und in Ihr Projekt zu kopieren. .{data-version:3.1.15}
+
 
 Mehrere Submit-Buttons .[#toc-multiple-submit-buttons]
 ======================================================
diff --git a/forms/de/validation.texy b/forms/de/validation.texy
index 29dd24e760..0abbb2c140 100644
--- a/forms/de/validation.texy
+++ b/forms/de/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette verfügt über eine Reihe von eingebauten Regeln, deren Namen Konstanten der Klasse `Nette\Forms\Form` sind:
+**Validierungsregeln werden nur dann überprüft, wenn der Benutzer das Element ausgefüllt hat.**
 
-Wir können die folgenden Regeln für alle Steuerelemente verwenden:
+Nette verfügt über eine Reihe von vordefinierten Regeln, deren Namen Konstanten der Klasse `Nette\Forms\Form` sind. Wir können diese Regeln auf alle Elemente anwenden:
 
 | Konstante | Beschreibung | Argumente
 |-------
@@ -38,7 +38,11 @@ Wir können die folgenden Regeln für alle Steuerelemente verwenden:
 | `IsNotIn` | Wert ist nicht gleich einem Element im Array | `array`
 | `Valid` | Eingabe besteht Validierung (für [Bedingungen |#conditions]) | -
 
-Für die Steuerelemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` können auch die folgenden Regeln verwendet werden:
+
+Texteingaben .[#toc-text-inputs]
+--------------------------------
+
+Für die Elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` können auch einige der folgenden Regeln angewendet werden:
 
 | `MinLength` | minimale Stringlänge | `int`
 | `MaxLength` | maximale Länge der Zeichenkette | `int`
@@ -57,9 +61,23 @@ Für die Steuerelemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail
 Die Regeln `Integer`, `Numeric` und `Float` konvertieren den Wert automatisch in Ganzzahl (bzw. Gleitkommazahl). Außerdem akzeptiert die Regel `URL` auch eine Adresse ohne Schema (z. B. `nette.org`) und vervollständigt das Schema (`https://nette.org`).
 Die Ausdrücke in `Pattern` und `PatternInsensitive` müssen für den gesamten Wert gültig sein, d. h. so, als ob er in die Zeichen `^` and `$` eingeschlossen wäre.
 
+
+Anzahl der Artikel .[#toc-number-of-items]
+------------------------------------------
+
+Für die Elemente `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` können Sie auch die folgenden Regeln verwenden, um die Anzahl der ausgewählten Elemente oder hochgeladenen Dateien zu begrenzen:
+
+| `MinLength` | Mindestanzahl | `int`
+| `MaxLength` | maximale Anzahl | `int`
+| `Length` | Anzahl im Bereich oder genaue Anzahl | Paare `[int, int]` oder `int`
+
+
+Datei hochladen
+---------------
+
 Für die Steuerelemente `addUpload()`, `addMultiUpload()` können auch die folgenden Regeln verwendet werden:
 
-| `MaxFileSize` | maximale Dateigröße | `int`
+| `MaxFileSize` | Maximale Dateigröße in Bytes | `int`
 | `MimeType` | MIME-Typ, akzeptiert Wildcards (`'video/*'`) | `string\|string[]`
 | `Image` | hochgeladene Datei ist JPEG, PNG, GIF, WebP | -
 | `Pattern` | Dateiname entspricht regulärem Ausdruck | `string`
@@ -67,15 +85,9 @@ Für die Steuerelemente `addUpload()`, `addMultiUpload()` können auch die folge
 
 Für `MimeType` und `Image` ist die PHP-Erweiterung `fileinfo` erforderlich. Ob eine Datei oder ein Bild dem erforderlichen Typ entspricht, wird anhand ihrer Signatur erkannt. Die Integrität der gesamten Datei wird nicht geprüft. Sie können herausfinden, ob ein Bild nicht beschädigt ist, indem Sie beispielsweise versuchen, [es zu laden |http:request#toImage].
 
-Für die Steuerelemente `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` können auch die folgenden Regeln verwendet werden, um die Anzahl der ausgewählten Elemente bzw. hochgeladenen Dateien zu begrenzen:
-
-| `MinLength` | minimale Anzahl | `int`
-| `MaxLength` | maximale Anzahl | `int`
-| `Length` | Anzahl im Bereich oder genaue Anzahl | Paar `[int, int]` oder `int`
-
 
 Fehlermeldungen .[#toc-error-messages]
---------------------------------------
+======================================
 
 Alle vordefinierten Regeln außer `Pattern` und `PatternInsensitive` haben eine Standard-Fehlermeldung, so dass sie weggelassen werden können. Wenn Sie jedoch alle benutzerdefinierten Meldungen übergeben und formulieren, wird das Formular benutzerfreundlicher.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 In Nette ist es sehr einfach, auf die Erfüllung oder Nichterfüllung einer Bedingung auf der JavaScript-Seite mit der Methode `toggle()` zu reagieren, siehe [Dynamisches JavaScript |#Dynamic JavaScript].
 
 
-Referenzen zwischen Controls .[#toc-references-between-controls]
-================================================================
+Verweis auf ein anderes Element .[#toc-reference-to-another-element]
+====================================================================
 
-Das Regel- oder Bedingungsargument kann ein Verweis auf ein anderes Element sein. Sie können zum Beispiel dynamisch überprüfen, ob `text` so viele Zeichen hat wie der Wert des Feldes `length` beträgt:
+Als Argument für eine Regel oder Bedingung können Sie auch ein anderes Formularelement übergeben. Die Regel wird dann den Wert verwenden, den der Benutzer später im Browser eingibt. Auf diese Weise kann z. B. dynamisch überprüft werden, ob das Element `password` dieselbe Zeichenfolge enthält wie das Element `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Dieses Skript ist `netteForms.js`, das von mehreren möglichen Quellen erhältli
 Sie können das Skript direkt in die HTML-Seite aus dem CDN einbetten:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Oder kopieren Sie es lokal in den öffentlichen Ordner des Projekts (z. B. von `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/el/controls.texy b/forms/el/controls.texy
index 978a60c42e..a211f8acfc 100644
--- a/forms/el/controls.texy
+++ b/forms/el/controls.texy
@@ -5,8 +5,8 @@
 Επισκόπηση των ενσωματωμένων στοιχείων ελέγχου φόρμας.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Προσθέτει πεδίο κειμένου μονής γραμμής (κλάση [TextInput |api:Nette\Forms\Controls\TextInput]). Αν ο χρήστης δεν συμπληρώσει το πεδίο, επιστρέφει ένα κενό αλφαριθμητικό `''`, ή χρησιμοποιεί το `setNullable()` για να το αλλάξει και να επιστρέφει `null`.
 
@@ -20,13 +20,10 @@ $form->addText('name', 'Name:')
 
 Το μέγιστο μήκος μπορεί να περιοριστεί χρησιμοποιώντας το `setMaxLength()`. Η [addFilter() |validation#Modifying Input Values] σας επιτρέπει να αλλάξετε την τιμή που εισάγει ο χρήστης.
 
-Χρησιμοποιήστε το `setHtmlType()` για να αλλάξετε τον [χαρακτήρα |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] του στοιχείου εισόδου σε `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Αντί των τύπων `number` και `email`, συνιστούμε τη χρήση των τύπων [addInteger |#addInteger] και [addEmail |#addEmail], οι οποίοι παρέχουν επικύρωση από την πλευρά του διακομιστή.
+Μπορείτε να αλλάξετε τον οπτικό χαρακτήρα ενός πεδίου κειμένου σε τύπους όπως `search`, `tel` ή `url` χρησιμοποιώντας το `setHtmlType()`, όπως φαίνεται στις [προδιαγραφές |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Να θυμάστε ότι η αλλαγή του τύπου είναι μόνο οπτική και δεν εκτελεί λειτουργίες επικύρωσης. Για τον τύπο `url`, είναι σκόπιμο να προσθέσετε έναν ειδικό [κανόνα URL |validation#Text inputs].
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Για άλλους τύπους εισόδου, όπως `number`, `range`, `email`, `date`, `datetime-local`, `time` και `color`, χρησιμοποιήστε εξειδικευμένες μεθόδους όπως [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] και [addColor |#addColor], οι οποίες εξασφαλίζουν επικύρωση από την πλευρά του διακομιστή. Οι τύποι `month` και `week` δεν υποστηρίζονται ακόμη πλήρως από όλους τους φυλλομετρητές.
 
 Για το στοιχείο μπορεί να οριστεί η λεγόμενη κενή τιμή (empty-value), η οποία είναι κάτι σαν την προεπιλεγμένη τιμή, αλλά αν ο χρήστης δεν την αντικαταστήσει, επιστρέφει κενή συμβολοσειρά ή `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Προσθέτει πεδίο εισόδου για ακέραιο αριθμό (κλάση [TextInput |api:Nette\Forms\Controls\TextInput]). Επιστρέφει είτε έναν ακέραιο είτε το `null` εάν ο χρήστης δεν εισάγει τίποτα.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'Το έτος πρέπει να βρίσκεται στο εύρος %d έως %d.', [1900, 2023 |1900, 2023]),
+```
+
+Το στοιχείο αποδίδεται ως `<input type="numeric">`. Χρησιμοποιώντας τη μέθοδο `setHtmlType()`, μπορείτε να αλλάξετε τον τύπο σε `range` για εμφάνιση ως ολισθητής ή σε `text` αν προτιμάτε ένα τυπικό πεδίο κειμένου χωρίς την ειδική συμπεριφορά του `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'Το επίπεδο πρέπει να είναι στο εύρος %d έως %d.', [0, 100 |0, 100]),
 ```
 
+Το στοιχείο αποδίδεται ως `<input type="numeric">`. Χρησιμοποιώντας τη μέθοδο `setHtmlType()`, μπορείτε να αλλάξετε τον τύπο σε `range` για εμφάνιση ως ολισθητής ή σε `text` αν προτιμάτε ένα τυπικό πεδίο κειμένου χωρίς την ειδική συμπεριφορά του `numeric`.
+
+Η Nette και το πρόγραμμα περιήγησης Chrome δέχονται τόσο ένα κόμμα όσο και μια τελεία ως δεκαδικά διαχωριστικά. Για να είναι διαθέσιμη αυτή η λειτουργικότητα στον Firefox, συνιστάται να ορίσετε το χαρακτηριστικό `lang` είτε για το συγκεκριμένο στοιχείο είτε για ολόκληρη τη σελίδα, για παράδειγμα, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Προσθέτει πεδίο διεύθυνσης ηλεκτρονικού ταχυδρομείου με έλεγχο εγκυρότητας (κλάση [TextInput |api:Nette\Forms\Controls\TextInput]). Αν ο χρήστης δεν συμπληρώσει το πεδίο, επιστρέφει ένα κενό αλφαριθμητικό `''`, ή χρησιμοποιεί το `setNullable()` για να το αλλάξει και να επιστρέφει `null`.
 
@@ -78,8 +92,8 @@ $form->addEmail('email', 'Email:');
 Το μέγιστο μήκος μπορεί να περιοριστεί με τη χρήση του `setMaxLength()`. Η [addFilter() |validation#Modifying Input Values] σας επιτρέπει να αλλάξετε την τιμή που εισάγει ο χρήστης. Μπορείτε να ορίσετε τη λεγόμενη κενή τιμή χρησιμοποιώντας το `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Προσθέτει πεδίο κωδικού πρόσβασης (κλάση [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Προσθέτει λίστα με πλαίσια ελέγχου για την επιλογή πολλαπλών στοιχείων (κλάση [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Επιστρέφει τον πίνακα με τα κλειδιά των επιλεγμένων στοιχείων. Η μέθοδος `getSelectedItems()` επιστρέφει τιμές αντί για κλειδιά.
 
@@ -125,9 +139,15 @@ $form->addCheckboxList('colors', 'Colors:', [
 
 Όταν ορίζονται προεπιλεγμένες τιμές, ελέγχει επίσης ότι είναι ένα από τα προσφερόμενα στοιχεία, διαφορετικά πετάει μια εξαίρεση. Αυτός ο έλεγχος μπορεί να απενεργοποιηθεί με τη μέθοδο `checkDefaultValue(false)`.
 
+Εάν υποβάλετε μια φόρμα χρησιμοποιώντας τη μέθοδο `GET`, μπορείτε να επιλέξετε μια πιο συμπαγή μέθοδο μεταφοράς δεδομένων που εξοικονομεί το μέγεθος της συμβολοσειράς ερωτημάτων. Αυτό ενεργοποιείται με τη ρύθμιση του χαρακτηριστικού HTML της φόρμας:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Προσθέτει κουμπιά επιλογής (κλάση [RadioList |api:Nette\Forms\Controls\RadioList]). Επιστρέφει το κλειδί του επιλεγμένου στοιχείου ή `null` αν ο χρήστης δεν επέλεξε τίποτα. Η μέθοδος `getSelectedItem()` επιστρέφει μια τιμή αντί για ένα κλειδί.
 
@@ -148,8 +168,8 @@ $form->addRadioList('gender', 'Gender:', $sex);
 Όταν έχει οριστεί η προεπιλεγμένη τιμή, ελέγχει επίσης ότι είναι ένα από τα προσφερόμενα στοιχεία, διαφορετικά πετάει μια εξαίρεση. Αυτός ο έλεγχος μπορεί να απενεργοποιηθεί με τη μέθοδο `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Προσθέτει πλαίσιο επιλογής (κλάση [SelectBox |api:Nette\Forms\Controls\SelectBox]). Επιστρέφει το κλειδί του επιλεγμένου στοιχείου ή `null` αν ο χρήστης δεν επέλεξε τίποτα. Η μέθοδος `getSelectedItem()` επιστρέφει μια τιμή αντί για ένα κλειδί.
 
@@ -193,8 +213,8 @@ $form->addSelect('country', 'Country:', $countries)
 Όταν έχει οριστεί η προεπιλεγμένη τιμή, ελέγχει επίσης ότι είναι ένα από τα προσφερόμενα στοιχεία, διαφορετικά πετάει μια εξαίρεση. Αυτός ο έλεγχος μπορεί να απενεργοποιηθεί με τη μέθοδο `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Προσθέτει πλαίσιο επιλογής πολλαπλών επιλογών (κλάση [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Επιστρέφει τον πίνακα των κλειδιών των επιλεγμένων στοιχείων. Η μέθοδος `getSelectedItems()` επιστρέφει τιμές αντί για κλειδιά.
 
@@ -246,8 +266,81 @@ $form->addMultiUpload('files', 'Files:')
 Οι κανόνες `MimeType` και `Image` ανιχνεύουν τον απαιτούμενο τύπο αρχείου ή εικόνας από την υπογραφή του. Η ακεραιότητα ολόκληρου του αρχείου δεν ελέγχεται. Μπορείτε να διαπιστώσετε αν μια εικόνα δεν είναι κατεστραμμένη, για παράδειγμα, προσπαθώντας να [τη φορτώσετε |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Προσθέτει ένα πεδίο που επιτρέπει στο χρήστη να εισάγει εύκολα μια ημερομηνία που αποτελείται από έτος, μήνα και ημέρα (κλάση [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Για την προεπιλεγμένη τιμή, δέχεται είτε αντικείμενα που υλοποιούν το `DateTimeInterface`, ένα αλφαριθμητικό με την ώρα, είτε έναν αριθμό που αντιπροσωπεύει ένα UNIX timestamp. Το ίδιο ισχύει και για τα ορίσματα των κανόνων `Min`, `Max` ή `Range`, τα οποία καθορίζουν την ελάχιστη και τη μέγιστη επιτρεπόμενη ημερομηνία.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable`. Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ή μια χρονοσφραγίδα:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Προσθέτει ένα πεδίο που επιτρέπει στο χρήστη να εισάγει εύκολα την ώρα που αποτελείται από ώρες, λεπτά και προαιρετικά δευτερόλεπτα (κλάση [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Για την προεπιλεγμένη τιμή, δέχεται είτε αντικείμενα που υλοποιούν το `DateTimeInterface`, ένα αλφαριθμητικό με την ώρα, είτε έναν αριθμό που αντιπροσωπεύει μια χρονοσφραγίδα UNIX. Χρησιμοποιείται μόνο η πληροφορία της ώρας από αυτές τις εισόδους- η ημερομηνία αγνοείται. Το ίδιο ισχύει και για τα ορίσματα των κανόνων `Min`, `Max` ή `Range`, τα οποία καθορίζουν τον ελάχιστο και μέγιστο επιτρεπόμενο χρόνο. Εάν η ελάχιστη τιμή που έχει οριστεί είναι μεγαλύτερη από τη μέγιστη, δημιουργείται ένα χρονικό εύρος που εκτείνεται μέχρι τα μεσάνυχτα.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable` (με ημερομηνία 1 Ιανουαρίου, έτος 1). Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Προσθέτει ένα πεδίο που επιτρέπει στο χρήστη να εισάγει εύκολα τόσο ημερομηνία όσο και ώρα που αποτελείται από έτος, μήνα, ημέρα, ώρες, λεπτά και προαιρετικά δευτερόλεπτα (κλάση [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Για την προεπιλεγμένη τιμή, δέχεται είτε αντικείμενα που υλοποιούν το `DateTimeInterface`, ένα αλφαριθμητικό με την ώρα, είτε έναν αριθμό που αντιπροσωπεύει ένα UNIX timestamp. Το ίδιο ισχύει και για τα ορίσματα των κανόνων `Min`, `Max` ή `Range`, τα οποία καθορίζουν την ελάχιστη και τη μέγιστη επιτρεπόμενη ημερομηνία.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable`. Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ή μια χρονοσφραγίδα:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Προσθέτει ένα πεδίο επιλογής χρώματος (κλάση [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Το χρώμα είναι μια συμβολοσειρά στη μορφή `#rrggbb`. Εάν ο χρήστης δεν κάνει επιλογή, το προεπιλεγμένο χρώμα που επιστρέφεται είναι το μαύρο `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Προσθέτει κρυφό πεδίο (κλάση [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Χρησιμοποιήστε το `setNullable()` για να το αλλάξετε ώστε να επιστρέφει `null` αντί για κενό αλφαριθμητικό. Η [addFilter() |validation#Modifying Input Values] σας επιτρέπει να αλλάξετε την υποβαλλόμενη τιμή.
 
+Παρόλο που το στοιχείο είναι κρυφό, είναι **σημαντικό να συνειδητοποιήσετε** ότι η τιμή του μπορεί να τροποποιηθεί ή να παραποιηθεί από έναν επιτιθέμενο. Πάντα να επαληθεύετε και να επικυρώνετε διεξοδικά όλες τις λαμβανόμενες τιμές στην πλευρά του διακομιστή για να αποφύγετε τους κινδύνους ασφαλείας που σχετίζονται με τη χειραγώγηση των δεδομένων.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Προσθέτει κουμπί υποβολής με τη μορφή εικόνας (κλάση [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ $sub2->addEmail('email', 'Email:');
 
 
 Παραλειφθείσες τιμές .[#toc-omitted-values]
--------------------------------------------
+===========================================
 
 Αν δεν σας ενδιαφέρει η τιμή που εισάγει ο χρήστης, μπορούμε να χρησιμοποιήσουμε το `setOmitted()` για να την παραλείψουμε από το αποτέλεσμα που παρέχεται από τη μέθοδο `$form->getValues​()` ή που περνάει στους χειριστές. Αυτό είναι κατάλληλο για διάφορους κωδικούς πρόσβασης για επαλήθευση, πεδία antispam κ.λπ.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Απενεργοποίηση εισόδων .[#toc-disabling-inputs]
------------------------------------------------
+===============================================
 
-Για να απενεργοποιήσετε μια είσοδο, μπορείτε να καλέσετε το `setDisabled()`. Ένα τέτοιο πεδίο δεν μπορεί να επεξεργαστεί από τον χρήστη.
+Οι είσοδοι μπορούν να απενεργοποιηθούν χρησιμοποιώντας το `setDisabled()`. Ο χρήστης δεν μπορεί να επεξεργαστεί μια απενεργοποιημένη είσοδο.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Σημειώστε ότι το πρόγραμμα περιήγησης δεν στέλνει καθόλου τα απενεργοποιημένα πεδία στο διακομιστή, οπότε δεν θα τα βρείτε καν στα δεδομένα που επιστρέφει η συνάρτηση `$form->getValues()`.
+Οι απενεργοποιημένες είσοδοι δεν αποστέλλονται στον διακομιστή από το πρόγραμμα περιήγησης, επομένως δεν θα τις βρείτε στα δεδομένα που επιστρέφονται από τη λειτουργία `$form->getValues()`. Ωστόσο, αν ορίσετε το `setOmitted(false)`, η Nette θα συμπεριλάβει την προεπιλεγμένη τιμή τους σε αυτά τα δεδομένα.
 
-Εάν ορίζετε μια προεπιλεγμένη τιμή για ένα πεδίο, πρέπει να το κάνετε μόνο αφού το απενεργοποιήσετε:
+Όταν καλείται η `setDisabled()`, **η τιμή της εισόδου διαγράφεται** για λόγους ασφαλείας. Εάν ορίζετε μια προεπιλεγμένη τιμή, είναι απαραίτητο να το κάνετε μετά την απενεργοποίησή της:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Μια εναλλακτική λύση για τις απενεργοποιημένες εισόδους είναι τα πεδία με το χαρακτηριστικό HTML `readonly`, τα οποία αποστέλλονται στον διακομιστή από το πρόγραμμα περιήγησης. Αν και το πεδίο είναι μόνο αναγνώσιμο, είναι **σημαντικό να συνειδητοποιήσετε** ότι η τιμή του μπορεί να τροποποιηθεί ή να παραποιηθεί από έναν εισβολέα.
+
 
 Προσαρμοσμένα στοιχεία ελέγχου .[#toc-custom-controls]
 ======================================================
@@ -428,8 +525,8 @@ $form->addComponent(new DateInput('Date:'), 'date');
 ```php
 use Nette\Forms\Container;
 
-// προσθέτει τη μέθοδο addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// προσθέτει τη μέθοδο addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/el/in-presenter.texy b/forms/el/in-presenter.texy
index 9221cee979..8631b73369 100644
--- a/forms/el/in-presenter.texy
+++ b/forms/el/in-presenter.texy
@@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded'];
 
 Από τη σκοπιά του παρουσιαστή, η φόρμα είναι ένα κοινό συστατικό. Ως εκ τούτου, αντιμετωπίζεται ως συστατικό και ενσωματώνεται στον παρουσιαστή χρησιμοποιώντας τη [μέθοδο factory |application:components#Factory Methods]. Αυτό θα έχει την εξής μορφή:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Και η απόδοση στο πρότυπο γίνεται με τη χρήση της ετικέτας `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ $form->addText('name', 'Name:')
 Εισάγεται στο πρότυπο διάταξης:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Αν κοιτάξετε στον πηγαίο κώδικα της σελίδας με τη φόρμα, μπορεί να παρατηρήσετε ότι η Nette εισάγει τα απαιτούμενα πεδία σε στοιχεία με κλάση CSS `required`. Δοκιμάστε να προσθέσετε το ακόλουθο στυλ στο πρότυπο, και η ετικέτα "Όνομα" θα είναι κόκκινη. Κομψά, επισημαίνουμε τα υποχρεωτικά πεδία για τους χρήστες:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Από την PHP 8.0, μπορείτε να χρησιμοποιήσετε αυτόν τον κομψό συμβολισμό που χρησιμοποιεί έναν κατασκευαστή:
+Εναλλακτικά, μπορείτε να χρησιμοποιήσετε τον κατασκευαστή:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Οι ιδιότητες της κλάσης δεδομένων μπορούν επίσης να είναι enums και θα αντιστοιχιστούν αυτόματα. .{data-version:3.2.4}
+
 Πώς μπορείτε να πείτε στη Nette να επιστρέφει δεδομένα ως αντικείμενα αυτής της κλάσης; Πιο εύκολα απ' ό,τι νομίζετε. Το μόνο που έχετε να κάνετε είναι να καθορίσετε την κλάση ως τύπο της παραμέτρου `$data` στον χειριστή:
 
 ```php
@@ -294,6 +296,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Μπορείτε να δημιουργήσετε μια πρόταση για την κλάση δεδομένων μιας φόρμας χρησιμοποιώντας τη μέθοδο `Nette\Forms\Blueprint::dataClass($form)`, η οποία θα την εκτυπώσει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, μπορείτε απλά να κάνετε κλικ για να επιλέξετε και να αντιγράψετε τον κώδικα στο έργο σας. .{data-version:3.1.15}
+
 
 Πολλαπλά κουμπιά υποβολής .[#toc-multiple-submit-buttons]
 =========================================================
diff --git a/forms/el/rendering.texy b/forms/el/rendering.texy
index d56be8d3f5..8f480cde41 100644
--- a/forms/el/rendering.texy
+++ b/forms/el/rendering.texy
@@ -11,6 +11,8 @@
 
 Το [σύστημα προτύπων Latte |latte:] διευκολύνει ουσιαστικά την απόδοση των μορφών και των στοιχείων τους. Αρχικά, θα δείξουμε πώς να αποδίδουμε τις φόρμες χειροκίνητα, στοιχείο προς στοιχείο, για να αποκτήσουμε πλήρη έλεγχο του κώδικα. Αργότερα θα δείξουμε πώς να [αυτοματοποιήσουμε |#Automatic rendering] την εν λόγω απόδοση.
 
+Μπορείτε να έχετε την πρόταση ενός προτύπου Latte για τη φόρμα που δημιουργείται χρησιμοποιώντας τη μέθοδο `Nette\Forms\Blueprint::latte($form)`, η οποία θα την εξάγει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, πρέπει απλώς να επιλέξετε τον κώδικα με ένα κλικ και να τον αντιγράψετε στο έργο σας. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form
 ```
 
 
-Πρόταση κώδικα `{formPrint}` .[#toc-formprint]
-----------------------------------------------
-
-Μπορείτε να δημιουργήσετε έναν παρόμοιο κωδικό Latte για μια φόρμα χρησιμοποιώντας την ετικέτα `{formPrint}`. Αν το τοποθετήσετε σε ένα πρότυπο, θα δείτε το σχέδιο κώδικα αντί για την κανονική απόδοση. Στη συνέχεια, απλά επιλέξτε το και αντιγράψτε το στο έργο σας.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ protected function createComponentSignInForm(): Form
 Ειδικές περιπτώσεις .[#toc-special-cases]
 -----------------------------------------
 
-Αν χρειάζεται να αποδώσετε μόνο το εσωτερικό περιεχόμενο μιας φόρμας χωρίς `<form>` & `</form>` ετικέτες HTML, για παράδειγμα, σε μια αίτηση AJAX, μπορείτε να ανοίξετε και να κλείσετε τη φόρμα με το `{formContext} … {/formContext}`. Λειτουργεί παρόμοια με το `{form}` με μια λογική έννοια, εδώ σας επιτρέπει να χρησιμοποιήσετε άλλες ετικέτες για να σχεδιάσετε στοιχεία της φόρμας, αλλά ταυτόχρονα δεν σχεδιάζει τίποτα.
+Αν θέλετε να αποδώσετε μόνο το εσωτερικό μέρος της φόρμας χωρίς ετικέτες HTML `<form>`, για παράδειγμα κατά την αποστολή αποσπασμάτων, αποκρύψτε τα χρησιμοποιώντας το χαρακτηριστικό `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Η ετικέτα `formContainer` βοηθά στην απόδοση των εισόδων μέσα σε ένα δοχείο φόρμας.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Ο renderer σχεδιάζει πρώτα τις ομάδες και στη συνέχεια τα στοιχεία που δεν ανήκουν σε καμία ομάδα.
+
 
 Υποστήριξη Bootstrap .[#toc-bootstrap-support]
 ----------------------------------------------
@@ -444,7 +442,7 @@ $form->addSelect('country', 'Country:', $countries);
 Χαρακτηριστικά HTML .[#toc-html-attributes]
 ===========================================
 
-Μπορείτε να ορίσετε οποιαδήποτε χαρακτηριστικά HTML σε στοιχεία ελέγχου φόρμας χρησιμοποιώντας το `setHtmlAttribute(string $name, $value = true)`:
+Για να ορίσετε αυθαίρετα χαρακτηριστικά HTML για στοιχεία φόρμας, χρησιμοποιήστε τη μέθοδο `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // καλεί τη συνάρτηση JS submit() κατά την αλλαγή
 
 
-// applying on <form>
+// Για να ορίσετε τα χαρακτηριστικά του ίδιου του <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Ρύθμιση τύπου εισόδου:
+Καθορισμός του τύπου του στοιχείου:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-Μπορούμε να ορίσουμε το χαρακτηριστικό HTML σε μεμονωμένα στοιχεία σε λίστες ραδιοφώνου ή checkbox με διαφορετικές τιμές για κάθε ένα από αυτά.
-Προσέξτε την άνω και κάτω τελεία μετά το `style:` για να διασφαλίσετε ότι η τιμή επιλέγεται με βάση το κλειδί:
+.[warning]
+Ο καθορισμός του τύπου και άλλων χαρακτηριστικών χρησιμεύει μόνο για οπτικούς σκοπούς. Η επαλήθευση της ορθότητας της εισόδου πρέπει να γίνεται στο διακομιστή, κάτι που μπορείτε να εξασφαλίσετε επιλέγοντας ένα κατάλληλο [στοιχείο ελέγχου φόρμας | controls] και καθορίζοντας [κανόνες επικύρωσης | validation].
+
+Για μεμονωμένα στοιχεία σε λίστες ραδιοφώνου ή checkbox, μπορούμε να ορίσουμε ένα χαρακτηριστικό HTML με διαφορετικές τιμές για καθένα από αυτά.
+Παρατηρήστε την άνω και κάτω τελεία μετά το `style:`, η οποία διασφαλίζει ότι η τιμή επιλέγεται με βάση το κλειδί:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Για ένα λογικό χαρακτηριστικό HTML (το οποίο δεν έχει τιμή, όπως το `readonly`), μπορείτε να χρησιμοποιήσετε ένα ερωτηματικό:
+Για τον καθορισμό boolean χαρακτηριστικών, όπως το `readonly`, μπορούμε να χρησιμοποιήσουμε τον συμβολισμό με ερωτηματικό:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // χρήση πίνακα για πολλαπλά κλειδιά, π.χ. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ $html->class('distinctive');         // <label class="distinctive">
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/el/standalone.texy b/forms/el/standalone.texy
index 67275ad240..fd72efc13b 100644
--- a/forms/el/standalone.texy
+++ b/forms/el/standalone.texy
@@ -107,7 +107,7 @@ $form->addText('name', 'Name:')
 Προσθέστε το στη σελίδα:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Αν κοιτάξετε στον πηγαίο κώδικα της σελίδας με τη φόρμα, μπορεί να παρατηρήσετε ότι η Nette εισάγει τα απαιτούμενα πεδία σε στοιχεία με κλάση CSS `required`. Δοκιμάστε να προσθέσετε το ακόλουθο στυλ στο πρότυπο, και η ετικέτα "Όνομα" θα είναι κόκκινη. Κομψά, επισημαίνουμε τα υποχρεωτικά πεδία για τους χρήστες:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Από την PHP 8.0, μπορείτε να χρησιμοποιήσετε αυτόν τον κομψό συμβολισμό που χρησιμοποιεί έναν κατασκευαστή:
+Εναλλακτικά, μπορείτε να χρησιμοποιήσετε τον κατασκευαστή:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Οι ιδιότητες της κλάσης δεδομένων μπορούν επίσης να είναι enums και θα αντιστοιχιστούν αυτόματα. .{data-version:3.2.4}
+
 Πώς να πούμε στη Nette να μας επιστρέψει δεδομένα ως αντικείμενα αυτής της κλάσης; Πιο εύκολα απ' ό,τι νομίζετε. Το μόνο που έχετε να κάνετε είναι να καθορίσετε το όνομα της κλάσης ή του αντικειμένου που θέλετε να ενυδατώσετε ως παράμετρο:
 
 ```php
@@ -258,6 +260,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Μπορείτε να δημιουργήσετε μια πρόταση για την κλάση δεδομένων μιας φόρμας χρησιμοποιώντας τη μέθοδο `Nette\Forms\Blueprint::dataClass($form)`, η οποία θα την εκτυπώσει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, μπορείτε απλά να κάνετε κλικ για να επιλέξετε και να αντιγράψετε τον κώδικα στο έργο σας. .{data-version:3.1.15}
+
 
 Πολλαπλά κουμπιά υποβολής .[#toc-multiple-submit-buttons]
 =========================================================
diff --git a/forms/el/validation.texy b/forms/el/validation.texy
index 0cee3fe0f0..7a205ccf3a 100644
--- a/forms/el/validation.texy
+++ b/forms/el/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Η Nette έρχεται με έναν αριθμό ενσωματωμένων κανόνων των οποίων τα ονόματα είναι σταθερές της κλάσης `Nette\Forms\Form`:
+**Οι κανόνες επαλήθευσης ελέγχονται μόνο αν ο χρήστης συμπλήρωσε το στοιχείο.**
 
-Μπορούμε να χρησιμοποιήσουμε τους ακόλουθους κανόνες για όλα τα στοιχεία ελέγχου:
+Η Nette διαθέτει έναν αριθμό προκαθορισμένων κανόνων, τα ονόματα των οποίων είναι σταθερές της κλάσης `Nette\Forms\Form`. Μπορούμε να εφαρμόσουμε αυτούς τους κανόνες σε όλα τα στοιχεία:
 
 | σταθερά | περιγραφή | επιχειρήματα
 |-------
@@ -38,7 +38,11 @@ $form->addPassword('password', 'Password:')
 | `IsNotIn` | η τιμή δεν είναι ίση με κάποιο στοιχείο του πίνακα | `array`
 | `Valid` | η είσοδος περνάει την επικύρωση (για τις [συνθήκες |#conditions]) | -
 
-Για τα στοιχεία ελέγχου `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες:
+
+Είσοδοι κειμένου .[#toc-text-inputs]
+------------------------------------
+
+Για τα στοιχεία `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` μπορούν επίσης να εφαρμοστούν ορισμένοι από τους ακόλουθους κανόνες:
 
 | `MinLength` | ελάχιστο μήκος συμβολοσειράς | `int`
 | `MaxLength` | μέγιστο μήκος συμβολοσειράς | `int`
@@ -57,9 +61,23 @@ $form->addPassword('password', 'Password:')
 Οι κανόνες `Integer`, `Numeric` και `Float` μετατρέπουν αυτόματα την τιμή σε ακέραιο (ή float αντίστοιχα). Επιπλέον, ο κανόνας `URL` δέχεται επίσης μια διεύθυνση χωρίς σχήμα (π.χ. `nette.org`) και συμπληρώνει το σχήμα (`https://nette.org`).
 Οι εκφράσεις στους κανόνες `Pattern` και `PatternInsensitive` πρέπει να ισχύουν για ολόκληρη την τιμή, δηλαδή σαν να ήταν τυλιγμένη στους χαρακτήρες `^` and `$`.
 
+
+Αριθμός στοιχείων .[#toc-number-of-items]
+-----------------------------------------
+
+Για τα στοιχεία `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` μπορείτε επίσης να χρησιμοποιήσετε τους ακόλουθους κανόνες για να περιορίσετε τον αριθμό των επιλεγμένων στοιχείων ή των ανεβασμένων αρχείων:
+
+| `MinLength` | ελάχιστος αριθμός | `int`
+| `MaxLength` | μέγιστος αριθμός | `int`
+| `Length` | αριθμός σε εύρος ή ακριβής αριθμός | ζεύγη `[int, int]` ή `int`
+
+
+Ανέβασμα αρχείου
+----------------
+
 Για τους ελέγχους `addUpload()`, `addMultiUpload()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες:
 
-| `MaxFileSize` | μέγιστο μέγεθος αρχείου | `int`
+| `MaxFileSize` | μέγιστο μέγεθος αρχείου σε bytes | `int`
 | `MimeType` | τύπος MIME, δέχεται μπαλαντέρ (`'video/*'`) | `string\|string[]`
 | `Image` | το ανεβασμένο αρχείο είναι JPEG, PNG, GIF, WebP | -
 | `Pattern` | το όνομα του αρχείου ταιριάζει με κανονική έκφραση | `string`
@@ -67,15 +85,9 @@ $form->addPassword('password', 'Password:')
 
 Τα `MimeType` και `Image` απαιτούν την επέκταση PHP `fileinfo`. Το αν ένα αρχείο ή μια εικόνα είναι του απαιτούμενου τύπου ανιχνεύεται από την υπογραφή του. Η ακεραιότητα ολόκληρου του αρχείου δεν ελέγχεται. Μπορείτε να διαπιστώσετε αν μια εικόνα δεν είναι κατεστραμμένη, για παράδειγμα, προσπαθώντας να [τη φορτώσετε |http:request#toImage].
 
-Για τα στοιχεία ελέγχου `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες για τον περιορισμό του αριθμού των επιλεγμένων στοιχείων, αντίστοιχα των φορτωμένων αρχείων:
-
-| `MinLength` | minimal count | `int`
-| `MaxLength` | μέγιστος αριθμός | `int`
-| `Length` | count in range or exact count | ζεύγος `[int, int]` ή `int`
-
 
 Μηνύματα σφάλματος .[#toc-error-messages]
------------------------------------------
+=========================================
 
 Όλοι οι προκαθορισμένοι κανόνες εκτός από τους `Pattern` και `PatternInsensitive` έχουν ένα προεπιλεγμένο μήνυμα σφάλματος, οπότε μπορούν να παραλειφθούν. Ωστόσο, περνώντας και διατυπώνοντας όλα τα προσαρμοσμένα μηνύματα, θα κάνετε τη φόρμα πιο φιλική προς το χρήστη.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 Στη Nette, είναι πολύ εύκολο να αντιδράσετε στην εκπλήρωση ή όχι μιας συνθήκης από την πλευρά της JavaScript χρησιμοποιώντας τη μέθοδο `toggle()`, βλέπε [Δυναμική JavaScript |#Dynamic JavaScript].
 
 
-Αναφορές μεταξύ στοιχείων ελέγχου .[#toc-references-between-controls]
-=====================================================================
+Αναφορά σε άλλο στοιχείο .[#toc-reference-to-another-element]
+=============================================================
 
-Το όρισμα του κανόνα ή της συνθήκης μπορεί να είναι μια αναφορά σε ένα άλλο στοιχείο. Για παράδειγμα, μπορείτε να επικυρώσετε δυναμικά ότι το `text` έχει τόσους χαρακτήρες όσοι είναι οι τιμές του πεδίου `length`:
+Ως όρισμα για έναν κανόνα ή συνθήκη, μπορείτε επίσης να περάσετε ένα άλλο στοιχείο της φόρμας. Ο κανόνας θα χρησιμοποιήσει τότε την τιμή που θα εισαχθεί αργότερα από τον χρήστη στο πρόγραμμα περιήγησης. Αυτό μπορεί να χρησιμοποιηθεί, για παράδειγμα, για τη δυναμική επικύρωση ότι το στοιχείο `password` περιέχει την ίδια συμβολοσειρά με το στοιχείο `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ $form->addText('zip', 'Postcode:')
 Μπορείτε να ενσωματώσετε το σενάριο απευθείας στη σελίδα HTML από το CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 ή να το αντιγράψετε τοπικά στο δημόσιο φάκελο του έργου (π.χ. από το `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/en/controls.texy b/forms/en/controls.texy
index 237761d601..c3d28d0d01 100644
--- a/forms/en/controls.texy
+++ b/forms/en/controls.texy
@@ -5,8 +5,8 @@ Form Controls
 Overview of built-in form controls.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Adds single line text field (class [TextInput |api:Nette\Forms\Controls\TextInput]). If the user does not fill in the field, it returns an empty string `''`, or use `setNullable()` to change it to return `null`.
 
@@ -20,13 +20,10 @@ It automatically validates UTF-8, trims left and right whitespaces, and removes
 
 The maximum length can be limited using `setMaxLength()`. The [addFilter()|validation#Modifying Input Values] allows you to change the user-entered value.
 
-Use `setHtmlType()` to change the [character|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] of input element to `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Instead of the `number` and `email` types, we recommend using [#addInteger] and [#addEmail], which provide server-side validation.
+You can change the visual character of a text field to types like `search`, `tel`, or `url` using `setHtmlType()`, as seen in the [specification|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Remember that changing the type is only visual and does not perform validation functions. For the `url` type, it is appropriate to add a specific [URL rule|validation#Text inputs].
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+For other input types such as `number`, `range`, `email`, `date`, `datetime-local`, `time`, and `color`, use specialized methods like [#addInteger], [#addFloat], [#addEmail] [#addDate], [#addTime], [#addDateTime], and [#addColor], which ensure server-side validation. The types `month` and `week` are not yet fully supported in all browsers.
 
 The so-called empty-value can be set for the element, which is something like the default value, but if the user does not overwrite it, returns empty string or `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Adds input field for integer (class [TextInput |api:Nette\Forms\Controls\TextInput]). Returns either an integer or `null` if the user does not enter anything.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'The year must be in the range %d to %d.', [1900, 2023]);
+```
+
+The element is rendered as `<input type="numeric">`. By using the `setHtmlType()` method, you can change the type to `range` for display as a slider, or to `text` if you prefer a standard text field without the special behavior of `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+	->addRule($form::Range, 'The level must be in the range %d to %d.', [0, 100]);
 ```
 
+The element is rendered as `<input type="numeric">`. By using the `setHtmlType()` method, you can change the type to `range` for display as a slider, or to `text` if you prefer a standard text field without the special behavior of `numeric`.
+
+Nette and the Chrome browser accept both a comma and a dot as decimal separators. To make this functionality available in Firefox, it is recommended to set the `lang` attribute either for the specific element or for the entire page, for example, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Adds email address field with validity check (class [TextInput |api:Nette\Forms\Controls\TextInput]). If the user does not fill in the field, it returns an empty string `''`, or use `setNullable()` to change it to return `null`.
 
@@ -78,8 +92,8 @@ Verifies that the value is a valid email address. It does not verify that the do
 The maximum length can be limited using `setMaxLength()`. The [addFilter()|validation#Modifying Input Values] allows you to change the user-entered value. You can set the so-called empty-value using `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Adds password field (class [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Adds list of checkboxes for selecting multiple items (class [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Returns the array of keys of the selected items. The `getSelectedItems()` method returns values instead of keys.
 
@@ -125,9 +139,15 @@ The element automatically checks that there has been no forgery and that the sel
 
 When default values are set, it also checks that they are one of the offered items, otherwise it throws an exception. This check can be turned off with `checkDefaultValue(false)`.
 
+If you are submitting a form using the `GET` method, you can choose a more compact data transfer method that saves on the size of the query string. This is activated by setting the HTML attribute of the form:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Adds radio buttons (class [RadioList |api:Nette\Forms\Controls\RadioList]). Returns the key of the selected item, or `null` if the user did not select anything. The `getSelectedItem()` method returns a value instead of a key.
 
@@ -148,8 +168,8 @@ The element automatically checks that there has been no forgery and that the sel
 When default value is set, it also checks that it is one of the offered items, otherwise it throws an exception. This check can be turned off with `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Adds select box (class [SelectBox |api:Nette\Forms\Controls\SelectBox]). Returns the key of the selected item, or `null` if the user did not select anything. The `getSelectedItem()` method returns a value instead of a key.
 
@@ -193,8 +213,8 @@ The element automatically checks that there has been no forgery and that the sel
 When default value is set, it also checks that it is one of the offered items, otherwise it throws an exception. This check can be turned off with `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Adds multichoice select box (class [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Returns the array of keys of the selected items. The `getSelectedItems()` method returns values instead of keys.
 
@@ -246,8 +266,81 @@ Do not trust the original file names returned by method `FileUpload::getName()`,
 Rules `MimeType` and `Image` detect required type of file or image by its signature. The integrity of the entire file is not checked. You can find out if an image is not corrupted for example by trying to [load it|http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Adds a field that allows the user to easily input a date consisting of year, month, and day (class [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+For the default value, it accepts either objects implementing the `DateTimeInterface`, a string with time, or a number representing a UNIX timestamp. The same applies to the `Min`, `Max`, or `Range` rule arguments, which define the minimum and maximum allowed date.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+By default, it returns a `DateTimeImmutable` object. Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] or timestamp:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Adds a field that allows the user to easily input time consisting of hours, minutes, and optionally seconds (class [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+For the default value, it accepts either objects implementing the `DateTimeInterface`, a string with time, or a number representing a UNIX timestamp. Only the time information from these inputs is used; the date is ignored. The same applies to the `Min`, `Max`, or `Range` rule arguments, which define the minimum and maximum allowed time. If the minimum value set is higher than the maximum, a time range spanning midnight is created.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+By default, it returns a `DateTimeImmutable` object (with date of January 1, year 1). Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Adds a field that allows the user to easily input both date and time consisting of year, month, day, hours, minutes, and optionally seconds (class [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+For the default value, it accepts either objects implementing the `DateTimeInterface`, a string with time, or a number representing a UNIX timestamp. The same applies to the `Min`, `Max`, or `Range` rule arguments, which define the minimum and maximum allowed date.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+By default, it returns a `DateTimeImmutable` object. Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] or timestamp:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Adds a color selection field (class [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). The color is a string in the format `#rrggbb`. If the user doesn't make a selection, the default color returned is black `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Adds hidden field (class [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Use `setNullable()` to change it to return `null` instead of an empty string. The [addFilter()|validation#Modifying Input Values] allows you to change the submitted value.
 
+Although the element is hidden, it is **important to realize** that its value can still be modified or spoofed by an attacker. Always thoroughly verify and validate all received values on the server side to prevent security risks associated with data manipulation.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Adds submit button in form of an image (class [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ The following methods can be called for the `addText()`, `addPassword()`, `addTe
 
 
 Omitted Values
---------------
+==============
 
 If you are not interested in the value entered by the user, we can use `setOmitted()` to omit it from the result provided by the `$form->getValues​()` method or passed to handlers. This is suitable for various passwords for verification, antispam fields, etc.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Disabling Inputs
-----------------
+================
 
-In order to disable an input, you can call `setDisabled()`. Such a field cannot be edited by the user.
+Inputs can be disabled using `setDisabled()`. A disabled input cannot be edited by the user.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Note that the browser does not send the disabled fields to the server at all, so you won't even find them in the data returned by the `$form->getValues()` function.
+Disabled inputs are not sent to the server by the browser, so you won't find them in the data returned by the `$form->getValues()` function. However, if you set `setOmitted(false)`, Nette will include their default value in this data.
 
-If you are setting a default value for a field, you must do so only after disabling it:
+When `setDisabled()` is called, **the input's value is erased** for security reasons. If you are setting a default value, it is necessary to do so after its deactivation:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+An alternative to disabled inputs are fields with the HTML `readonly` attribute, which are sent to the server by the browser. Although the field is only readable, it is **important to realize** that its value can still be modified or spoofed by an attacker.
+
 
 Custom Controls
 ===============
@@ -428,8 +525,8 @@ There is a way to define new form methods for adding custom elements (eg `$form-
 ```php
 use Nette\Forms\Container;
 
-// adds method addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// adds method addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy
index e09ebee337..119cce4250 100644
--- a/forms/en/in-presenter.texy
+++ b/forms/en/in-presenter.texy
@@ -30,7 +30,7 @@ The form in the presenter is an object of the class `Nette\Application\UI\Form`,
 
 From the presenter's point of view, the form is a common component. Therefore, it is treated as a component and incorporated into the presenter using [factory method |application:components#Factory Methods]. It will look like this:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 And render in template is done using `{control}` tag:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ The form is always validated on the server side, but JavaScript validation is al
 Insert it into the layout template:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 If you look in the source code of the page with form, you may notice that Nette inserts the required fields into elements with a CSS class `required`. Try adding the following style to the template, and the "Name" label will be red. Elegantly, we mark the required fields for the users:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-As of PHP 8.0, you can use this elegant notation that uses a constructor:
+Alternatively, you can use the constructor:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Properties of the data class can also be enums and they will be automatically mapped. .{data-version:3.2.4}
+
 How to tell Nette to return data as objects of this class? Easier than you think. All you have to do is specify the class as the type of the `$data` parameter in the handler:
 
 ```php
@@ -294,6 +296,8 @@ The mapping then knows from the `$person` property type that it should map the c
 $person->setMappedType(PersonFormData::class);
 ```
 
+You can generate a proposal for the data class of a form using the method `Nette\Forms\Blueprint::dataClass($form)`, which will print it out to the browser page. You can then simply click to select and copy the code into your project. .{data-version:3.1.15}
+
 
 Multiple Submit Buttons
 =======================
diff --git a/forms/en/rendering.texy b/forms/en/rendering.texy
index 27c71677e4..7172270f3e 100644
--- a/forms/en/rendering.texy
+++ b/forms/en/rendering.texy
@@ -11,6 +11,8 @@ Rendering With Latte
 
 The [Latte templating system|latte:] fundamentally facilitates the rendering of forms and their elements. First, we'll show how to render forms manually, element by element, to gain full control over the code. Later we will show how to [automate |#Automatic rendering] such rendering.
 
+You can have the proposal of a Latte template for the form generated using the method `Nette\Forms\Blueprint::latte($form)`, which will output it to the browser page. Then, you simply need to select the code with a click and copy it into your project. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ More complex form elements, such as RadioList or CheckboxList, can be rendered i
 ```
 
 
-Code Proposal `{formPrint}` .[#toc-formprint]
----------------------------------------------
-
-You can generate a similar Latte code for a form using the `{formPrint}` tag. If you place it in a template, you will see the draft code instead of the normal rendering. Then just select it and copy it into your project.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ You only need to import the block in one place, at the beginning of the layout t
 Special Cases
 -------------
 
-If you only need to render the inner content of a form without `<form>` & `</form>` HTML tags, for example, in an AJAX request, you can open and close the form with `{formContext} … {/formContext}`. It works similarly to `{form}` in a logical sense, here it allows you to use other tags to draw form elements, but at the same time it doesn't draw anything.
+If you need to render only the inner part of the form without HTML tags `<form>`, for example when sending snippets, hide them using the `n:tag-if` attribute:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Tag `formContainer` helps with rendering of inputs inside a form container.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+The renderer draws groups first and then elements that do not belong to any group.
+
 
 Bootstrap Support
 -----------------
@@ -444,7 +442,7 @@ You can find [examples |https://github.com/nette/forms/tree/master/examples] of
 HTML Attributes
 ===============
 
-You can set any HTML attributes to form controls using `setHtmlAttribute(string $name, $value = true)`:
+To set arbitrary HTML attributes for form elements, use the method `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // calls JS function submit() on change
 
 
-// applying on <form>
+// To set attributes of the <form> itself
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Setting input type:
+Specifying the type of element:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-We can set HTML attribute to individual items in radio or checkbox lists with different values for each of them.
-Note the colon after `style:` to ensure that the value is selected by key:
+.[warning]
+Setting the type and other attributes serves only for visual purposes. Verification of input correctness must occur on the server, which you can ensure by choosing an appropriate [form control | controls] and specifying [validation rules | validation].
+
+For individual items in radio or checkbox lists, we can set an HTML attribute with different values for each of them.
+Notice the colon after `style:`, which ensures the value is selected based on the key:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-For a logical HTML attribute (which has no value, such as `readonly`), you can use a question mark:
+For setting boolean attributes, such as `readonly`, we can use the notation with a question mark:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // use array for multiple keys, e.g. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ For Checkbox, CheckboxList and RadioList items you can influence the element tem
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/en/standalone.texy b/forms/en/standalone.texy
index 13d1285515..bd089f60a1 100644
--- a/forms/en/standalone.texy
+++ b/forms/en/standalone.texy
@@ -107,7 +107,7 @@ The form is always validated on the server side, but JavaScript validation is al
 Add it to the page:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 If you look in the source code of the page with form, you may notice that Nette inserts the required fields into elements with a CSS class `required`. Try adding the following style to the template, and the "Name" label will be red. Elegantly, we mark the required fields for the users:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-As of PHP 8.0, you can use this elegant notation that uses a constructor:
+Alternatively, you can use the constructor:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Properties of the data class can also be enums and they will be automatically mapped. .{data-version:3.2.4}
+
 How to tell Nette to return data to us as objects of this class? Easier than you think. All you have to do is specify the class name or object to hydrate as a parameter:
 
 ```php
@@ -258,6 +260,8 @@ The mapping then knows from the `$person` property type that it should map the c
 $person->setMappedType(PersonFormData::class);
 ```
 
+You can generate a proposal for the data class of a form using the method `Nette\Forms\Blueprint::dataClass($form)`, which will print it out to the browser page. You can then simply click to select and copy the code into your project. .{data-version:3.1.15}
+
 
 Multiple Submit Buttons
 =======================
diff --git a/forms/en/validation.texy b/forms/en/validation.texy
index 18db69d0e0..215f7c21e8 100644
--- a/forms/en/validation.texy
+++ b/forms/en/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette comes with a number of built-in rules whose names are constants of the `Nette\Forms\Form` class:
+**Validation rules are checked only if the user filled in the element.**
 
-We can use the following rules for all controls:
+Nette comes with a number of predefined rules whose names are constants of the class `Nette\Forms\Form`. We can apply these rules to all elements:
 
 | constant | description | arguments
 |-------
@@ -38,7 +38,11 @@ We can use the following rules for all controls:
 | `IsNotIn` | value does not equal any element in the array | `array`
 | `Valid` | input passes validation (for [#conditions])  | -
 
-For controls `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` the following rules can also be used:
+
+Text inputs
+-----------
+
+For elements `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` some of the following rules can also be applied:
 
 | `MinLength` | minimal string length | `int`
 | `MaxLength` | maximal string length | `int`
@@ -55,11 +59,25 @@ For controls `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addIn
 | `Range` | value in the range | pair `[int\|float, int\|float]`
 
 The `Integer`, `Numeric` a `Float` rules automatically convert the value to integer (or float respectively). Furthermore, the `URL` rule also accepts an address without a schema (eg `nette.org`) and completes the schema (`https://nette.org`).
-The expressions in `Pattern` and `PatternInsensitive` must be valid for the whole value, ie as if it were wrapped in the characters `^` and `$`.
+The expressions in `Pattern` and `PatternInsensitive` must be valid for the whole value, i.e. as if it were wrapped in the characters `^` and `$`.
+
+
+Number of Items
+---------------
+
+For the elements `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` you can also use the following rules to limit the number of selected items or uploaded files:
+
+| `MinLength` | minimum number | `int`
+| `MaxLength` | maximum number | `int`
+| `Length` | number in range or exact number | pairs `[int, int]` or `int`
+
+
+File Upload
+-----------
 
 For controls `addUpload()`, `addMultiUpload()` the following rules can also be used:
 
-| `MaxFileSize` | maximal file size | `int`
+| `MaxFileSize` | maximal file size in bytes | `int`
 | `MimeType` | MIME type, accepts wildcards (`'video/*'`) | `string\|string[]`
 | `Image` | uploaded file is JPEG, PNG, GIF, WebP, AVIF | -
 | `Pattern` | file name matches regular expression | `string`
@@ -67,17 +85,11 @@ For controls `addUpload()`, `addMultiUpload()` the following rules can also be u
 
 The `MimeType` and `Image` require PHP extension `fileinfo`. Whether a file or image is of the required type is detected by its signature. The integrity of the entire file is not checked. You can find out if an image is not corrupted for example by trying to [load it|http:request#toImage].
 
-For controls `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` the following rules can also be used to limit the number of selected items, respectively uploaded files:
-
-| `MinLength` | minimal count | `int`
-| `MaxLength` | maximal count | `int`
-| `Length` | count in range or exact count | pair `[int, int]` or `int`
-
 
 Error Messages
---------------
+==============
 
-All predefined rules except `Pattern` and `PatternInsensitive` have a default error message, so they it be omitted. However, by passing and formulating all customized messages, you will make the form more user-friendly.
+All predefined rules except `Pattern` and `PatternInsensitive` have a default error message, so they can be omitted. However, by passing and formulating all customized messages, you will make the form more user-friendly.
 
 You can change the default messages in [forms:configuration], by modifying the texts in the `Nette\Forms\Validator::$messages` array or by using [translator|rendering#translating].
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 In Nette, it is very easy to react to the fulfillment or not of a condition on the JavaScript side using the `toggle()` method, see [#Dynamic JavaScript].
 
 
-References Between Controls
-===========================
+Reference to Another Element
+============================
 
-The rule or condition argument can be a reference to another element. For example, you can dynamically validate that the `text` has as many characters as the value of the `length` field is:
+As an argument for a rule or condition, you can also pass another form element. The rule will then use the value entered later by the user in the browser. This can be used, for example, to dynamically validate that the `password` element contains the same string as the `password_confirm` element:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -267,7 +279,7 @@ $form->addText('zip', 'Postcode:')
 	->addRule($form::Pattern, 'The postal code is not five digits', '\d{5}');
 ```
 
-The filter is included between the validation rules and conditions and therefore depends on the order of the methods, ie the filter and the rule are called in the same order as is the order of the `addFilter()` and `addRule()` methods.
+The filter is included between the validation rules and conditions and therefore depends on the order of the methods, i.e. the filter and the rule are called in the same order as is the order of the `addFilter()` and `addRule()` methods.
 
 
 JavaScript Validation
@@ -281,7 +293,7 @@ This script is `netteForms.js`, which is available from several possible sources
 You can embed the script directly into the HTML page from the CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Or copy locally to the public folder of the project (e.g. from `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/es/controls.texy b/forms/es/controls.texy
index a1ee2d5426..5095332863 100644
--- a/forms/es/controls.texy
+++ b/forms/es/controls.texy
@@ -5,8 +5,8 @@ Controles de formularios
 Visión general de los controles de formulario incorporados.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Añade un campo de texto de una sola línea (clase [TextInput |api:Nette\Forms\Controls\TextInput]). Si el usuario no rellena el campo, devuelve una cadena vacía `''`, o utiliza `setNullable()` para cambiarlo y que devuelva `null`.
 
@@ -20,13 +20,10 @@ Valida automáticamente UTF-8, recorta los espacios en blanco a izquierda y dere
 
 La longitud máxima puede limitarse mediante `setMaxLength()`. La [función addFilter() |validation#Modifying Input Values] permite cambiar el valor introducido por el usuario.
 
-Utilice `setHtmlType()` para cambiar el [carácter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] del elemento de entrada a `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. En lugar de los tipos `number` y `email`, recomendamos utilizar [addInteger |#addInteger] y [addEmail |#addEmail], que proporcionan validación del lado del servidor.
+Puede cambiar el carácter visual de un campo de texto a tipos como `search`, `tel`, o `url` utilizando `setHtmlType()`, como se ve en la [especificación |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Recuerde que el cambio de tipo es sólo visual y no realiza funciones de validación. Para el tipo `url`, es conveniente añadir una [regla URL |validation#Text inputs] específica.
 
-```php
-$form->addText('color', 'Elige color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'valor no válido', '[0-9a-f]{6}');
-```
+.[note]
+Para otros tipos de entrada como `number`, `range`, `email`, `date`, `datetime-local`, `time`, y `color`, utilice métodos especializados como [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime], y [addColor |#addColor], que aseguran la validación del lado del servidor. Los tipos `month` y `week` aún no son totalmente compatibles con todos los navegadores.
 
 Se puede establecer el llamado empty-value para el elemento, que es algo así como el valor por defecto, pero si el usuario no lo sobrescribe, devuelve cadena vacía o `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Añade un campo de entrada para números enteros (clase [TextInput |api:Nette\Forms\Controls\TextInput]). Devuelve un entero o `null` si el usuario no introduce nada.
 
 ```php
-$form->addInteger('level', 'Nivel:')
+$form->addInteger('año', 'Año:')
+	->addRule($form::Range, 'El año debe estar en el rango %d a %d.', [1900, 2023 |1900, 2023]);
+```
+
+El elemento se representa como `<input type="numeric">`. Utilizando el método `setHtmlType()`, puede cambiar el tipo a `range` para mostrarlo como un deslizador, o a `text` si prefiere un campo de texto estándar sin el comportamiento especial de `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('nivel', 'Nivel:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'El nivel debe estar entre %d y %d.', [0, 100]);
+->addRule($form::Range, 'El nivel debe estar en el rango %d a %d.', [0, 100 |0, 100]);
 ```
 
+El elemento se representa como `<input type="numeric">`. Utilizando el método `setHtmlType()`, puede cambiar el tipo a `range` para mostrarlo como un deslizador, o a `text` si prefiere un campo de texto estándar sin el comportamiento especial de `numeric`.
+
+Nette y el navegador Chrome aceptan tanto una coma como un punto como separadores decimales. Para que esta funcionalidad esté disponible en Firefox, se recomienda establecer el atributo `lang` para el elemento específico o para toda la página, por ejemplo, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Añade un campo de dirección de correo electrónico con comprobación de validez (clase [TextInput |api:Nette\Forms\Controls\TextInput]). Si el usuario no rellena el campo, devuelve una cadena vacía `''`, o utiliza `setNullable()` para cambiarlo y que devuelva `null`.
 
@@ -78,8 +92,8 @@ Verifica que el valor es una dirección de correo electrónico válida. No verif
 La longitud máxima puede limitarse utilizando `setMaxLength()`. La [función addFilter() |validation#Modifying Input Values] permite cambiar el valor introducido por el usuario. Puede establecer el llamado valor vacío utilizando `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Añade campo de contraseña (clase [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'Estoy de acuerdo con las condiciones')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Añade una lista de casillas de verificación para seleccionar varios elementos (clase [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Devuelve el array de claves de los elementos seleccionados. El método `getSelectedItems()` devuelve valores en lugar de claves.
 
@@ -125,9 +139,15 @@ El elemento comprueba automáticamente que no ha habido falsificación y que los
 
 Cuando se establecen valores por defecto, también comprueba que son uno de los elementos ofrecidos, de lo contrario lanza una excepción. Esta comprobación puede desactivarse con `checkDefaultValue(false)`.
 
+Si está enviando un formulario utilizando el método `GET`, puede elegir un método de transferencia de datos más compacto que ahorra en el tamaño de la cadena de consulta. Esto se activa configurando el atributo HTML del formulario:
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
+
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Añade botones de radio (clase [RadioList |api:Nette\Forms\Controls\RadioList]). Devuelve la clave del elemento seleccionado, o `null` si el usuario no seleccionó nada. El método `getSelectedItem()` devuelve un valor en lugar de una clave.
 
@@ -148,8 +168,8 @@ El elemento comprueba automáticamente que no ha habido falsificación y que el
 Cuando se establece el valor por defecto, también comprueba que es uno de los elementos ofrecidos, de lo contrario lanza una excepción. Esta comprobación puede desactivarse con `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Añade una caja de selección (clase [SelectBox |api:Nette\Forms\Controls\SelectBox]). Devuelve la clave del elemento seleccionado, o `null` si el usuario no seleccionó nada. El método `getSelectedItem()` devuelve un valor en lugar de una clave.
 
@@ -193,8 +213,8 @@ El elemento comprueba automáticamente que no ha habido falsificación y que el
 Cuando se establece el valor por defecto, también comprueba que es uno de los elementos ofrecidos, de lo contrario lanza una excepción. Esta comprobación puede desactivarse con `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Añade una caja de selección multielección (clase [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Devuelve el array de claves de los elementos seleccionados. El método `getSelectedItems()` devuelve valores en lugar de claves.
 
@@ -246,8 +266,81 @@ No confíe en los nombres de archivo originales devueltos por el método `FileUp
 Las reglas `MimeType` y `Image` detectan el tipo de archivo o imagen requerido por su firma. No se comprueba la integridad de todo el archivo. Puedes averiguar si una imagen no está corrupta, por ejemplo, intentando [cargarla |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Añade un campo que permite al usuario introducir fácilmente una fecha consistente en año, mes y día (clase [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Para el valor predeterminado, acepta objetos que implementen la regla `DateTimeInterface`, una cadena con la hora o un número que represente una marca de tiempo UNIX. Lo mismo ocurre con los argumentos de regla `Min`, `Max`, o `Range`, que definen la fecha mínima y máxima permitidas.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Por defecto, devuelve un objeto `DateTimeImmutable`. Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o una marca de tiempo:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Añade un campo que permite al usuario introducir fácilmente la hora consistente en horas, minutos y, opcionalmente, segundos (clase [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Por defecto, acepta objetos que implementen la clase `DateTimeInterface`, una cadena con la hora o un número que represente una marca de tiempo UNIX. Sólo se utiliza la información horaria de estas entradas; la fecha se ignora. Lo mismo ocurre con los argumentos de regla `Min`, `Max` o `Range`, que definen el tiempo mínimo y máximo permitido. Si el valor mínimo establecido es superior al máximo, se crea un intervalo de tiempo que abarca la medianoche.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Por defecto, devuelve un objeto `DateTimeImmutable` (con fecha de 1 de enero del año 1). Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Añade un campo que permite al usuario introducir fácilmente tanto la fecha como la hora consistente en año, mes, día, horas, minutos y opcionalmente segundos (clase [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Para el valor por defecto, acepta bien objetos que implementen el `DateTimeInterface`, una cadena con la hora, o un número que represente una marca de tiempo UNIX. Lo mismo se aplica a los argumentos de regla `Min`, `Max`, o `Range`, que definen la fecha mínima y máxima permitidas.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Por defecto, devuelve un objeto `DateTimeImmutable`. Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o una marca de tiempo:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Añade un campo de selección de color (clase [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). El color es una cadena con el formato `#rrggbb`. Si el usuario no hace una selección, el color devuelto por defecto es el negro `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Añade un campo oculto (clase [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Utiliza `setNullable()` para cambiarlo y que devuelva `null` en lugar de una cadena vacía. La [función addFilter() |validation#Modifying Input Values] permite cambiar el valor enviado.
 
+Aunque el elemento esté oculto, es **importante darse cuenta** de que su valor aún puede ser modificado o suplantado por un atacante. Verifica y valida siempre todos los valores recibidos en el servidor para evitar riesgos de seguridad asociados a la manipulación de datos.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Añade un botón de envío en forma de imagen (clase [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Los siguientes métodos pueden ser llamados para los elementos `addText()`, `add
 
 
 Valores omitidos .[#toc-omitted-values]
----------------------------------------
+=======================================
 
 Si no nos interesa el valor introducido por el usuario, podemos utilizar `setOmitted()` para omitirlo del resultado proporcionado por el método `$form->getValues​()` o pasado a los manejadores. Esto es adecuado para varias contraseñas de verificación, campos antispam, etc.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Contraseña de nuevo:')
 
 
 Desactivar entradas .[#toc-disabling-inputs]
---------------------------------------------
+============================================
 
-Para desactivar una entrada, puede llamar a `setDisabled()`. Un campo de este tipo no puede ser editado por el usuario.
+Las entradas pueden desactivarse utilizando `setDisabled()`. Una entrada desactivada no puede ser editada por el usuario.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Tenga en cuenta que el navegador no envía los campos deshabilitados al servidor en absoluto, por lo que ni siquiera los encontrará en los datos devueltos por la función `$form->getValues()`.
+Las entradas deshabilitadas no son enviadas al servidor por el navegador, por lo que no las encontrará en los datos devueltos por la función `$form->getValues()`. Sin embargo, si configuras `setOmitted(false)`, Nette incluirá su valor por defecto en estos datos.
 
-Si establece un valor predeterminado para un campo, debe hacerlo sólo después de desactivarlo:
+Cuando se llama a `setDisabled()`, **el valor de la entrada se borra** por razones de seguridad. Si establece un valor por defecto, es necesario hacerlo después de su desactivación:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Una alternativa a las entradas deshabilitadas son los campos con el atributo HTML `readonly`, que el navegador envía al servidor. Aunque el campo sólo es legible, es **importante darse cuenta** de que su valor aún puede ser modificado o suplantado por un atacante.
+
 
 Controles personalizados .[#toc-custom-controls]
 ================================================
@@ -428,8 +525,8 @@ Existe una forma de definir nuevos métodos de formulario para añadir elementos
 ```php
 use Nette\Forms\Container;
 
-// adds method addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// adds method addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/es/in-presenter.texy b/forms/es/in-presenter.texy
index 2dddcee064..b1e4a9ae56 100644
--- a/forms/es/in-presenter.texy
+++ b/forms/es/in-presenter.texy
@@ -30,7 +30,7 @@ El formulario en el presentador es un objeto de la clase `Nette\Application\UI\F
 
 Desde el punto de vista del presentador, el formulario es un componente común. Por lo tanto, se trata como un componente y se incorpora al presentador utilizando [el método factory |application:components#Factory Methods]. Tendrá el siguiente aspecto:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Y el renderizado en la plantilla se realiza utilizando la etiqueta `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registro</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ El formulario siempre se valida en el lado del servidor, pero también se genera
 Insértelo en la plantilla de diseño:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Si mira en el código fuente de la página con formulario, puede observar que Nette inserta los campos obligatorios en elementos con una clase CSS `required`. Pruebe a añadir el siguiente estilo a la plantilla, y la etiqueta "Nombre" será de color rojo. Elegantemente, marcamos los campos obligatorios para los usuarios:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-A partir de PHP 8.0, puedes usar esta elegante notación que usa un constructor:
+Alternativamente, puede utilizar el constructor:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Las propiedades de la clase de datos también pueden ser enums y se asignarán automáticamente. .{data-version:3.2.4}
+
 ¿Cómo decirle a Nette que devuelva datos como objetos de esta clase? Más fácil de lo que piensa. Todo lo que tiene que hacer es especificar la clase como tipo del parámetro `$data` en el manejador:
 
 ```php
@@ -294,6 +296,8 @@ El mapeo entonces sabe por el tipo de propiedad `$person` que debe mapear el con
 $person->setMappedType(PersonFormData::class);
 ```
 
+Puede generar una propuesta para la clase de datos de un formulario utilizando el método `Nette\Forms\Blueprint::dataClass($form)`, que la imprimirá en la página del navegador. A continuación, puede simplemente hacer clic para seleccionar y copiar el código en su proyecto. .{data-version:3.1.15}
+
 
 Botones de envío múltiples .[#toc-multiple-submit-buttons]
 ==========================================================
diff --git a/forms/es/rendering.texy b/forms/es/rendering.texy
index 91ce9f6d5e..d3146c2006 100644
--- a/forms/es/rendering.texy
+++ b/forms/es/rendering.texy
@@ -11,6 +11,8 @@ Renderizado con Latte .[#toc-rendering-with-latte]
 
 El [sistema de plantillas |latte:] Latte facilita fundamentalmente el renderizado de formularios y sus elementos. En primer lugar, mostraremos cómo renderizar formularios manualmente, elemento por elemento, para obtener un control total sobre el código. Más adelante mostraremos cómo [automatizar |#Automatic rendering] dicho renderizado.
 
+Usted puede tener la propuesta de una plantilla de Latte para el formulario generado utilizando el método `Nette\Forms\Blueprint::latte($form)`, que le dará salida a la página del navegador. A continuación, sólo tiene que seleccionar el código con un clic y copiarlo en su proyecto. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Los elementos de formulario más complejos, como RadioList o CheckboxList, puede
 ```
 
 
-Propuesta de código `{formPrint}` .[#toc-formprint]
----------------------------------------------------
-
-Puede generar un código Latte similar para un formulario utilizando la etiqueta `{formPrint}`. Si lo colocas en una plantilla, verás el borrador del código en lugar de la representación normal. Luego sólo tienes que seleccionarlo y copiarlo en tu proyecto.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Sólo tendrá que importar el bloque en un lugar, al principio de la plantilla d
 Casos especiales .[#toc-special-cases]
 --------------------------------------
 
-Si sólo necesita renderizar el contenido interno de un formulario sin `<form>` & `</form>` por ejemplo, en una petición AJAX, puedes abrir y cerrar el formulario con `{formContext} … {/formContext}`. Funciona de forma similar a `{form}` en un sentido lógico, aquí te permite usar otras etiquetas para dibujar elementos del formulario, pero al mismo tiempo no dibuja nada.
+Si necesita mostrar sólo la parte interior del formulario sin etiquetas HTML `<form>`por ejemplo, al enviar fragmentos, ocúltelos con el atributo `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Nombre de usuario: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 La etiqueta `formContainer` ayuda con la representación de entradas dentro de un contenedor de formulario.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+El renderizador dibuja primero los grupos y después los elementos que no pertenecen a ningún grupo.
+
 
 Soporte Bootstrap .[#toc-bootstrap-support]
 -------------------------------------------
@@ -444,7 +442,7 @@ Puede encontrar [ejemplos |https://github.com/nette/forms/tree/master/examples]
 Atributos HTML .[#toc-html-attributes]
 ======================================
 
-Puede establecer cualquier atributo HTML a los controles de formulario utilizando `setHtmlAttribute(string $name, $value = true)`:
+Para establecer atributos HTML arbitrarios para elementos de formulario, utilice el método `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Número:')
@@ -454,11 +452,11 @@ $form->addSelect('range', 'Ordenar por:', ['precio', 'nombre'])
 	->setHtmlAttribute('onchange', 'submit()'); // llama a la función JS submit() al cambiar
 
 
-// aplicando en <form>
+// Para establecer atributos del propio <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Configuración del tipo de entrada:
+Especificación del tipo de elemento:
 
 ```php
 $form->addText('tel', 'Su teléfono:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Su teléfono:')
 	->setHtmlAttribute('placeholder', 'Por favor, introduzca su teléfono');
 ```
 
-Podemos establecer el atributo HTML a elementos individuales en listas de radio o casillas de verificación con valores diferentes para cada uno de ellos.
-Tenga en cuenta los dos puntos después de `style:` para asegurarse de que el valor se selecciona por clave:
+.[warning]
+Establecer el tipo y otros atributos sólo sirve a efectos visuales. La verificación de la corrección de la entrada debe ocurrir en el servidor, lo que puede asegurar eligiendo un [control de formulario | controls] apropiado y especificando [reglas de validación | validation].
+
+Para elementos individuales en listas de radio o casillas de verificación, podemos establecer un atributo HTML con valores diferentes para cada uno de ellos.
+Observe los dos puntos después de `style:`, que garantiza que el valor se selecciona en función de la clave:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Para un atributo HTML lógico (que no tiene valor, como `readonly`), puede utilizar un signo de interrogación:
+Para establecer atributos booleanos, como `readonly`, podemos utilizar la notación con un signo de interrogación:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // use array for multiple keys, e.g. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ Para los elementos Checkbox, CheckboxList y RadioList se puede influir en la pla
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/es/standalone.texy b/forms/es/standalone.texy
index 22066da21c..cb33c175ec 100644
--- a/forms/es/standalone.texy
+++ b/forms/es/standalone.texy
@@ -107,7 +107,7 @@ El formulario siempre se valida en el lado del servidor, pero también se genera
 Añádelo a la página:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Si miras en el código fuente de la página con formulario, puedes notar que Nette inserta los campos requeridos en elementos con una clase CSS `required`. Pruebe a añadir el siguiente estilo a la plantilla, y la etiqueta "Nombre" será de color rojo. Elegantemente, marcamos los campos obligatorios para los usuarios:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-A partir de PHP 8.0, puedes usar esta elegante notación que usa un constructor:
+Alternativamente, puede utilizar el constructor:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Las propiedades de la clase de datos también pueden ser enums y se asignarán automáticamente. .{data-version:3.2.4}
+
 ¿Cómo decirle a Nette que nos devuelva datos como objetos de esta clase? Más fácil de lo que piensas. Todo lo que tienes que hacer es especificar el nombre de la clase u objeto a hidratar como parámetro:
 
 ```php
@@ -258,6 +260,8 @@ El mapeo entonces sabe por el tipo de propiedad `$person` que debe mapear el con
 $person->setMappedType(PersonFormData::class);
 ```
 
+Puede generar una propuesta para la clase de datos de un formulario utilizando el método `Nette\Forms\Blueprint::dataClass($form)`, que la imprimirá en la página del navegador. A continuación, puede simplemente hacer clic para seleccionar y copiar el código en su proyecto. .{data-version:3.1.15}
+
 
 Botones de envío múltiples .[#toc-multiple-submit-buttons]
 ==========================================================
diff --git a/forms/es/validation.texy b/forms/es/validation.texy
index 9b7e35bc31..8b49641b8d 100644
--- a/forms/es/validation.texy
+++ b/forms/es/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Contraseña:')
 	->addRule($form::MinLength, 'La contraseña debe tener al menos %d caracteres', 8);
 ```
 
-Nette viene con una serie de reglas incorporadas cuyos nombres son constantes de la clase `Nette\Forms\Form`:
+**Las reglas de validación sólo se comprueban si el usuario ha rellenado el elemento.
 
-Podemos utilizar las siguientes reglas para todos los controles:
+Nette viene con una serie de reglas predefinidas cuyos nombres son constantes de la clase `Nette\Forms\Form`. Podemos aplicar estas reglas a todos los elementos:
 
 | constante | descripción | argumentos
 |-------
@@ -38,7 +38,11 @@ Podemos utilizar las siguientes reglas para todos los controles:
 | `IsNotIn` | El valor no es igual a ningún elemento de la matriz. `array`
 | `Valid` | la entrada pasa la validación (para [condiciones |#conditions]) | -
 
-Para los controles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` también se pueden utilizar las siguientes reglas:
+
+Entradas de texto .[#toc-text-inputs]
+-------------------------------------
+
+Para los elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` también se pueden aplicar algunas de las siguientes reglas:
 
 | `MinLength` | longitud mínima de cadena | `int`
 | `MaxLength` | longitud máxima de cadena | `int`
@@ -57,9 +61,23 @@ Para los controles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`,
 Las reglas `Integer`, `Numeric` a `Float` convierten automáticamente el valor a entero (o flotante respectivamente). Además, la regla `URL` también acepta una dirección sin esquema (por ejemplo, `nette.org`) y completa el esquema (`https://nette.org`).
 Las expresiones de `Pattern` y `PatternInsensitive` deben ser válidas para todo el valor, es decir, como si estuviera envuelto en los caracteres `^` and `$`.
 
+
+Número de artículos .[#toc-number-of-items]
+-------------------------------------------
+
+Para los elementos `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` también puede utilizar las siguientes reglas para limitar el número de elementos seleccionados o archivos cargados:
+
+| `MinLength` | número mínimo | `int`
+| `MaxLength` Número máximo `int`
+| `Length` | número en rango o número exacto | pares `[int, int]` o `int`
+
+
+Carga de archivos
+-----------------
+
 Para los controles `addUpload()`, `addMultiUpload()` también se pueden utilizar las siguientes reglas:
 
-| `MaxFileSize` | tamaño máximo del archivo | `int`
+| `MaxFileSize` | tamaño máximo del archivo en bytes | `int`
 | `MimeType` | tipo de MIME, acepta comodines (`'video/*'`) | `string\|string[]`
 | `Image` | el archivo cargado es JPEG, PNG, GIF, WebP | -
 | `Pattern` | nombre de archivo coincide con expresión regular | `string`
@@ -67,15 +85,9 @@ Para los controles `addUpload()`, `addMultiUpload()` también se pueden utilizar
 
 `MimeType` y `Image` requieren la extensión PHP `fileinfo`. Si un archivo o imagen es del tipo requerido se detecta por su firma. No se comprueba la integridad de todo el archivo. Puede averiguar si una imagen no está dañada, por ejemplo, intentando [cargarla |http:request#toImage].
 
-Para los controles `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` también se pueden utilizar las siguientes reglas para limitar el número de elementos seleccionados, respectivamente archivos cargados:
-
-| `MinLength` | recuento mínimo | `int`
-| `MaxLength` | recuento máximo `int`
-| `Length` | recuento en rango o recuento exacto | par `[int, int]` o `int`
-
 
 Mensajes de error .[#toc-error-messages]
-----------------------------------------
+========================================
 
 Todas las reglas predefinidas excepto `Pattern` y `PatternInsensitive` tienen un mensaje de error por defecto, por lo que pueden omitirse. Sin embargo, al pasar y formular todos los mensajes personalizados, hará que el formulario sea más fácil de usar.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 En Nette, es muy fácil reaccionar al cumplimiento o no de una condición en la parte JavaScript utilizando el método `toggle()`, véase [JavaScript dinámico |#Dynamic JavaScript].
 
 
-Referencias entre Controles .[#toc-references-between-controls]
+Referencia a otro elemento .[#toc-reference-to-another-element]
 ===============================================================
 
-El argumento de la regla o condición puede ser una referencia a otro elemento. Por ejemplo, puede validar dinámicamente que `text` tenga tantos caracteres como el valor del campo `length`:
+Como argumento para una regla o condición, también puede pasar otro elemento del formulario. La regla utilizará entonces el valor introducido posteriormente por el usuario en el navegador. Esto se puede utilizar, por ejemplo, para validar dinámicamente que el elemento `password` contiene la misma cadena que el elemento `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Este script es `netteForms.js`, que está disponible en varias fuentes posibles:
 Puedes incrustar el script directamente en la página HTML desde el CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 O copiarlo localmente en la carpeta pública del proyecto (por ejemplo, desde `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/fr/controls.texy b/forms/fr/controls.texy
index 89528a8818..bd6c7d9675 100644
--- a/forms/fr/controls.texy
+++ b/forms/fr/controls.texy
@@ -5,8 +5,8 @@ Contrôles de formulaires
 Aperçu des contrôles de formulaires intégrés.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Ajoute un champ de texte à une ligne (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Si l'utilisateur ne remplit pas le champ, il renvoie une chaîne vide `''`, ou utilise `setNullable()` pour le modifier et renvoyer `null`.
 
@@ -20,13 +20,10 @@ Il valide automatiquement l'UTF-8, coupe les espaces à gauche et à droite et s
 
 La longueur maximale peut être limitée en utilisant `setMaxLength()`. La [fonction addFilter() |validation#Modifying Input Values] permet de modifier la valeur saisie par l'utilisateur.
 
-Utilisez `setHtmlType()` pour changer le [caractère |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] de l'élément d'entrée en `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Au lieu des types `number` et `email`, nous vous recommandons d'utiliser [addInteger |#addInteger] et [addEmail |#addEmail], qui fournissent une validation côté serveur.
+Vous pouvez modifier le caractère visuel d'un champ de texte en utilisant des types tels que `search`, `tel`, ou `url` en utilisant `setHtmlType()`, comme indiqué dans la [spécification |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. N'oubliez pas que le changement de type n'est que visuel et qu'il n'exécute pas de fonctions de validation. Pour le type `url`, il convient d'ajouter une [règle URL |validation#Text inputs] spécifique.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Pour les autres types d'entrée tels que `number`, `range`, `email`, `date`, `datetime-local`, `time`, et `color`, utilisez des méthodes spécialisées telles que [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime], et [addColor |#addColor], qui assurent la validation côté serveur. Les types `month` et `week` ne sont pas encore totalement pris en charge par tous les navigateurs.
 
 La valeur dite vide peut être définie pour l'élément, qui ressemble à la valeur par défaut, mais si l'utilisateur ne l'écrase pas, elle renvoie une chaîne vide ou `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Ajoute un champ de saisie pour un nombre entier (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Renvoie soit un entier, soit `null` si l'utilisateur ne saisit rien.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'L'année doit être comprise entre %d et %d.', [1900, 2023 |1900, 2023]) ;
+```
+
+L'élément est rendu sous la forme `<input type="numeric">`. En utilisant la méthode `setHtmlType()`, vous pouvez changer le type en `range` pour l'afficher comme un curseur, ou en `text` si vous préférez un champ de texte standard sans le comportement spécial de `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('niveau', 'Niveau:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'Le niveau doit être compris entre %d et %d.', [0, 100 |0, 100]) ;
 ```
 
+L'élément est rendu sous la forme `<input type="numeric">`. En utilisant la méthode `setHtmlType()`, vous pouvez changer le type en `range` pour l'afficher comme un curseur, ou en `text` si vous préférez un champ de texte standard sans le comportement spécial de `numeric`.
+
+Nette et le navigateur Chrome acceptent à la fois une virgule et un point comme séparateurs décimaux. Pour que cette fonctionnalité soit disponible dans Firefox, il est recommandé de définir l'attribut `lang` soit pour l'élément spécifique, soit pour la page entière, par exemple, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Ajoute un champ d'adresse électronique avec contrôle de validité (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Si l'utilisateur ne remplit pas le champ, il renvoie une chaîne vide `''`, ou utilise `setNullable()` pour le modifier et renvoyer `null`.
 
@@ -78,8 +92,8 @@ Vérifie que la valeur est une adresse électronique valide. Il ne vérifie pas
 La longueur maximale peut être limitée en utilisant `setMaxLength()`. La [fonction addFilter() |validation#Modifying Input Values] vous permet de modifier la valeur saisie par l'utilisateur. Vous pouvez définir la valeur dite vide à l'aide de `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Ajoute un champ de mot de passe (classe [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Ajoute une liste de cases à cocher pour sélectionner plusieurs éléments (classe [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Renvoie le tableau des clés des éléments sélectionnés. La méthode `getSelectedItems()` renvoie des valeurs au lieu des clés.
 
@@ -125,9 +139,15 @@ L'élément vérifie automatiquement qu'il n'y a pas eu de falsification et que
 
 Lorsque des valeurs par défaut sont définies, la méthode vérifie également qu'il s'agit de l'un des éléments proposés, sinon elle lève une exception. Cette vérification peut être désactivée avec `checkDefaultValue(false)`.
 
+Si vous soumettez un formulaire à l'aide de la méthode `GET`, vous pouvez choisir une méthode de transfert de données plus compacte qui réduit la taille de la chaîne de requête. Cette option est activée en définissant l'attribut HTML du formulaire :
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Ajoute des boutons radio (classe [RadioList |api:Nette\Forms\Controls\RadioList]). Renvoie la clé de l'élément sélectionné, ou `null` si l'utilisateur n'a rien sélectionné. La méthode `getSelectedItem()` renvoie une valeur au lieu d'une clé.
 
@@ -148,8 +168,8 @@ L'élément vérifie automatiquement qu'il n'y a pas eu de falsification et que
 Lorsque la valeur par défaut est définie, elle vérifie également qu'il s'agit de l'un des éléments proposés, sinon elle lève une exception. Cette vérification peut être désactivée avec `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Ajoute une boîte de sélection (classe [SelectBox |api:Nette\Forms\Controls\SelectBox]). Renvoie la clé de l'élément sélectionné, ou `null` si l'utilisateur n'a rien sélectionné. La méthode `getSelectedItem()` renvoie une valeur au lieu d'une clé.
 
@@ -193,8 +213,8 @@ L'élément vérifie automatiquement qu'il n'y a pas eu de falsification et que
 Lorsque la valeur par défaut est définie, elle vérifie également qu'il s'agit de l'un des éléments proposés, sinon elle lève une exception. Cette vérification peut être désactivée avec `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Ajoute une boîte de sélection multichoix (classe [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Renvoie le tableau des clés des éléments sélectionnés. La méthode `getSelectedItems()` renvoie des valeurs au lieu des clés.
 
@@ -246,8 +266,81 @@ Ne vous fiez pas aux noms de fichiers originaux renvoyés par la méthode `FileU
 Les règles `MimeType` et `Image` détectent le type de fichier ou d'image requis par sa signature. L'intégrité de l'ensemble du fichier n'est pas vérifiée. Vous pouvez savoir si une image n'est pas corrompue, par exemple en essayant de [la charger |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Ajoute un champ qui permet à l'utilisateur de saisir facilement une date composée de l'année, du mois et du jour (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Pour la valeur par défaut, il accepte soit des objets implémentant la classe `DateTimeInterface`, soit une chaîne de caractères avec l'heure, soit un nombre représentant un horodatage UNIX. Il en va de même pour les arguments `Min`, `Max` ou `Range`, qui définissent la date minimale et maximale autorisée.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Par défaut, elle renvoie un objet `DateTimeImmutable`. La méthode `setFormat()` permet de spécifier un [format texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou un horodatage :
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Ajoute un champ qui permet à l'utilisateur de saisir facilement l'heure sous forme d'heures, de minutes et éventuellement de secondes (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Pour la valeur par défaut, il accepte soit des objets implémentant `DateTimeInterface`, soit une chaîne de caractères avec l'heure, soit un nombre représentant un horodatage UNIX. Seule l'information temporelle de ces entrées est utilisée ; la date est ignorée. Il en va de même pour les arguments `Min`, `Max` ou `Range`, qui définissent la durée minimale et maximale autorisée. Si la valeur minimale définie est supérieure à la valeur maximale, une plage horaire s'étendant jusqu'à minuit est créée.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Par défaut, elle renvoie un objet `DateTimeImmutable` (avec la date du 1er janvier de l'année 1). La méthode `setFormat()` permet de spécifier un [format de texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Ajoute un champ qui permet à l'utilisateur de saisir facilement la date et l'heure en indiquant l'année, le mois, le jour, les heures, les minutes et, éventuellement, les secondes (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Pour la valeur par défaut, il accepte soit des objets implémentant la classe `DateTimeInterface`, soit une chaîne de caractères avec l'heure, soit un nombre représentant un horodatage UNIX. Il en va de même pour les arguments `Min`, `Max` ou `Range`, qui définissent la date minimale et maximale autorisée.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Par défaut, elle renvoie un objet `DateTimeImmutable`. La méthode `setFormat()` permet de spécifier un [format texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou un horodatage :
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Ajoute un champ de sélection de couleur (classe [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). La couleur est une chaîne au format `#rrggbb`. Si l'utilisateur ne fait pas de sélection, la couleur renvoyée par défaut est le noir `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Ajoute un champ caché (classe [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Utilisez `setNullable()` pour le modifier afin qu'il renvoie `null` au lieu d'une chaîne vide. La [fonction addFilter() |validation#Modifying Input Values] permet de modifier la valeur soumise.
 
+Bien que l'élément soit caché, il est **important de réaliser** que sa valeur peut toujours être modifiée ou usurpée par un attaquant. Il faut toujours vérifier et valider soigneusement toutes les valeurs reçues du côté du serveur pour éviter les risques de sécurité liés à la manipulation des données.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Ajoute un bouton d'envoi sous la forme d'une image (classe [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Les méthodes suivantes peuvent être appelées pour les éléments `addText()`,
 
 
 Valeurs omises .[#toc-omitted-values]
--------------------------------------
+=====================================
 
 Si la valeur saisie par l'utilisateur ne vous intéresse pas, nous pouvons utiliser `setOmitted()` pour l'omettre du résultat fourni par la méthode `$form->getValues​()` ou transmis aux gestionnaires. Cela convient pour divers mots de passe à des fins de vérification, des champs antispam, etc.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Désactiver les entrées .[#toc-disabling-inputs]
------------------------------------------------
+===============================================
 
-Pour désactiver une entrée, vous pouvez appeler `setDisabled()`. Un tel champ ne peut pas être modifié par l'utilisateur.
+Les entrées peuvent être désactivées à l'aide de `setDisabled()`. Une entrée désactivée ne peut pas être modifiée par l'utilisateur.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Notez que le navigateur n'envoie pas du tout les champs désactivés au serveur, de sorte que vous ne les trouverez même pas dans les données renvoyées par la fonction `$form->getValues()`.
+Les entrées désactivées ne sont pas envoyées au serveur par le navigateur, et vous ne les trouverez donc pas dans les données renvoyées par la fonction `$form->getValues()`. Toutefois, si vous définissez `setOmitted(false)`, Nette inclura leur valeur par défaut dans ces données.
 
-Si vous définissez une valeur par défaut pour un champ, vous devez le faire uniquement après l'avoir désactivé :
+Lorsque `setDisabled()` est appelé, **la valeur de l'entrée est effacée** pour des raisons de sécurité. Si vous définissez une valeur par défaut, il est nécessaire de le faire après sa désactivation :
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Une alternative aux entrées désactivées sont les champs avec l'attribut HTML `readonly`, qui sont envoyés au serveur par le navigateur. Bien que le champ ne soit que lisible, il est **important de réaliser** que sa valeur peut toujours être modifiée ou usurpée par un attaquant.
+
 
 Contrôles personnalisés .[#toc-custom-controls]
 ===============================================
@@ -428,8 +525,8 @@ Il est possible de définir de nouvelles méthodes de formulaire pour ajouter de
 ```php
 use Nette\Forms\Container;
 
-// ajoute la méthode addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// ajoute la méthode addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/fr/in-presenter.texy b/forms/fr/in-presenter.texy
index 0fb310f2cb..2932ff8eb7 100644
--- a/forms/fr/in-presenter.texy
+++ b/forms/fr/in-presenter.texy
@@ -30,7 +30,7 @@ Le formulaire dans le présentateur est un objet de la classe `Nette\Application
 
 Du point de vue du présentateur, le formulaire est un composant commun. Par conséquent, il est traité comme un composant et incorporé dans le présentateur à l'aide de la [méthode factory |application:components#Factory Methods]. Cela ressemblera à ceci :
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Et le rendu dans le modèle est effectué à l'aide de la balise `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Le formulaire est toujours validé du côté du serveur, mais la validation Java
 Insérez-le dans le modèle de mise en page :
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Si vous regardez dans le code source de la page avec formulaire, vous pouvez remarquer que Nette insère les champs obligatoires dans des éléments avec une classe CSS `required`. Essayez d'ajouter le style suivant au modèle, et l'étiquette "Nom" sera rouge. De manière élégante, nous marquons les champs obligatoires pour les utilisateurs :
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-A partir de PHP 8.0, vous pouvez utiliser cette notation élégante qui utilise un constructeur :
+Vous pouvez également utiliser le constructeur :
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Les propriétés de la classe de données peuvent également être des enums et elles seront automatiquement mappées. .{data-version:3.2.4}
+
 Comment dire à Nette de retourner les données sous forme d'objets de cette classe ? C'est plus facile que vous ne le pensez. Tout ce que vous avez à faire est de spécifier la classe comme type du paramètre `$data` dans le gestionnaire :
 
 ```php
@@ -294,6 +296,8 @@ Le mappage sait alors, à partir du type de propriété `$person`, qu'il doit ma
 $person->setMappedType(PersonFormData::class);
 ```
 
+Vous pouvez générer une proposition pour la classe de données d'un formulaire à l'aide de la méthode `Nette\Forms\Blueprint::dataClass($form)`, qui l'imprimera sur la page du navigateur. Il vous suffit ensuite de cliquer pour sélectionner et copier le code dans votre projet. .{data-version:3.1.15}
+
 
 Boutons d'envoi multiples .[#toc-multiple-submit-buttons]
 =========================================================
diff --git a/forms/fr/rendering.texy b/forms/fr/rendering.texy
index 2915a9b2c9..30735f39b2 100644
--- a/forms/fr/rendering.texy
+++ b/forms/fr/rendering.texy
@@ -11,6 +11,8 @@ Rendu avec Latte .[#toc-rendering-with-latte]
 
 Le [système de templates Latte |latte:] facilite fondamentalement le rendu des formulaires et de leurs éléments. Nous allons d'abord montrer comment rendre les formulaires manuellement, élément par élément, afin d'avoir un contrôle total sur le code. Plus tard, nous montrerons comment [automatiser |#Automatic rendering] ce rendu.
 
+Vous pouvez obtenir la proposition d'un modèle Latte pour le formulaire généré à l'aide de la méthode `Nette\Forms\Blueprint::latte($form)`, qui l'affichera sur la page du navigateur. Il vous suffit ensuite de sélectionner le code d'un clic et de le copier dans votre projet. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Les éléments de formulaire plus complexes, tels que RadioList ou CheckboxList,
 ```
 
 
-Proposition de code `{formPrint}` .[#toc-formprint]
----------------------------------------------------
-
-Vous pouvez générer un code latte similaire pour un formulaire en utilisant la balise `{formPrint}`. Si vous le placez dans un modèle, vous verrez le projet de code au lieu du rendu normal. Il suffit ensuite de le sélectionner et de le copier dans votre projet.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Vous ne devez importer le bloc qu'à un seul endroit, au début du modèle de mi
 Cas particuliers .[#toc-special-cases]
 --------------------------------------
 
-Si vous avez seulement besoin de rendre le contenu interne d'un formulaire sans `<form>` & `</form>` HTML, par exemple dans une requête AJAX, vous pouvez ouvrir et fermer le formulaire à l'aide de `{formContext} … {/formContext}`. Son fonctionnement est similaire à celui de `{form}` d'un point de vue logique, puisqu'il vous permet d'utiliser d'autres balises pour dessiner des éléments de formulaire, mais en même temps, il ne dessine rien.
+Si vous devez rendre uniquement la partie intérieure du formulaire sans balises HTML, par exemple lors de l'envoi d'extraits, masquez-les à l'aide de l'attribut . `<form>`par exemple lors de l'envoi d'extraits, masquez-les à l'aide de l'attribut `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 La balise `formContainer` aide à rendre les entrées à l'intérieur d'un conteneur de formulaire.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Le moteur de rendu dessine d'abord les groupes, puis les éléments qui n'appartiennent à aucun groupe.
+
 
 Support Bootstrap .[#toc-bootstrap-support]
 -------------------------------------------
@@ -444,7 +442,7 @@ Vous trouverez des [exemples |https://github.com/nette/forms/tree/master/example
 Attributs HTML .[#toc-html-attributes]
 ======================================
 
-Vous pouvez définir n'importe quel attribut HTML pour les contrôles de formulaires en utilisant `setHtmlAttribute(string $name, $value = true)`:
+Pour définir des attributs HTML arbitraires pour les éléments de formulaire, utilisez la méthode `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // appelle la fonction JS submit() en cas de modification.
 
 
-// application sur <form>
+// Pour définir les attributs du site <form> lui-même
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Définition du type d'entrée :
+Spécification du type d'élément :
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-Nous pouvons définir l'attribut HTML à des éléments individuels dans des listes de radio ou de cases à cocher avec des valeurs différentes pour chacun d'eux.
-Notez les deux points après `style:` pour vous assurer que la valeur est sélectionnée par la clé :
+.[warning]
+La définition du type et d'autres attributs ne sert qu'à des fins visuelles. La vérification de l'exactitude des entrées doit avoir lieu sur le serveur, ce que vous pouvez faire en choisissant un [contrôle de formulaire | controls] approprié et en spécifiant des [règles de validation | validation].
+
+Pour les éléments individuels des listes de radios ou de cases à cocher, nous pouvons définir un attribut HTML avec des valeurs différentes pour chacun d'entre eux.
+Remarquez les deux points après `style:`, qui garantissent que la valeur est sélectionnée en fonction de la clé :
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders :
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Pour un attribut HTML logique (qui n'a pas de valeur, comme `readonly`), vous pouvez utiliser un point d'interrogation :
+Pour définir des attributs booléens, tels que `readonly`, nous pouvons utiliser la notation avec un point d'interrogation :
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // utiliser un tableau pour les clés multiples, par exemple ['r', 'g'].
 ```
@@ -541,9 +541,6 @@ Pour les éléments Checkbox, CheckboxList et RadioList, vous pouvez influencer
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/fr/standalone.texy b/forms/fr/standalone.texy
index ea3843cd3e..e7e3a31c2e 100644
--- a/forms/fr/standalone.texy
+++ b/forms/fr/standalone.texy
@@ -107,7 +107,7 @@ Le formulaire est toujours validé du côté du serveur, mais la validation Java
 Ajoutez-le à la page :
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Si vous regardez dans le code source de la page avec formulaire, vous pouvez remarquer que Nette insère les champs obligatoires dans des éléments avec une classe CSS `required`. Essayez d'ajouter le style suivant au modèle, et l'étiquette "Nom" sera rouge. De manière élégante, nous marquons les champs obligatoires pour les utilisateurs :
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-A partir de PHP 8.0, vous pouvez utiliser cette notation élégante qui utilise un constructeur :
+Vous pouvez également utiliser le constructeur :
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Les propriétés de la classe de données peuvent également être des enums et elles seront automatiquement mappées. .{data-version:3.2.4}
+
 Comment dire à Nette de nous retourner les données sous forme d'objets de cette classe ? C'est plus facile que vous ne le pensez. Tout ce que vous avez à faire est de spécifier le nom de la classe ou de l'objet à hydrater comme paramètre :
 
 ```php
@@ -258,6 +260,8 @@ Le mappage sait alors, à partir du type de propriété `$person`, qu'il doit ma
 $person->setMappedType(PersonFormData::class);
 ```
 
+Vous pouvez générer une proposition pour la classe de données d'un formulaire à l'aide de la méthode `Nette\Forms\Blueprint::dataClass($form)`, qui l'imprimera sur la page du navigateur. Il vous suffit ensuite de cliquer pour sélectionner et copier le code dans votre projet. .{data-version:3.1.15}
+
 
 Boutons d'envoi multiples .[#toc-multiple-submit-buttons]
 =========================================================
diff --git a/forms/fr/validation.texy b/forms/fr/validation.texy
index 361456d8c7..479ffcdd3e 100644
--- a/forms/fr/validation.texy
+++ b/forms/fr/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette est livré avec un certain nombre de règles intégrées dont les noms sont des constantes de la classe `Nette\Forms\Form`:
+**Les règles de validation ne sont vérifiées que si l'utilisateur a rempli l'élément.
 
-Nous pouvons utiliser les règles suivantes pour tous les contrôles :
+Nette est livré avec un certain nombre de règles prédéfinies dont les noms sont des constantes de la classe `Nette\Forms\Form`. Nous pouvons appliquer ces règles à tous les éléments :
 
 | constante | description | arguments
 |-------
@@ -38,7 +38,11 @@ Nous pouvons utiliser les règles suivantes pour tous les contrôles :
 | `IsNotIn` | la valeur n'est égale à aucun élément du tableau | `array`
 | `Valid` | L'entrée passe la validation (pour les [conditions |#conditions]) | -
 
-Pour les contrôles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` les règles suivantes peuvent également être utilisées :
+
+Entrées de texte .[#toc-text-inputs]
+------------------------------------
+
+Pour les éléments `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()`, certaines des règles suivantes peuvent également être appliquées :
 
 | `MinLength` | longueur minimale de la chaîne | `int`
 | `MaxLength` | longueur maximale de la chaîne de caractères | `int`
@@ -57,9 +61,23 @@ Pour les contrôles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`,
 Les règles `Integer`, `Numeric` et `Float` convertissent automatiquement la valeur en nombre entier (ou flottant respectivement). En outre, la règle `URL` accepte également une adresse sans schéma (par exemple `nette.org`) et complète le schéma (`https://nette.org`).
 Les expressions de `Pattern` et `PatternInsensitive` doivent être valables pour la valeur entière, c'est-à-dire comme si elle était enveloppée dans les caractères `^` and `$`.
 
+
+Nombre d'articles .[#toc-number-of-items]
+-----------------------------------------
+
+Pour les éléments `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` vous pouvez également utiliser les règles suivantes pour limiter le nombre d'éléments sélectionnés ou de fichiers téléchargés :
+
+ `MinLength` | nombre minimum | | nombre maximum `int`
+| `MaxLength` | nombre maximum `int`
+| `Length` | nombre dans l'intervalle ou nombre exact | paires `[int, int]` ou `int`
+
+
+Téléchargement de fichiers
+--------------------------
+
 Pour les contrôles `addUpload()`, `addMultiUpload()`, les règles suivantes peuvent également être utilisées :
 
-| `MaxFileSize` | taille maximale du fichier | `int`
+| `MaxFileSize` | taille maximale du fichier en octets | `int`
 `MimeType` | type MIME, accepte les caractères génériques (`'video/*'`) | type MIME, accepte les caractères génériques ( ) | type MIME, accepte les caractères génériques ( ) `string\|string[]`
 | `Image` | le fichier téléchargé est un JPEG, PNG, GIF, WebP | -
 | `Pattern` | le nom du fichier correspond à une expression régulière | `string`
@@ -67,15 +85,9 @@ Pour les contrôles `addUpload()`, `addMultiUpload()`, les règles suivantes peu
 
 Les sites `MimeType` et `Image` nécessitent l'extension PHP `fileinfo`. Le fait qu'un fichier ou une image soit du type requis est détecté par sa signature. L'intégrité de l'ensemble du fichier n'est pas vérifiée. Vous pouvez savoir si une image n'est pas corrompue, par exemple en essayant de [la charger |http:request#toImage].
 
-Pour les contrôles `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()`, les règles suivantes peuvent également être utilisées pour limiter le nombre d'éléments sélectionnés, respectivement de fichiers téléchargés :
-
-| `MinLength` | compte minimal | `int`
-| `MaxLength` | compte maximal | `int`
-| `Length` | compte dans l'intervalle ou compte exact | paire `[int, int]` ou `int`
-
 
 Messages d'erreur .[#toc-error-messages]
-----------------------------------------
+========================================
 
 Toutes les règles prédéfinies, à l'exception de `Pattern` et `PatternInsensitive`, ont un message d'erreur par défaut ; elles peuvent donc être omises. Toutefois, en passant et en formulant tous les messages personnalisés, vous rendrez le formulaire plus convivial.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 Dans Nette, il est très facile de réagir à la réalisation ou non d'une condition du côté JavaScript en utilisant la méthode `toggle()`, voir [Dynamic JavaScript |#Dynamic JavaScript].
 
 
-Références entre les contrôles .[#toc-references-between-controls]
-==================================================================
+Référence à un autre élément .[#toc-reference-to-another-element]
+=================================================================
 
-L'argument de la règle ou de la condition peut être une référence à un autre élément. Par exemple, vous pouvez valider dynamiquement que le champ `text` comporte autant de caractères que la valeur du champ `length`:
+En tant qu'argument d'une règle ou d'une condition, vous pouvez également transmettre un autre élément de formulaire. La règle utilisera alors la valeur introduite ultérieurement par l'utilisateur dans le navigateur. Cela peut être utilisé, par exemple, pour valider dynamiquement que l'élément `password` contient la même chaîne de caractères que l'élément `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Ce script est `netteForms.js`, qui est disponible à partir de plusieurs sources
 Vous pouvez intégrer le script directement dans la page HTML à partir du CDN :
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ou le copier localement dans le dossier public du projet (par exemple à partir de `vendor/nette/forms/src/assets/netteForms.min.js`) :
diff --git a/forms/hu/controls.texy b/forms/hu/controls.texy
index 8c00e73adc..f8d87e005c 100644
--- a/forms/hu/controls.texy
+++ b/forms/hu/controls.texy
@@ -5,8 +5,8 @@ Nyomtatvány vezérlők
 A beépített űrlapvezérlők áttekintése.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Egysoros szövegmező hozzáadása ( [TextInput |api:Nette\Forms\Controls\TextInput] osztály). Ha a felhasználó nem tölti ki a mezőt, akkor egy üres karakterláncot ad vissza `''`, vagy a `setNullable()` segítségével megváltoztatja, hogy `null` adjon vissza.
 
@@ -20,13 +20,10 @@ Automatikusan érvényesíti az UTF-8 szabványt, levágja a bal és jobb oldali
 
 A maximális hossz a `setMaxLength()` segítségével korlátozható. Az [addFilter() |validation#Modifying Input Values] lehetővé teszi a felhasználó által megadott érték megváltoztatását.
 
-A `setHtmlType()` segítségével a `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color` beviteli elem [karakterét |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] módosíthatja. A `number` és `email` típusok helyett az [addInteger |#addInteger] és az [addEmail |#addEmail] típusok használatát javasoljuk, amelyek szerveroldali érvényesítést biztosítanak.
+A szövegmező vizuális karakterét a `search`, `tel` vagy `url` típusokra változtathatja a `setHtmlType()` segítségével, ahogyan az a [specifikációban |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] látható. Ne feledje, hogy a típus megváltoztatása csak vizuális, és nem végez érvényesítési funkciókat. A `url` típushoz célszerű egy speciális [URL-szabályt |validation#Text inputs] hozzáadni.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Más bemeneti típusokhoz, mint például a `number`, `range`, `email`, `date`, `datetime-local`, `time` és `color`, használjon speciális módszereket, mint például az [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] és [addColor |#addColor], amelyek biztosítják a szerveroldali érvényesítést. A `month` és a `week` típusok még nem támogatottak teljes mértékben minden böngészőben.
 
 Az elemhez beállítható az úgynevezett üres-érték, ami valami olyasmi, mint az alapértelmezett érték, de ha a felhasználó nem írja felül, akkor üres stringet vagy `null` ad vissza.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Egész számok beviteli mezőjének hozzáadása ( [TextInput |api:Nette\Forms\Controls\TextInput] osztály). Egész számot vagy a `null` értéket adja vissza, ha a felhasználó nem ad meg semmit.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('year', 'Év:')
+	->addRule($form::Range, 'Az évnek a %d és %d közötti tartományban kell lennie.', [1900, 2023 |1900, 2023]);
+```
+
+Az elemet a következő módon jeleníti meg `<input type="numeric">`. A `setHtmlType()` metódus használatával a típust `range` -re változtathatja a csúszkaként való megjelenítéshez, vagy `text` -re, ha a `numeric` speciális viselkedése nélküli normál szövegmezőt szeretné.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('szint', 'Szint:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'A szintnek a %d és %d közötti tartományban kell lennie.', [0, 100 |0, 100]);
 ```
 
+Az elemet a következő módon jeleníti meg `<input type="numeric">`. A `setHtmlType()` metódus használatával a típust `range` -re változtathatja a csúszkaként való megjelenítéshez, vagy `text` -re, ha a `numeric` speciális viselkedése nélküli normál szövegmezőt szeretné.
+
+A Nette és a Chrome böngésző a vesszőt és a pontot is elfogadja tizedesválasztóként. Ahhoz, hogy ez a funkció a Firefoxban is elérhető legyen, ajánlott a `lang` attribútumot beállítani például az adott elemre vagy az egész oldalra, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 E-mail cím mező hozzáadása érvényességi ellenőrzéssel ( [TextInput |api:Nette\Forms\Controls\TextInput] osztály). Ha a felhasználó nem tölti ki a mezőt, akkor egy üres karakterláncot ad vissza `''`, vagy a `setNullable()` segítségével megváltoztatja, hogy `null` adjon vissza.
 
@@ -78,8 +92,8 @@ Ellenőrzi, hogy az érték érvényes e-mail cím-e. Nem ellenőrzi, hogy a dom
 A maximális hossz a `setMaxLength()` segítségével korlátozható. Az [addFilter() |validation#Modifying Input Values] lehetővé teszi a felhasználó által megadott érték megváltoztatását. Az úgynevezett üres értéket a `setEmptyValue()` segítségével állíthatja be.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Jelszó mező hozzáadása ( [TextInput |api:Nette\Forms\Controls\TextInput] osztály).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Több elem kiválasztására szolgáló jelölőnégyzetek listájának hozzáadása ( [CheckboxList |api:Nette\Forms\Controls\CheckboxList] osztály). Visszaadja a kiválasztott elemek kulcsainak tömbjét. A `getSelectedItems()` módszer kulcsok helyett értékeket ad vissza.
 
@@ -125,9 +139,15 @@ Az elem automatikusan ellenőrzi, hogy nem történt-e hamisítás, és hogy a k
 
 Alapértelmezett értékek beállítása esetén azt is ellenőrzi, hogy azok a felkínált elemek közé tartoznak-e, ellenkező esetben kivételt dob. Ez az ellenőrzés kikapcsolható a `checkDefaultValue(false)` segítségével.
 
+Ha egy űrlapot a `GET` módszerrel küld el, választhat egy kompaktabb adatátviteli módszert, amely megtakarítja a lekérdezési karakterlánc méretét. Ezt az űrlap HTML-attribútumának beállításával lehet aktiválni:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Rádiógombok hozzáadása ( [RadioList |api:Nette\Forms\Controls\RadioList] osztály). Visszaadja a kiválasztott elem kulcsát, vagy `null`, ha a felhasználó nem választott ki semmit. A `getSelectedItem()` metódus kulcs helyett értéket ad vissza.
 
@@ -148,8 +168,8 @@ Az elem automatikusan ellenőrzi, hogy nem történt-e hamisítás, és hogy a k
 Alapértelmezett érték beállítása esetén azt is ellenőrzi, hogy a felajánlott elemek egyike-e, ellenkező esetben kivételt dob. Ez az ellenőrzés kikapcsolható a `checkDefaultValue(false)` segítségével.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Kijelölő doboz hozzáadása ( [SelectBox |api:Nette\Forms\Controls\SelectBox] osztály). Visszaadja a kiválasztott elem kulcsát, vagy `null`, ha a felhasználó nem választott ki semmit. A `getSelectedItem()` metódus kulcs helyett értéket ad vissza.
 
@@ -193,8 +213,8 @@ Az elem automatikusan ellenőrzi, hogy nem történt-e hamisítás, és hogy a k
 Alapértelmezett érték beállítása esetén azt is ellenőrzi, hogy a felajánlott elemek egyike-e, ellenkező esetben kivételt dob. Ez az ellenőrzés kikapcsolható a `checkDefaultValue(false)` segítségével.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Hozzáadja a többválasztós kiválasztó dobozt ( [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox] osztály). Visszaadja a kiválasztott elemek kulcsainak tömbjét. A `getSelectedItems()` módszer kulcsok helyett értékeket ad vissza.
 
@@ -246,8 +266,81 @@ Ne bízzon a `FileUpload::getName()` módszer által visszaküldött eredeti fá
 A `MimeType` és a `Image` szabályok az aláírás alapján ismerik fel a kívánt fájl- vagy képtípust. A teljes fájl sértetlenségét nem ellenőrzik. Azt, hogy egy kép nem sérült-e, például a [betöltési |http:request#toImage] próbálkozással állapíthatja meg.
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Hozzáad egy mezőt, amely lehetővé teszi a felhasználó számára, hogy egyszerűen beírjon egy dátumot, amely évből, hónapból és napból áll ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] osztály).
+
+Alapértelmezett értékként elfogadja a `DateTimeInterface` objektumokat megvalósító objektumokat, az időt tartalmazó karakterláncot, vagy egy UNIX időbélyeget reprezentáló számot. Ugyanez vonatkozik a `Min`, `Max` vagy `Range` szabály argumentumaira is, amelyek a minimális és maximálisan megengedett dátumot határozzák meg.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza. A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] vagy időbélyeget adhat meg:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Hozzáad egy mezőt, amely lehetővé teszi a felhasználó számára, hogy egyszerűen beírja az órákból, percekből és opcionálisan másodpercekből álló időt ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] osztály).
+
+Alapértelmezett értékként elfogadja a `DateTimeInterface` objektumokat megvalósító objektumokat, az időt tartalmazó karakterláncot vagy egy UNIX időbélyeget jelentő számot. Csak az ezekből a bemenetekből származó időinformáció kerül felhasználásra; a dátumot figyelmen kívül hagyja. Ugyanez vonatkozik a `Min`, `Max` vagy `Range` szabály argumentumaira is, amelyek a minimális és maximális megengedett időt határozzák meg. Ha a beállított minimális érték nagyobb, mint a maximális, akkor egy éjfélig tartó időtartomány jön létre.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza (január 1-jei dátummal, 1. év). A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] adhat meg:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Hozzáad egy olyan mezőt, amely lehetővé teszi a felhasználó számára, hogy egyszerűen beírja a dátumot és az időt, amely évből, hónapból, napból, órából, percből és opcionálisan másodpercekből áll ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] osztály).
+
+Alapértelmezett értékként elfogadja a `DateTimeInterface` objektumokat megvalósító objektumokat, egy karakterláncot az idővel, vagy egy UNIX időbélyeget reprezentáló számot. Ugyanez vonatkozik a `Min`, `Max` vagy `Range` szabály argumentumaira is, amelyek a minimális és maximálisan megengedett dátumot határozzák meg.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza. A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] vagy időbélyeget adhat meg:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Hozzáad egy színválasztó mezőt ( [ColorPicker |api:Nette\Forms\Controls\ColorPicker] osztály). A szín egy karakterlánc a `#rrggbb` formátumban. Ha a felhasználó nem választ, a visszaküldött alapértelmezett szín a fekete `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Rejtett mező hozzáadása ( [HiddenField |api:Nette\Forms\Controls\HiddenField] osztály).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Használja a `setNullable()` címet, hogy üres karakterlánc helyett `null` -t adjon vissza. Az [addFilter() |validation#Modifying Input Values] lehetővé teszi a beküldött érték megváltoztatását.
 
+Bár az elem rejtve van, **fontos tudatosítani**, hogy az értékét egy támadó még mindig módosíthatja vagy meghamisíthatja. Az adatmanipulációval kapcsolatos biztonsági kockázatok megelőzése érdekében mindig alaposan ellenőrizze és validálja az összes kapott értéket a kiszolgálói oldalon.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Hozzáadja a submit gombot kép formájában ( [ImageButton |api:Nette\Forms\Controls\ImageButton] osztály).
 
@@ -377,7 +472,7 @@ A következő metódusok hívhatók a `addText()`, `addPassword()`, `addTextArea
 
 
 Kihagyott értékek .[#toc-omitted-values]
-----------------------------------------
+========================================
 
 Ha nem érdekel a felhasználó által megadott érték, a `setOmitted()` segítségével kihagyhatjuk azt a `$form->getValues​()` metódus által szolgáltatott vagy a kezelőknek átadott eredményből. Ez alkalmas különböző jelszavak ellenőrzésére, spamellenes mezőkhöz stb.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Bemenetek letiltása .[#toc-disabling-inputs]
---------------------------------------------
+============================================
 
-Egy bemenet letiltásához hívja a `setDisabled()` címet. Az ilyen mezőt a felhasználó nem szerkesztheti.
+A bemeneteket a `setDisabled()` segítségével lehet letiltani. A letiltott bemenetet a felhasználó nem tudja szerkeszteni.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Vegye figyelembe, hogy a böngésző egyáltalán nem küldi el a letiltott mezőket a szerverre, így a `$form->getValues()` függvény által visszaküldött adatokban sem fogja megtalálni őket.
+A letiltott bemeneteket a böngésző nem küldi el a kiszolgálónak, így a `$form->getValues()` funkció által visszaküldött adatokban sem találja meg őket. Ha azonban beállítja a `setOmitted(false)`, a Nette az alapértelmezett értéküket is tartalmazza ezekben az adatokban.
 
-Ha alapértelmezett értéket állít be egy mezőhöz, akkor ezt csak a mező letiltása után szabad megtennie:
+A `setDisabled()` meghívásakor **a bemenet értéke biztonsági okokból törlődik**. Ha alapértelmezett értéket állít be, akkor azt a deaktiválás után kell megtennie:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+A letiltott bejegyzések alternatívája a HTML `readonly` attribútummal rendelkező mezők, amelyeket a böngésző küld a kiszolgálónak. Bár a mező csak olvasható, **fontos tudatosítani**, hogy az értékét egy támadó még mindig módosíthatja vagy meghamisíthatja.
+
 
 Egyéni vezérlők .[#toc-custom-controls]
 =======================================
@@ -428,8 +525,8 @@ Van lehetőség új űrlapmódszerek definiálására az egyéni elemek hozzáad
 ```php
 use Nette\Forms\Container;
 
-// adds method addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// adds method addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Legalább 5 szám', '[0-9]{5}');
 });
diff --git a/forms/hu/in-presenter.texy b/forms/hu/in-presenter.texy
index d3bc0884a4..e7422c10ec 100644
--- a/forms/hu/in-presenter.texy
+++ b/forms/hu/in-presenter.texy
@@ -30,7 +30,7 @@ A prezenterben lévő űrlap a `Nette\Application\UI\Form` osztály objektuma, e
 
 A bemutató szempontjából az űrlap egy közös komponens. Ezért komponensként kezeljük, és a [factory metódus |application:components#Factory Methods] segítségével beépítjük a prezentálóba. Ez így fog kinézni:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 A sablonban történő megjelenítés pedig a `{control}` tag használatával történik:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Az űrlap mindig a szerveroldalon validálódik, de a JavaScript validáció is
 Ezt illessze be az elrendezési sablonba:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ha megnézi az űrlapot tartalmazó oldal forráskódját, észreveheti, hogy a Nette a szükséges mezőket a `required` CSS osztályú elemekbe illeszti be. Próbálja meg a következő stílust hozzáadni a sablonhoz, és a "Név" felirat piros lesz. Elegánsan jelöljük a kötelező mezőket a felhasználók számára:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-A PHP 8.0-tól kezdve használhatja ezt az elegáns jelölést, amely egy konstruktort használ:
+Alternatívaként használhatja a konstruktort is:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Az adatosztály tulajdonságai lehetnek enumok is, és automatikusan le lesznek képezve. .{data-version:3.2.4}
+
 Hogyan mondhatjuk meg a Nette-nek, hogy az adatokat ennek az osztálynak az objektumaiként adja vissza? Könnyebb, mint gondolnád. Mindössze annyit kell tennie, hogy a kezelőben a `$data` paraméter típusaként megadja az osztályt:
 
 ```php
@@ -294,6 +296,8 @@ A leképezés ekkor a `$person` tulajdonságtípusból tudja, hogy a konténert
 $person->setMappedType(PersonFormData::class);
 ```
 
+Egy űrlap adatosztályának javaslatát a `Nette\Forms\Blueprint::dataClass($form)` metódussal generálhatja, amely a böngészőoldalra nyomtatja ki. Ezután egyszerűen rákattintva kiválaszthatja és bemásolhatja a kódot a projektjébe. .{data-version:3.1.15}
+
 
 Többszörös beküldőgombok .[#toc-multiple-submit-buttons]
 ========================================================
diff --git a/forms/hu/rendering.texy b/forms/hu/rendering.texy
index 813324306e..cefdca3d53 100644
--- a/forms/hu/rendering.texy
+++ b/forms/hu/rendering.texy
@@ -11,6 +11,8 @@ Renderelés Latte-val .[#toc-rendering-with-latte]
 
 A [Latte templating rendszer |latte:] alapvetően megkönnyíti az űrlapok és elemeik megjelenítését. Először megmutatjuk, hogyan lehet az űrlapokat manuálisan, elemenként renderelni, hogy teljes kontrollt kapjunk a kód felett. Később megmutatjuk, hogyan lehet [automatizálni |#Automatic rendering] ezt a renderelést.
 
+A `Nette\Forms\Blueprint::latte($form)` metódus segítségével létrehozhatja a Latte sablon javaslatát az űrlaphoz, amely a böngészőoldalra kimeneti azt. Ezután csak ki kell választania a kódot egy kattintással, és be kell másolnia a projektjébe. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Az összetettebb űrlapelemek, mint például a RadioList vagy CheckboxList, ele
 ```
 
 
-Kódjavaslat `{formPrint}` .[#toc-formprint]
--------------------------------------------
-
-Hasonló Latte kódot generálhat egy űrlaphoz a `{formPrint}` tag használatával. Ha ezt egy sablonba helyezi, a normál megjelenítés helyett a kódtervezetet fogja látni. Ezután csak válassza ki, és másolja be a projektjébe.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ A blokkot csak egy helyre kell importálnia, az elrendezési sablon elejére:
 Speciális esetek .[#toc-special-cases]
 --------------------------------------
 
-Ha csak egy űrlap belső tartalmát kell megjelenítenie anélkül, hogy a `<form>` & `</form>` HTML-címkéket, például egy AJAX-kérés során, akkor a `{formContext} … {/formContext}` segítségével nyithatja meg és zárhatja be az űrlapot. Logikai értelemben hasonlóan működik, mint a `{form}`, itt lehetővé teszi, hogy más címkéket használjon az űrlapelemek megrajzolásához, ugyanakkor nem rajzol semmit.
+Ha csak az űrlap belső részét kell megjelenítenie HTML címkék nélkül `<form>`, például a snippetek elküldésekor, rejtse el őket a `n:tag-if` attribútummal:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 A `formContainer` címke az űrlapkonténeren belüli bemenetek megjelenítését segíti.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+A renderelő először a csoportokat rajzolja ki, majd azokat az elemeket, amelyek nem tartoznak egyik csoporthoz sem.
+
 
 Bootstrap támogatás .[#toc-bootstrap-support]
 ---------------------------------------------
@@ -444,7 +442,7 @@ Bootstrap támogatás .[#toc-bootstrap-support]
 HTML attribútumok .[#toc-html-attributes]
 =========================================
 
-A `setHtmlAttribute(string $name, $value = true)` segítségével bármilyen HTML-attribútumot beállíthat az űrlapvezérlőkhöz:
+Az űrlapelemek tetszőleges HTML-attribútumainak beállításához használja a `setHtmlAttribute(string $name, $value = true)` metódust:
 
 ```php
 $form->addInteger('number', 'Szám:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // változáskor meghívja a submit() JS függvényt.
 
 
-// <form>-ra való alkalmazás
+// A <form> attribútumainak beállítása.
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Input type beállítása:
+Az elem típusának megadása:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-HTML attribútumot állíthatunk be a rádió- vagy jelölőnégyzet-listák egyes elemeihez, mindegyikhez különböző értékekkel.
-Figyeljük meg a kettőspontot a `style:` után, hogy az értéket a kulcs szerint válasszuk ki:
+.[warning]
+A típus és egyéb attribútumok beállítása csak vizuális célokat szolgál. A bevitel helyességének ellenőrzésének a kiszolgálón kell megtörténnie, amit egy megfelelő [űrlapvezérlő | controls] kiválasztásával és [érvényesítési szabályok | validation] megadásával biztosíthat.
+
+A rádió- vagy jelölőnégyzet-listák egyes elemeihez beállíthatunk egy HTML-attribútumot, amelynek értékei eltérőek lehetnek.
+Vegyük észre a kettőspontot a `style:` után, ami biztosítja, hogy az értéket a kulcs alapján válasszuk ki:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-A logikai HTML-attribútumok (amelyeknek nincs értéke, mint például a `readonly`) esetében kérdőjelet használhat:
+A boolean attribútumok beállításához, mint például a `readonly`, használhatjuk a kérdőjellel ellátott jelölést:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // több kulcs esetén használjunk tömböt, pl. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ A Checkbox, CheckboxList és RadioList elemek esetében befolyásolhatja az elem
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/hu/standalone.texy b/forms/hu/standalone.texy
index bcb4b6c8be..478adc10b1 100644
--- a/forms/hu/standalone.texy
+++ b/forms/hu/standalone.texy
@@ -107,7 +107,7 @@ Az űrlap mindig a szerveroldalon validálódik, de a JavaScript validáció is
 Adja hozzá az oldalhoz:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ha megnézi az űrlapot tartalmazó oldal forráskódját, észreveheti, hogy a Nette a szükséges mezőket a `required` CSS osztályú elemekbe illeszti be. Próbálja meg hozzáadni a következő stílust a sablonhoz, és a "Név" felirat piros lesz. Elegánsan jelöljük a kötelező mezőket a felhasználók számára:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-A PHP 8.0-tól kezdve használhatja ezt az elegáns jelölést, amely egy konstruktort használ:
+Alternatívaként használhatja a konstruktort is:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Az adatosztály tulajdonságai lehetnek enumok is, és automatikusan le lesznek képezve. .{data-version:3.2.4}
+
 Hogyan mondjuk meg a Nette-nek, hogy az adatokat ennek az osztálynak az objektumaként adja vissza nekünk? Egyszerűbb, mint gondolnád. Mindössze annyit kell tennünk, hogy paraméterként megadjuk a hidratálandó osztály nevét vagy objektumát:
 
 ```php
@@ -258,6 +260,8 @@ A leképezés ekkor a `$person` tulajdonságtípusból tudja, hogy a konténert
 $person->setMappedType(PersonFormData::class);
 ```
 
+Egy űrlap adatosztályának javaslatát a `Nette\Forms\Blueprint::dataClass($form)` metódussal generálhatja, amely a böngészőoldalra nyomtatja ki. Ezután egyszerűen rákattintva kiválaszthatja és bemásolhatja a kódot a projektjébe. .{data-version:3.1.15}
+
 
 Többszörös beküldőgombok .[#toc-multiple-submit-buttons]
 ========================================================
diff --git a/forms/hu/validation.texy b/forms/hu/validation.texy
index c75844fbdb..757fc82906 100644
--- a/forms/hu/validation.texy
+++ b/forms/hu/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-A Nette számos beépített szabályt tartalmaz, amelyek neve a `Nette\Forms\Form` osztály konstansa:
+**A hitelesítési szabályok csak akkor kerülnek ellenőrzésre, ha a felhasználó kitöltötte az elemet.**
 
-A következő szabályokat használhatjuk az összes vezérlőelemhez:
+A Nette számos előre definiált szabályt tartalmaz, amelyek neve a `Nette\Forms\Form` osztály konstanciái. Ezeket a szabályokat minden elemre alkalmazhatjuk:
 
 | konstans | leírás | érvek
 |-------
@@ -38,7 +38,11 @@ A következő szabályokat használhatjuk az összes vezérlőelemhez:
 | `IsNotIn` | érték nem egyenlő a tömb egyetlen elemével sem | `array`
 | `Valid` | a bemenet átmegy az érvényesítésen ( [feltételek |#conditions] esetén) | -
 
-A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` vezérlőkhöz a következő szabályok is használhatók:
+
+Szöveges bemenetek .[#toc-text-inputs]
+--------------------------------------
+
+A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` elemekre a következő szabályok közül néhányat is lehet alkalmazni:
 
 | `MinLength` | minimális karakterlánc-hossz | `int`
 | `MaxLength` | maximális karakterlánc-hossz | `int`
@@ -57,9 +61,23 @@ A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` ve
 A `Integer`, `Numeric` és `Float` szabályok automatikusan egész számra (illetve lebegőszámra) konvertálják az értéket. Továbbá a `URL` szabály elfogad egy séma nélküli címet is (pl. `nette.org`), és kiegészíti a sémát (`https://nette.org`).
 A `Pattern` és a `PatternInsensitive` kifejezéseknek a teljes értékre érvényesnek kell lenniük, azaz mintha a `^` and `$` karakterekbe lenne csomagolva.
 
+
+Tételek száma .[#toc-number-of-items]
+-------------------------------------
+
+A `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` elemek esetében a következő szabályokkal is korlátozhatja a kiválasztott elemek vagy feltöltött fájlok számát:
+
+| `MinLength` | minimális szám | `int`
+| `MaxLength` | maximális szám | `int`
+| `Length` | szám tartományon belül vagy pontos szám | párok `[int, int]` vagy `int`
+
+
+Fájl feltöltés
+--------------
+
 A `addUpload()`, `addMultiUpload()` vezérlőkre a következő szabályok is alkalmazhatók:
 
-| `MaxFileSize` | maximális fájlméret | `int`
+| `MaxFileSize` | maximális fájlméret bájtban | `int`
 | `MimeType` | MIME-típus, elfogadja a helyettesítő karaktereket (`'video/*'`) | `string\|string[]`
 | `Image` | a feltöltött fájl JPEG, PNG, GIF, WebP | -
 | `Pattern` | a fájl neve megfelel a reguláris kifejezésnek | `string`
@@ -67,15 +85,9 @@ A `addUpload()`, `addMultiUpload()` vezérlőkre a következő szabályok is alk
 
 A `MimeType` és a `Image` a `fileinfo` PHP kiterjesztést igényli. Az, hogy egy fájl vagy kép a kívánt típusba tartozik-e, az aláírás alapján állapítható meg. A teljes fájl sértetlenségét nem ellenőrzi a rendszer. Azt, hogy egy kép nem sérült-e, például úgy lehet megállapítani, ha megpróbáljuk [betölteni |http:request#toImage].
 
-A `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` vezérlőkhöz a következő szabályok is használhatók a kiválasztott elemek, illetve a feltöltött fájlok számának korlátozására:
-
-| `MinLength` | minimális szám | `int`
-| `MaxLength` | maximális szám | `int`
-| `Length` | szám a tartományban vagy pontos szám | pár `[int, int]` vagy `int`
-
 
 Hibaüzenetek .[#toc-error-messages]
------------------------------------
+===================================
 
 A `Pattern` és a `PatternInsensitive` kivételével minden előre definiált szabály rendelkezik alapértelmezett hibaüzenettel, így ezek elhagyhatók. Az összes testreszabott üzenet átadásával és megfogalmazásával azonban felhasználóbarátabbá teszi az űrlapot.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 A Nette-ben nagyon egyszerűen reagálhatunk egy feltétel teljesülésére vagy nem teljesülésére a JavaScript oldalán a `toggle()` metódus segítségével, lásd [Dynamic JavaScript |#Dynamic JavaScript].
 
 
-Hivatkozások a vezérlők között .[#toc-references-between-controls]
-==================================================================
+Hivatkozás egy másik elemre .[#toc-reference-to-another-element]
+================================================================
 
-A szabály vagy feltétel argumentum lehet hivatkozás egy másik elemre. Például dinamikusan érvényesítheti, hogy a `text` annyi karaktert tartalmazzon, ahány karakter a `length` mező értéke:
+Egy szabály vagy feltétel argumentumaként egy másik űrlapelemet is átadhat. A szabály ekkor a felhasználó által a böngészőben később megadott értéket fogja használni. Ez például arra használható, hogy dinamikusan ellenőrizze, hogy a `password` elem ugyanazt a karakterláncot tartalmazza-e, mint a `password_confirm` elem:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Ez a szkript a `netteForms.js`, amely több lehetséges forrásból is elérhet
 A szkriptet közvetlenül a CDN-ből származó HTML-oldalba ágyazhatja be:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Vagy másolja be helyileg a projekt nyilvános mappájába (pl. a `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/it/controls.texy b/forms/it/controls.texy
index a8bd71747e..f139b25cb8 100644
--- a/forms/it/controls.texy
+++ b/forms/it/controls.texy
@@ -5,8 +5,8 @@ Controlli del modulo
 Panoramica dei controlli di modulo incorporati.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Aggiunge un campo di testo a riga singola (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Se l'utente non compila il campo, restituisce una stringa vuota `''`, oppure si può usare `setNullable()` per modificarlo e restituire `null`.
 
@@ -20,13 +20,10 @@ Convalida automaticamente UTF-8, taglia gli spazi bianchi a destra e a sinistra
 
 La lunghezza massima può essere limitata utilizzando `setMaxLength()`. Il metodo [addFilter() |validation#Modifying Input Values] consente di modificare il valore inserito dall'utente.
 
-Utilizzare `setHtmlType()` per cambiare il [carattere |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] dell'elemento di input in `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Al posto dei tipi `number` e `email`, si consiglia di usare [addInteger |#addInteger] e [addEmail |#addEmail], che forniscono una validazione lato server.
+È possibile cambiare il carattere visivo di un campo di testo in tipi come `search`, `tel`, o `url` usando `setHtmlType()`, come si vede nelle [specifiche |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Ricordare che la modifica del tipo è solo visiva e non svolge funzioni di validazione. Per il tipo `url`, è opportuno aggiungere una [regola URL |validation#Text inputs] specifica.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Per altri tipi di input, come `number`, `range`, `email`, `date`, `datetime-local`, `time` e `color`, utilizzare metodi specializzati come [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] e [addColor |#addColor], che garantiscono la validazione lato server. I tipi `month` e `week` non sono ancora pienamente supportati da tutti i browser.
 
 È possibile impostare il cosiddetto valore vuoto per l'elemento, che è qualcosa di simile al valore predefinito, ma se l'utente non lo sovrascrive, restituisce una stringa vuota o `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Aggiunge un campo di input per numeri interi (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Restituisce un intero o `null` se l'utente non inserisce nulla.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('anno', 'Anno:')
+	->addRule($form::Range, 'L'anno deve essere compreso tra %d e %d.', [1900, 2023 |1900, 2023]);
+```
+
+L'elemento viene reso come `<input type="numeric">`. Utilizzando il metodo `setHtmlType()`, si può cambiare il tipo in `range` per la visualizzazione come cursore, oppure in `text` se si preferisce un campo di testo standard senza il comportamento speciale di `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'Il livello deve essere compreso tra %d e %d', [0, 100 |0, 100]);
 ```
 
+L'elemento viene reso come `<input type="numeric">`. Utilizzando il metodo `setHtmlType()`, si può cambiare il tipo in `range` per la visualizzazione come cursore, oppure in `text` se si preferisce un campo di testo standard senza il comportamento speciale di `numeric`.
+
+Nette e il browser Chrome accettano sia una virgola che un punto come separatori decimali. Per rendere disponibile questa funzionalità in Firefox, si consiglia di impostare l'attributo `lang` per un elemento specifico o per l'intera pagina, ad esempio, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Aggiunge un campo per l'indirizzo e-mail con controllo di validità (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Se l'utente non compila il campo, restituisce una stringa vuota `''`, oppure si può usare `setNullable()` per modificarlo e restituire `null`.
 
@@ -78,8 +92,8 @@ Verifica che il valore sia un indirizzo e-mail valido. Non verifica l'effettiva
 La lunghezza massima può essere limitata utilizzando `setMaxLength()`. Il metodo [addFilter() |validation#Modifying Input Values] consente di modificare il valore inserito dall'utente. È possibile impostare il cosiddetto valore vuoto utilizzando `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Aggiunge il campo password (classe [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Aggiunge un elenco di caselle di controllo per la selezione di più elementi (classe [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Restituisce l'array di chiavi degli elementi selezionati. Il metodo `getSelectedItems()` restituisce i valori invece delle chiavi.
 
@@ -125,9 +139,15 @@ L'elemento controlla automaticamente che non ci siano state contraffazioni e che
 
 Quando sono impostati dei valori predefiniti, controlla anche che siano uno degli elementi offerti, altrimenti lancia un'eccezione. Questo controllo può essere disattivato con `checkDefaultValue(false)`.
 
+Se si invia un modulo con il metodo `GET`, è possibile scegliere un metodo di trasferimento dei dati più compatto, che consente di risparmiare sulle dimensioni della stringa di query. Questo metodo si attiva impostando l'attributo HTML del modulo:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Aggiunge pulsanti di opzione (classe [RadioList |api:Nette\Forms\Controls\RadioList]). Restituisce la chiave dell'elemento selezionato o `null` se l'utente non ha selezionato nulla. Il metodo `getSelectedItem()` restituisce un valore invece di una chiave.
 
@@ -148,8 +168,8 @@ L'elemento controlla automaticamente che non ci siano state contraffazioni e che
 Quando il valore predefinito è impostato, controlla anche che sia uno degli elementi offerti, altrimenti lancia un'eccezione. Questo controllo può essere disattivato con `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Aggiunge una casella di selezione (classe [SelectBox |api:Nette\Forms\Controls\SelectBox]). Restituisce la chiave dell'elemento selezionato o `null` se l'utente non ha selezionato nulla. Il metodo `getSelectedItem()` restituisce un valore invece di una chiave.
 
@@ -193,8 +213,8 @@ L'elemento controlla automaticamente che non ci siano state contraffazioni e che
 Quando il valore predefinito è impostato, controlla anche che sia uno degli elementi offerti, altrimenti lancia un'eccezione. Questo controllo può essere disattivato con `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Aggiunge una casella di selezione a scelta multipla (classe [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Restituisce l'array di chiavi degli elementi selezionati. Il metodo `getSelectedItems()` restituisce i valori invece delle chiavi.
 
@@ -246,8 +266,81 @@ Non fidatevi dei nomi originali dei file restituiti dal metodo `FileUpload::getN
 Le regole `MimeType` e `Image` rilevano il tipo di file o immagine richiesto in base alla sua firma. L'integrità dell'intero file non viene controllata. È possibile scoprire se un'immagine non è danneggiata, ad esempio provando a [caricarla |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Aggiunge un campo che consente all'utente di inserire facilmente una data composta da anno, mese e giorno (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Per il valore predefinito, accetta o oggetti che implementano la regola `DateTimeInterface`, una stringa con l'ora o un numero che rappresenta un timestamp UNIX. Lo stesso vale per gli argomenti delle regole `Min`, `Max`, o `Range`, che definiscono la data minima e massima consentita.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable`. Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o un timestamp:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Aggiunge un campo che consente all'utente di inserire facilmente il tempo composto da ore, minuti e, facoltativamente, secondi (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Per il valore predefinito, accetta oggetti che implementano `DateTimeInterface`, una stringa con l'ora o un numero che rappresenta un timestamp UNIX. Solo le informazioni sull'ora di questi input vengono utilizzate; la data viene ignorata. Lo stesso vale per gli argomenti delle regole `Min`, `Max`, o `Range`, che definiscono il tempo minimo e massimo consentito. Se il valore minimo impostato è superiore a quello massimo, viene creato un intervallo di tempo che copre la mezzanotte.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable` (con data 1 gennaio, anno 1). Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Aggiunge un campo che consente all'utente di inserire facilmente sia la data che l'ora, composta da anno, mese, giorno, ore, minuti e, facoltativamente, secondi (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Per il valore predefinito, accetta sia oggetti che implementano `DateTimeInterface`, sia una stringa con l'ora, sia un numero che rappresenta un timestamp UNIX. Lo stesso vale per gli argomenti delle regole `Min`, `Max`, o `Range`, che definiscono la data minima e massima consentita.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable`. Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o un timestamp:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Aggiunge un campo di selezione del colore (classe [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Il colore è una stringa nel formato `#rrggbb`. Se l'utente non effettua alcuna selezione, il colore predefinito restituito è il nero `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Aggiunge un campo nascosto (classe [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Utilizzare `setNullable()` per modificarlo in modo che restituisca `null` invece di una stringa vuota. Il metodo [addFilter() |validation#Modifying Input Values] consente di modificare il valore inviato.
 
+Sebbene l'elemento sia nascosto, è **importante rendersi conto** che il suo valore può comunque essere modificato o falsificato da un utente malintenzionato. Verificare e convalidare sempre accuratamente tutti i valori ricevuti sul lato server per evitare rischi di sicurezza associati alla manipolazione dei dati.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Aggiunge un pulsante di invio sotto forma di immagine (classe [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ I seguenti metodi possono essere richiamati per gli elementi `addText()`, `addPa
 
 
 Valori omessi .[#toc-omitted-values]
-------------------------------------
+====================================
 
 Se non si è interessati al valore inserito dall'utente, si può usare `setOmitted()` per ometterlo dal risultato fornito dal metodo `$form->getValues​()` o passato ai gestori. Questo è adatto per varie password di verifica, campi antispam, ecc.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Disabilitazione degli ingressi .[#toc-disabling-inputs]
--------------------------------------------------------
+=======================================================
 
-Per disabilitare un input, si può chiamare `setDisabled()`. Questo campo non può essere modificato dall'utente.
+Gli ingressi possono essere disabilitati utilizzando `setDisabled()`. Un ingresso disabilitato non può essere modificato dall'utente.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Si noti che il browser non invia affatto i campi disabilitati al server, quindi non li si troverà nemmeno nei dati restituiti dalla funzione `$form->getValues()`.
+Gli input disabilitati non vengono inviati al server dal browser, quindi non li troverete nei dati restituiti dalla funzione `$form->getValues()`. Tuttavia, se si imposta `setOmitted(false)`, Nette includerà il loro valore predefinito in questi dati.
 
-Se si imposta un valore predefinito per un campo, è necessario farlo solo dopo averlo disabilitato:
+Quando viene richiamato `setDisabled()`, **il valore dell'input viene cancellato** per motivi di sicurezza. Se si imposta un valore predefinito, è necessario farlo dopo la sua disattivazione:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Un'alternativa agli input disabilitati sono i campi con l'attributo HTML `readonly`, che vengono inviati al server dal browser. Sebbene il campo sia solo leggibile, è **importante rendersi conto** che il suo valore può comunque essere modificato o falsificato da un utente malintenzionato.
+
 
 Controlli personalizzati .[#toc-custom-controls]
 ================================================
@@ -428,8 +525,8 @@ Esiste un modo per definire nuovi metodi del modulo per aggiungere elementi pers
 ```php
 use Nette\Forms\Container;
 
-// aggiunge il metodo addZip(string $nome, string $etichetta = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// aggiunge il metodo addZip(string $nome, ?string $etichetta = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Almeno 5 numeri', '[0-9]{5}');
 });
diff --git a/forms/it/in-presenter.texy b/forms/it/in-presenter.texy
index a7b68bbb17..4f05ff5567 100644
--- a/forms/it/in-presenter.texy
+++ b/forms/it/in-presenter.texy
@@ -30,7 +30,7 @@ Il modulo nel presentatore è un oggetto della classe `Nette\Application\UI\Form
 
 Dal punto di vista del presentatore, il modulo è un componente comune. Pertanto, viene trattato come un componente e incorporato nel presentatore con il [metodo factory |application:components#Factory Methods]. L'aspetto sarà il seguente:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 E il rendering nel template viene effettuato utilizzando il tag `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Il modulo viene sempre convalidato sul lato server, ma viene generata anche una
 Inserirlo nel modello di layout:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Se si guarda nel codice sorgente della pagina con il modulo, si può notare che Nette inserisce i campi obbligatori in elementi con una classe CSS `required`. Provate ad aggiungere il seguente stile al modello e l'etichetta "Nome" diventerà rossa. In modo elegante, contrassegniamo i campi obbligatori per gli utenti:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-A partire da PHP 8.0, è possibile utilizzare questa elegante notazione che utilizza un costruttore:
+In alternativa, è possibile utilizzare il costruttore:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Le proprietà della classe di dati possono anche essere enum e verranno mappate automaticamente. .{data-version:3.2.4}
+
 Come dire a Nette di restituire i dati come oggetti di questa classe? È più facile di quanto si pensi. Basta specificare la classe come tipo del parametro `$data` nel gestore:
 
 ```php
@@ -294,6 +296,8 @@ La mappatura sa quindi dal tipo di proprietà `$person` che deve mappare il cont
 $person->setMappedType(PersonFormData::class);
 ```
 
+È possibile generare una proposta per la classe di dati di un modulo utilizzando il metodo `Nette\Forms\Blueprint::dataClass($form)`, che la stamperà nella pagina del browser. È quindi sufficiente fare clic per selezionare e copiare il codice nel progetto. .{data-version:3.1.15}
+
 
 Pulsanti di invio multipli .[#toc-multiple-submit-buttons]
 ==========================================================
diff --git a/forms/it/rendering.texy b/forms/it/rendering.texy
index b1ac2c635b..6d4cff8e53 100644
--- a/forms/it/rendering.texy
+++ b/forms/it/rendering.texy
@@ -11,6 +11,8 @@ Rendering con Latte .[#toc-rendering-with-latte]
 
 Il [sistema di template Latte |latte:] facilita fondamentalmente il rendering dei moduli e dei loro elementi. In primo luogo, mostreremo come rendere i moduli manualmente, elemento per elemento, per ottenere il pieno controllo sul codice. In seguito mostreremo come [automatizzare |#Automatic rendering] tale rendering.
 
+È possibile far generare la proposta di un modello Latte per il modulo utilizzando il metodo `Nette\Forms\Blueprint::latte($form)`, che lo invierà alla pagina del browser. È quindi sufficiente selezionare il codice con un clic e copiarlo nel progetto. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Elementi di form più complessi, come RadioList o CheckboxList, possono essere r
 ```
 
 
-Proposta di codice `{formPrint}` .[#toc-formprint]
---------------------------------------------------
-
-È possibile generare un codice Latte simile per un modulo usando il tag `{formPrint}`. Se lo si inserisce in un modello, si vedrà la bozza di codice invece del normale rendering. È sufficiente selezionarlo e copiarlo nel progetto.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ In questo modo sarà un po' più facile da usare:
 Casi speciali .[#toc-special-cases]
 -----------------------------------
 
-Se si ha bisogno di rendere solo il contenuto interno di un modulo senza `<form>` & `</form>` HTML, ad esempio in una richiesta AJAX, si può aprire e chiudere il modulo con `{formContext} … {/formContext}`. Funziona in modo simile a `{form}` in senso logico, ma permette di usare altri tag per disegnare gli elementi del modulo, ma allo stesso tempo non disegna nulla.
+Se si ha bisogno di rendere solo la parte interna del modulo senza tag HTML `<form>`ad esempio per l'invio di snippet, è possibile nasconderli utilizzando l'attributo `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Il tag `formContainer` aiuta a rendere gli input all'interno di un contenitore di form.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Il renderer disegna prima i gruppi e poi gli elementi che non appartengono a nessun gruppo.
+
 
 Supporto Bootstrap .[#toc-bootstrap-support]
 --------------------------------------------
@@ -444,7 +442,7 @@ Supporto Bootstrap .[#toc-bootstrap-support]
 Attributi HTML .[#toc-html-attributes]
 ======================================
 
-È possibile impostare qualsiasi attributo HTML ai controlli dei moduli utilizzando `setHtmlAttribute(string $name, $value = true)`:
+Per impostare attributi HTML arbitrari per gli elementi del modulo, utilizzare il metodo `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Ordina per:', ['prezzo', 'nome'])
 	->setHtmlAttribute('onchange', 'submit()'); // richiama la funzione JS submit() al momento della modifica
 
 
-// applicazione su <form>
+// Per impostare gli attributi dello stesso <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Impostazione del tipo di input:
+Specificare il tipo di elemento:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-È possibile impostare l'attributo HTML per le singole voci degli elenchi di radio o di caselle di controllo con valori diversi per ciascuna di esse.
-Notate i due punti dopo `style:` per garantire che il valore sia selezionato per chiave:
+.[warning]
+L'impostazione del tipo e degli altri attributi serve solo a fini visivi. La verifica della correttezza dell'input deve avvenire sul server, cosa che si può garantire scegliendo un [controllo di forma | controls] appropriato e specificando [le regole di convalida | validation].
+
+Per i singoli elementi degli elenchi di radio o di caselle di controllo, possiamo impostare un attributo HTML con valori diversi per ciascuno di essi.
+Notate i due punti dopo `style:`, che assicurano che il valore sia selezionato in base alla chiave:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Rende:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Per un attributo HTML logico (che non ha valore, come `readonly`), si può usare un punto interrogativo:
+Per impostare attributi booleani, come `readonly`, si può usare la notazione con il punto interrogativo:
 
 ```php
-$colors = ['r' => 'rosso', 'g' => 'verde', 'b' => 'blu'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // utilizzare un array per più chiavi, ad esempio ['r', 'g'].
 ```
@@ -541,9 +541,6 @@ Per gli elementi Checkbox, CheckboxList e RadioList è possibile influenzare il
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/it/standalone.texy b/forms/it/standalone.texy
index 20ac7858c9..935d8217ca 100644
--- a/forms/it/standalone.texy
+++ b/forms/it/standalone.texy
@@ -107,7 +107,7 @@ Il modulo viene sempre convalidato sul lato server, ma viene generata anche una
 Aggiungerlo alla pagina:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Se si guarda nel codice sorgente della pagina con il modulo, si può notare che Nette inserisce i campi obbligatori in elementi con una classe CSS `required`. Provate ad aggiungere il seguente stile al template e l'etichetta "Nome" diventerà rossa. In modo elegante, contrassegniamo i campi obbligatori per gli utenti:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-A partire da PHP 8.0, è possibile utilizzare questa elegante notazione che utilizza un costruttore:
+In alternativa, è possibile utilizzare il costruttore:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Le proprietà della classe di dati possono anche essere enum e verranno mappate automaticamente. .{data-version:3.2.4}
+
 Come dire a Nette di restituirci i dati come oggetti di questa classe? È più facile di quanto si pensi. Basta specificare come parametro il nome della classe o dell'oggetto da idratare:
 
 ```php
@@ -258,6 +260,8 @@ La mappatura sa quindi dal tipo di proprietà `$person` che deve mappare il cont
 $person->setMappedType(PersonFormData::class);
 ```
 
+È possibile generare una proposta per la classe di dati di un modulo utilizzando il metodo `Nette\Forms\Blueprint::dataClass($form)`, che la stamperà nella pagina del browser. È quindi sufficiente fare clic per selezionare e copiare il codice nel progetto. .{data-version:3.1.15}
+
 
 Pulsanti di invio multipli .[#toc-multiple-submit-buttons]
 ==========================================================
diff --git a/forms/it/validation.texy b/forms/it/validation.texy
index 1602645bce..d608296e92 100644
--- a/forms/it/validation.texy
+++ b/forms/it/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette dispone di una serie di regole incorporate, i cui nomi sono costanti della classe `Nette\Forms\Form`:
+**Le regole di validazione vengono controllate solo se l'utente ha compilato l'elemento **.
 
-Possiamo utilizzare le seguenti regole per tutti i controlli:
+Nette dispone di una serie di regole predefinite i cui nomi sono costanti della classe `Nette\Forms\Form`. Possiamo applicare queste regole a tutti gli elementi:
 
 | costante | descrizione | argomenti
 |-------
@@ -38,7 +38,11 @@ Possiamo utilizzare le seguenti regole per tutti i controlli:
 | `IsNotIn` | il valore non è uguale a nessun elemento dell'array | `array`
 | `Valid` | l'input supera la convalida (per le [condizioni |#conditions]) | -
 
-Per i controlli `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` possono essere utilizzate anche le seguenti regole:
+
+Ingressi di testo .[#toc-text-inputs]
+-------------------------------------
+
+Per gli elementi `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` si possono applicare anche alcune delle seguenti regole:
 
 | `MinLength` | lunghezza minima della stringa | `int`
 | `MaxLength` | lunghezza massima della stringa | `int`
@@ -57,9 +61,23 @@ Per i controlli `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `ad
 Le regole `Integer`, `Numeric` e `Float` convertono automaticamente il valore in numero intero (o in virgola mobile, rispettivamente). Inoltre, la regola `URL` accetta anche un indirizzo senza schema (ad esempio `nette.org`) e completa lo schema (`https://nette.org`).
 Le espressioni in `Pattern` e `PatternInsensitive` devono essere valide per l'intero valore, cioè come se fosse avvolto nei caratteri `^` and `$`.
 
+
+Numero di articoli .[#toc-number-of-items]
+------------------------------------------
+
+Per gli elementi `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` è possibile utilizzare anche le seguenti regole per limitare il numero di elementi selezionati o di file caricati:
+
+| `MinLength` | numero minimo | `int`
+| `MaxLength` | numero massimo | `int`
+| `Length` | numero nell'intervallo o numero esatto | coppie `[int, int]` o `int`
+
+
+Caricamento file
+----------------
+
 Per i controlli `addUpload()`, `addMultiUpload()` si possono utilizzare anche le seguenti regole:
 
-| `MaxFileSize` | dimensione massima del file | `int`
+| `MaxFileSize` | dimensione massima del file in byte | `int`
 | `MimeType` | Tipo MIME, accetta caratteri jolly (`'video/*'`) | `string\|string[]`
 | `Image` | il file caricato è JPEG, PNG, GIF, WebP | - - | il nome del file corrisponde a una regola regolare.
 | `Pattern` | il nome del file corrisponde a un'espressione regolare | `string`
@@ -67,15 +85,9 @@ Per i controlli `addUpload()`, `addMultiUpload()` si possono utilizzare anche le
 
 `MimeType` e `Image` richiedono l'estensione PHP `fileinfo`. Il fatto che un file o un'immagine sia del tipo richiesto viene rilevato dalla sua firma. L'integrità dell'intero file non viene controllata. È possibile scoprire se un'immagine non è danneggiata, ad esempio provando a [caricarla |http:request#toImage].
 
-Per i controlli `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` è possibile utilizzare le seguenti regole per limitare il numero di elementi selezionati, rispettivamente di file caricati:
-
-| `MinLength` | conteggio minimo | `int`
-| `MaxLength` | conteggio massimo | `int`
-| `Length` | conteggio nell'intervallo o conteggio esatto | coppia `[int, int]` o `int`
-
 
 Messaggi di errore .[#toc-error-messages]
------------------------------------------
+=========================================
 
 Tutte le regole predefinite, tranne `Pattern` e `PatternInsensitive`, hanno un messaggio di errore predefinito, quindi possono essere omesse. Tuttavia, passando e formulando tutti i messaggi personalizzati, si renderà il modulo più facile da usare.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 In Nette, è molto facile reagire all'adempimento o meno di una condizione sul lato JavaScript, usando il metodo `toggle()`, vedere [JavaScript dinamico |#Dynamic JavaScript].
 
 
-Riferimenti tra controlli .[#toc-references-between-controls]
-=============================================================
+Riferimento a un altro elemento .[#toc-reference-to-another-element]
+====================================================================
 
-L'argomento della regola o della condizione può essere un riferimento a un altro elemento. Ad esempio, è possibile convalidare dinamicamente che il campo `text` abbia un numero di caratteri pari al valore del campo `length`:
+Come argomento per una regola o una condizione, si può passare anche un altro elemento del modulo. La regola utilizzerà il valore inserito successivamente dall'utente nel browser. Questo può essere utilizzato, ad esempio, per convalidare dinamicamente che l'elemento `password` contenga la stessa stringa dell'elemento `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Questo script è `netteForms.js`, disponibile da diverse fonti:
 È possibile incorporare lo script direttamente nella pagina HTML dal CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Oppure copiare localmente nella cartella pubblica del progetto (ad esempio da `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/pl/controls.texy b/forms/pl/controls.texy
index 397c90cc97..1eaf58a2a1 100644
--- a/forms/pl/controls.texy
+++ b/forms/pl/controls.texy
@@ -5,8 +5,8 @@ Elementy formularza
 Przegląd standardowych elementów formularza.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Dodaje jednolinijkowe pole tekstowe (klasa [TextInput |api:Nette\Forms\Controls\TextInput]). Jeśli użytkownik nie wypełni pola, zwraca pusty ciąg `''`, lub `setNullable()` może być użyty do określenia, że zwraca `null`.
 
@@ -20,13 +20,10 @@ Automatycznie waliduje UTF-8, obcina lewe i prawe spacje oraz usuwa przerwy w li
 
 Maksymalna długość może być ograniczona za pomocą `setMaxLength()`. Modyfikacja wartości wprowadzonej przez użytkownika umożliwia [addFilter() |validation#Modifying-Input-Values].
 
-Używając `setHtmlType()`, [charakter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementu wejściowego można zmienić na `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Zalecamy użycie [addInteger |#addInteger] i [addEmail |#addEmail] zamiast typów `number` i `email`, które mają walidację po stronie serwera.
+Można zmienić wizualny charakter pola tekstowego na typy takie jak `search`, `tel`, lub `url` przy użyciu `setHtmlType()`, jak pokazano w [specyfikacji |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Należy pamiętać, że zmiana typu jest tylko wizualna i nie wykonuje funkcji walidacji. W przypadku typu `url` należy dodać określoną [regułę adresu URL |validation#Text inputs].
 
-```php
-$form->addText('color', 'Vyberte barvu:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+W przypadku innych typów wejściowych, takich jak `number`, `range`, `email`, `date`, `datetime-local`, `time` i `color`, należy użyć specjalistycznych metod, takich jak [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail], [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] i [addColor |#addColor], które zapewniają walidację po stronie serwera. Typy `month` i `week` nie są jeszcze w pełni obsługiwane we wszystkich przeglądarkach.
 
 Element może być ustawiony na empty-value, co jest jak wartość domyślna, ale jeśli użytkownik nie zmieni go, element zwróci pusty ciąg lub `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Dodaje pole do wprowadzania liczby całkowitej (klasa [TextInput |api:Nette\Forms\Controls\TextInput]). Zwraca liczbę całkowitą lub `null`, jeśli użytkownik nic nie wprowadzi.
 
 ```php
-$form->addInteger('level', 'Úroveň:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'Rok musi być z zakresu %d do %d.', [1900, 2023 |1900, 2023]);
+```
+
+Element jest renderowany jako `<input type="numeric">`. Za pomocą metody `setHtmlType()` można zmienić typ na `range`, aby wyświetlić jako suwak, lub na `text`, jeśli wolisz standardowe pole tekstowe bez specjalnego zachowania `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Úroveň musí být v rozsahu mezi %d a %d.', [0, 100]);
+->addRule($form::Range, 'The level must be in the range %d to %d.', [0, 100 |0, 100]);
 ```
 
+Element jest renderowany jako `<input type="numeric">`. Za pomocą metody `setHtmlType()` można zmienić typ na `range`, aby wyświetlić jako suwak, lub na `text`, jeśli wolisz standardowe pole tekstowe bez specjalnego zachowania `numeric`.
+
+Nette i przeglądarka Chrome akceptują zarówno przecinek, jak i kropkę jako separatory dziesiętne. Aby udostępnić tę funkcjonalność w przeglądarce Firefox, zaleca się ustawienie atrybutu `lang` albo dla określonego elementu, albo dla całej strony, na przykład, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Dodaje pole do wpisania adresu e-mail (klasa [TextInput |api:Nette\Forms\Controls\TextInput]). Jeśli użytkownik nie wypełni pola, zwraca pusty ciąg `''`, lub można określić `setNullable()`, aby zwrócić `null`.
 
@@ -78,8 +92,8 @@ Sprawdza, czy podana wartość jest prawidłowym adresem e-mail. Nie sprawdza, c
 Maksymalna długość może być ograniczona przy użyciu `setMaxLength()`. [AddFilter() |validation#Modifying-Input-Values] może być użyty do modyfikacji wartości wprowadzonej przez użytkownika. Pusta wartość może być ustawiona przy użyciu `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Dodaje pole do wpisania hasła (klasa [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'Souhlasím s podmínkami')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Dodaje pola wyboru do zaznaczania wielu elementów (klasa [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Zwraca tablicę kluczy dla wybranych elementów. Metoda `getSelectedItems()` zwraca wartości zamiast kluczy.
 
@@ -125,9 +139,15 @@ Element ten automatycznie sprawdza, czy nie doszło do oszustwa oraz czy wybrane
 
 Podczas ustawiania domyślnych wybranych elementów sprawdza również, czy są one jednym z oferowanych elementów, w przeciwnym razie rzuca wyjątek. To sprawdzanie można wyłączyć za pomocą `checkDefaultValue(false)`.
 
+Jeśli przesyłasz formularz za pomocą metody `GET`, możesz wybrać bardziej kompaktową metodę przesyłania danych, która oszczędza rozmiar ciągu zapytania. Jest to aktywowane poprzez ustawienie atrybutu HTML formularza:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Dodaje przyciski radiowe (klasa [RadioList |api:Nette\Forms\Controls\RadioList]). Zwraca klucz wybranego elementu lub `null`, jeśli użytkownik nic nie wybrał. Metoda `getSelectedItem()` zwraca wartość zamiast klucza.
 
@@ -148,8 +168,8 @@ Element automatycznie sprawdza, czy nie doszło do podebrania oraz czy wybrana p
 Po ustawieniu domyślnego wybranego elementu sprawdza również, czy jest to jeden z oferowanych elementów, w przeciwnym razie rzuca wyjątek. To sprawdzanie można wyłączyć za pomocą `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Dodaje pole wyboru (klasa [SelectBox |api:Nette\Forms\Controls\SelectBox]). Zwraca klucz wybranego elementu lub `null`, jeśli użytkownik nic nie wybrał. Metoda `getSelectedItem()` zwraca wartość zamiast klucza.
 
@@ -193,8 +213,8 @@ Pozycja automatycznie sprawdza, czy nie doszło do oszustwa oraz czy wybrany prz
 Gdy ustawiony jest domyślny wybrany element, sprawdza również, czy jest to jeden z oferowanych elementów, w przeciwnym razie rzuca wyjątek. To sprawdzanie można wyłączyć za pomocą `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Dodaje select box do wyboru wielu elementów (klasa [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Zwraca tablicę kluczy dla wybranych elementów. Metoda `getSelectedItems()` zwraca wartości zamiast kluczy.
 
@@ -246,8 +266,81 @@ Nigdy nie ufaj oryginalnym nazwom plików zwracanym przez metodę `FileUpload::g
 Reguły `MimeType` i `Image` wykrywają żądany typ na podstawie sygnatury pliku i nie sprawdzają jego integralności. Możesz określić, czy obraz nie jest uszkodzony, na przykład próbując go [odzyskać |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Dodaje pole, które pozwala użytkownikowi łatwo wprowadzić datę składającą się z roku, miesiąca i dnia (klasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Dla wartości domyślnej akceptuje obiekty implementujące `DateTimeInterface`, ciąg znaków z czasem lub liczbę reprezentującą znacznik czasu UNIX. To samo dotyczy argumentów reguł `Min`, `Max` lub `Range`, które definiują minimalną i maksymalną dozwoloną datę.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Domyślnie zwraca ona obiekt `DateTimeImmutable`. Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] lub znacznik czasu:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Dodaje pole, które umożliwia użytkownikowi łatwe wprowadzanie czasu składającego się z godzin, minut i opcjonalnie sekund (klasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Dla wartości domyślnej akceptuje obiekty implementujące `DateTimeInterface`, ciąg znaków z czasem lub liczbę reprezentującą znacznik czasu UNIX. Używane są tylko informacje o czasie z tych danych wejściowych; data jest ignorowana. To samo dotyczy argumentów reguł `Min`, `Max` lub `Range`, które definiują minimalny i maksymalny dozwolony czas. Jeśli ustawiona wartość minimalna jest wyższa niż maksymalna, tworzony jest zakres czasu obejmujący północ.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Domyślnie zwraca obiekt `DateTimeImmutable` (z datą 1 stycznia, rok 1). Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Dodaje pole, które umożliwia użytkownikowi łatwe wprowadzanie zarówno daty, jak i czasu składającego się z roku, miesiąca, dnia, godzin, minut i opcjonalnie sekund (klasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Dla wartości domyślnej akceptuje obiekty implementujące `DateTimeInterface`, ciąg znaków z czasem lub liczbę reprezentującą znacznik czasu UNIX. To samo dotyczy argumentów reguł `Min`, `Max` lub `Range`, które definiują minimalną i maksymalną dozwoloną datę.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Domyślnie zwraca ona obiekt `DateTimeImmutable`. Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] lub znacznik czasu:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Dodaje pole wyboru koloru (klasa [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Kolor jest ciągiem znaków w formacie `#rrggbb`. Jeśli użytkownik nie dokona wyboru, domyślnym zwracanym kolorem jest czarny `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Dodaje ukryte pole (klasa [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Używając `setNullable()`, można go ustawić, aby zwracał `null` zamiast pustego łańcucha. Modyfikuje wartość przesłaną przez [addFilter() |validation#Modifying-Input-Values].
 
+Chociaż element jest ukryty, **ważne jest, aby zdać sobie sprawę**, że jego wartość może być nadal modyfikowana lub fałszowana przez atakującego. Zawsze dokładnie sprawdzaj i waliduj wszystkie otrzymane wartości po stronie serwera, aby zapobiec zagrożeniom bezpieczeństwa związanym z manipulacją danymi.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Zvýšit plat')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Dodaje przycisk submit w postaci obrazka (klasa [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Poniższe metody można wywołać dla elementów `addText()`, `addPassword()`, `
 
 
 Pomijanie wartości .[#toc-omitted-values]
------------------------------------------
+=========================================
 
 Jeśli nie interesuje nas wartość wypełniona przez użytkownika, możemy użyć `setOmitted()`, aby pominąć ją w wyniku metody `$form->getValues()` lub w danych przekazywanych do handlerów. Jest to przydatne dla różnych sprawdzarek haseł, elementów antyspamowych itp.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Heslo pro kontrolu:')
 
 
 Dezaktywacja elementów .[#toc-disabling-inputs]
------------------------------------------------
+===============================================
 
-Elementy mogą być dezaktywowane za pomocą `setDisabled()`. Użytkownik nie może edytować takich elementów.
+Wejścia można wyłączyć za pomocą `setDisabled()`. Wyłączone wejście nie może być edytowane przez użytkownika.
 
 ```php
 $form->addText('username', 'Uživatelské jméno:')
 	->setDisabled();
 ```
 
-Należy pamiętać, że elementy wyłączone nie są w ogóle wysyłane przez przeglądarkę do serwera, więc nie znajdziemy ich w danych zwracanych przez funkcję `$form->getValues()`.
+Wyłączone wejścia nie są wysyłane do serwera przez przeglądarkę, więc nie znajdziesz ich w danych zwracanych przez funkcję `$form->getValues()`. Jeśli jednak ustawisz `setOmitted(false)`, Nette uwzględni ich domyślną wartość w tych danych.
 
-Jeśli ustawisz wartość domyślną dla elementu, musisz to zrobić dopiero po jego dezaktywacji:
+Gdy wywoływana jest funkcja `setDisabled()`, **wartość wejściowa jest usuwana** ze względów bezpieczeństwa. W przypadku ustawiania wartości domyślnej należy to zrobić po jej dezaktywacji:
 
 ```php
 $form->addText('username', 'Uživatelské jméno:')
@@ -409,6 +504,8 @@ $form->addText('username', 'Uživatelské jméno:')
 	->setDefaultValue($userName);
 ```
 
+Alternatywą dla wyłączonych danych wejściowych są pola z atrybutem HTML `readonly`, które są wysyłane do serwera przez przeglądarkę. Chociaż pole jest tylko czytelne, **ważne jest, aby zdać sobie sprawę**, że jego wartość może zostać zmodyfikowana lub sfałszowana przez atakującego.
+
 
 Elementy niestandardowe .[#toc-custom-controls]
 ===============================================
@@ -428,8 +525,8 @@ Istnieje sposób definiowania nowych metod formularza do dodawania niestandardow
 ```php
 use Nette\Forms\Container;
 
-// přidáme metodu addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// přidáme metodu addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Alespoň 5 čísel', '[0-9]{5}');
 });
diff --git a/forms/pl/in-presenter.texy b/forms/pl/in-presenter.texy
index ff8db944ce..741bae67a2 100644
--- a/forms/pl/in-presenter.texy
+++ b/forms/pl/in-presenter.texy
@@ -30,7 +30,7 @@ Formularz w prezenterze jest obiektem klasy `Nette\Application\UI\Form`, jego po
 
 Z punktu widzenia prezentera formularz jest normalnym komponentem. Dlatego traktujemy go jako komponent i włączamy do prezentera za pomocą [metody factory |application:components#Factory-Methods]. Będzie to wyglądało tak:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 A w szablonie renderujemy formularz z tagiem `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registrace</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Formularz jest zawsze walidowany po stronie serwera, ale generuje również wali
 Wstaw go do szablonu układu:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Jeśli spojrzysz na kod źródłowy strony formularza, możesz zauważyć, że Nette wstawia wymagane elementy z klasą CSS `required`. Spróbuj dodać następujący arkusz stylów do szablonu, a etykieta "Nazwa" będzie czerwona. To elegancko podkreśli wymagane elementy dla użytkownika:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Od PHP 8.0 możesz użyć tej eleganckiej notacji, która wykorzystuje konstruktor:
+Alternatywnie można użyć konstruktora:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Właściwości klasy danych mogą być również wyliczeniami i zostaną automatycznie zmapowane. .{data-version:3.2.4}
+
 Jak powiedzieć Nette, aby zwracała dane jako obiekty tej klasy? Łatwiejsze niż myślisz. Wystarczy określić klasę jako typ parametru `$data` w metodzie handler:
 
 ```php
@@ -294,6 +296,8 @@ Mapowanie wie wtedy z typu właściwości `$person`, że powinno mapować konten
 $person->setMappedType(PersonFormData::class);
 ```
 
+Propozycję klasy danych formularza można wygenerować za pomocą metody `Nette\Forms\Blueprint::dataClass($form)`, która wydrukuje ją na stronie przeglądarki. Następnie wystarczy kliknąć, aby wybrać i skopiować kod do swojego projektu. .{data-version:3.1.15}
+
 
 Więcej przycisków .[#toc-multiple-submit-buttons]
 =================================================
diff --git a/forms/pl/rendering.texy b/forms/pl/rendering.texy
index b224e8d73d..0500660dff 100644
--- a/forms/pl/rendering.texy
+++ b/forms/pl/rendering.texy
@@ -11,6 +11,8 @@ Rendering z Latte .[#toc-rendering-with-latte]
 
 [System szablonów Latte |latte:] zasadniczo ułatwia renderowanie formularzy i ich elementów. Najpierw pokażemy, jak ręcznie renderować formularze element po elemencie i dzięki temu zyskać pełną kontrolę nad kodem. Później pokażemy, jak [zautomatyzować |#Automatické vykreslování] takie renderowanie.
 
+Propozycję szablonu Latte dla formularza można wygenerować za pomocą metody `Nette\Forms\Blueprint::latte($form)`, która wyświetli go na stronie przeglądarki. Następnie wystarczy wybrać kod jednym kliknięciem i skopiować go do swojego projektu. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Bardziej złożone elementy formularza, takie jak RadioList lub CheckboxList, mo
 ```
 
 
-Projektowanie kodu `{formPrint}` .[#toc-formprint]
---------------------------------------------------
-
-Możesz mieć podobny kod Latte dla swojego formularza wygenerowanego za pomocą tagu `{formPrint}` Jeśli umieścisz go w szablonie, zobaczysz sugestię kodu zamiast normalnego renderowania. Następnie wystarczy go zaznaczyć i skopiować do swojego projektu.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Blok wystarczy zaimportować tylko w jednym miejscu, na początku szablonu ukła
 Szczególne przypadki .[#toc-special-cases]
 ------------------------------------------
 
-Jeśli chcesz wyrenderować tylko wewnętrzną część formularza bez znaczników HTML `<form>` & `</form>`, na przykład w żądaniu AJAX, możesz otworzyć i zamknąć formularz na `{formContext} … {/formContext}`. Działa to podobnie do `<form n:form>` lub `{form}` w sensie logicznym, tutaj pozwoli Ci użyć innych znaczników do rysowania elementów formularza, ale jednocześnie nie rysuje niczego.
+Jeśli chcesz renderować tylko wewnętrzną część formularza bez znaczników HTML `<form>`na przykład podczas wysyłania fragmentów, ukryj je za pomocą atrybutu `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Znacznik `{formContainer}` pomoże w rysowaniu elementów wewnątrz kontenera formularza.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Program renderujący najpierw rysuje grupy, a następnie elementy, które nie należą do żadnej grupy.
+
 
 Wsparcie dla Bootstrap .[#toc-bootstrap-support]
 ------------------------------------------------
@@ -444,7 +442,7 @@ Wsparcie dla Bootstrap .[#toc-bootstrap-support]
 Atrybuty HTML .[#toc-html-attributes]
 =====================================
 
-Możemy ustawić dowolne atrybuty HTML do elementów formularza za pomocą `setHtmlAttribute(string $name, $value = true)`:
+Aby ustawić dowolne atrybuty HTML dla elementów formularza, należy użyć metody `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('liczba', 'Liczba:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Rank by:', ['cena', 'nazwa'])
 	->setHtmlAttribute('onchange', 'submit()'); // submit on change
 
 
-// jeśli chcemy zrobić to samo dla <form>
+// Aby ustawić atrybuty samej strony <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Ustawienia typu:
+Określenie typu elementu:
 
 ```php
 $form->addText('tel', 'Váš telefon:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Váš telefon:')
 	->setHtmlAttribute('placeholder', 'napište telefon');
 ```
 
-Możemy ustawić atrybut HTML dla poszczególnych pozycji w listach radio lub checkbox z różnymi wartościami dla każdej z nich.
-Zwróć uwagę na dwukropek po `style:`, który zapewni, że wartość zostanie wybrana zgodnie z kluczem:
+.[warning]
+Ustawienie typu i innych atrybutów służy jedynie celom wizualnym. Weryfikacja poprawności danych wejściowych musi odbywać się na serwerze, co można zapewnić, wybierając odpowiednią [kontrolkę formularza | controls] i określając [reguły walidacji | validation].
+
+Dla poszczególnych elementów na listach radio lub checkbox możemy ustawić atrybut HTML z różnymi wartościami dla każdego z nich.
+Zwróć uwagę na dwukropek po `style:`, który zapewnia, że wartość jest wybierana na podstawie klucza:
 
 ```php
 $colors = ['r' => 'červená', 'g' => 'zelená', 'b' => 'modrá'];
@@ -484,10 +485,9 @@ Listy:
 <label><input type="checkbox" name="colors[]" value="b">modrá</label>
 ```
 
-Jeśli jest to logiczny atrybut HTML (który nie ma wartości, np. `readonly`), możemy użyć notacji znaku zapytania:
+Do ustawiania atrybutów logicznych, takich jak `readonly`, możemy użyć notacji ze znakiem zapytania:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // dla wielu kluczy należy użyć tablicy, np. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ W przypadku elementów Checkbox, CheckboxList i RadioList można wpływać na sz
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>.
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/pl/standalone.texy b/forms/pl/standalone.texy
index 82353d1de2..ef45543e85 100644
--- a/forms/pl/standalone.texy
+++ b/forms/pl/standalone.texy
@@ -107,7 +107,7 @@ Formularz jest zawsze walidowany po stronie serwera, ale generuje również wali
 Wstaw go na stronę:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Jeśli spojrzysz na kod źródłowy strony formularza, możesz zauważyć, że Nette wstawia wymagane elementy z klasą CSS `required`. Spróbuj dodać następujący arkusz stylów do szablonu, a etykieta "Nazwa" będzie czerwona. Dzięki temu w elegancki sposób zaznaczymy dla użytkowników elementy obowiązkowe:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Od PHP 8.0 możesz użyć tej eleganckiej notacji, która wykorzystuje konstruktor:
+Alternatywnie można użyć konstruktora:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Właściwości klasy danych mogą być również wyliczeniami i zostaną automatycznie zmapowane. .{data-version:3.2.4}
+
 Jak powiedzieć Nette, aby zwracała dane jako obiekty tej klasy? Łatwiejsze niż myślisz. Wystarczy, że jako parametr podasz nazwę klasy lub obiektu do nawodnienia:
 
 ```php
@@ -258,6 +260,8 @@ Mapowanie wie wtedy z typu właściwości `$person`, że powinno mapować konten
 $person->setMappedType(PersonFormData::class);
 ```
 
+Propozycję klasy danych formularza można wygenerować za pomocą metody `Nette\Forms\Blueprint::dataClass($form)`, która wydrukuje ją na stronie przeglądarki. Następnie wystarczy kliknąć, aby wybrać i skopiować kod do swojego projektu. .{data-version:3.1.15}
+
 
 Więcej przycisków .[#toc-multiple-submit-buttons]
 =================================================
diff --git a/forms/pl/validation.texy b/forms/pl/validation.texy
index 75e7c62d54..c8c6a1b9c6 100644
--- a/forms/pl/validation.texy
+++ b/forms/pl/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Heslo:')
 	->addRule($form::MinLength, 'Heslo musí mít alespoň %d znaků', 8);
 ```
 
-Nette posiada szereg predefiniowanych reguł, których nazwy są stałymi klasy `Nette\Forms\Form`.
+**Reguły walidacji są sprawdzane tylko wtedy, gdy użytkownik wypełnił dany element.
 
-Zasady te możemy stosować dla wszystkich elementów:
+Nette posiada szereg predefiniowanych reguł, których nazwy są stałymi klasy `Nette\Forms\Form`. Możemy zastosować te reguły do wszystkich elementów:
 
 | stały | opis | typ argumentu
 |-------
@@ -38,7 +38,11 @@ Zasady te możemy stosować dla wszystkich elementów:
 | `IsNotIn` | wartość nie jest równa żadnej pozycji w tablicy |. `array`
 | `Valid` | czy element został wypełniony poprawnie? (dla [warunków |#Conditions]) | -
 
-Poniższe reguły mogą być również stosowane dla elementów `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`:
+
+Wejścia tekstowe .[#toc-text-inputs]
+------------------------------------
+
+W przypadku elementów `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` można również zastosować niektóre z poniższych reguł:
 
 | `MinLength` | minimalna długość tekstu | `int`
 | `MaxLength` | maksymalna długość tekstu | `int`
@@ -57,9 +61,23 @@ Poniższe reguły mogą być również stosowane dla elementów `addText()`, `ad
 Reguły walidacji `Integer`, `Numeric` i `Float` bezpośrednio konwertują wartość na liczbę całkowitą i float odpowiednio. Ponadto reguła `URL` przyjmuje adres bez schematu (np. `nette.org`) i dodaje schemat (`https://nette.org`).
 Wyrażenie w `Pattern` i `PatternIcase` musi być ważne dla całej wartości, czyli tak jakby było zawinięte przez `^` a `$`.
 
+
+Liczba elementów .[#toc-number-of-items]
+----------------------------------------
+
+W przypadku elementów `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` można również użyć następujących reguł, aby ograniczyć liczbę wybranych elementów lub przesłanych plików:
+
+| `MinLength` | minimalna liczba | `int`
+| `MaxLength` | maksymalna liczba | `int`
+| `Length` | liczba w zakresie lub dokładna liczba | pary `[int, int]` lub `int`
+
+
+Przesyłanie plików
+------------------
+
 Poniższe zasady mogą być również stosowane dla elementów `addUpload()`, `addMultiUpload()`:
 
-| `MaxFileSize` | maksymalny rozmiar pliku | `int`
+| `MaxFileSize` | maksymalny rozmiar pliku w bajtach | `int`
 | `MimeType` | Typ MIME, dozwolone symbole wieloznaczne (`'video/*'`) | `string\|string[]`
 | `Image` | obraz JPEG, PNG, GIF, WebP | -.
 | `Pattern` | nazwa pliku pasuje do wyrażenia regularnego | `string`
@@ -67,15 +85,9 @@ Poniższe zasady mogą być również stosowane dla elementów `addUpload()`, `a
 
 `MimeType` i `Image` wymagają rozszerzenia PHP `fileinfo`. Wykrywają one, że plik lub obraz jest pożądanego typu na podstawie jego sygnatury i **nie sprawdzają integralności całego pliku.** Możesz powiedzieć, czy obraz jest uszkodzony, próbując go [załadować |http:request#toImage], na przykład.
 
-Dla elementów `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` można również zastosować następujące reguły, aby ograniczyć liczbę wybranych elementów lub przesłanych plików:
-
-| `MinLength` | minimalna liczba | `int`
-| `MaxLength` | maksymalna liczba | `int`
-| `Length` | liczba w zakresie lub dokładna liczba | par `[int, int]` lub `int`
-
 
 Komunikaty o błędach .[#toc-error-messages]
--------------------------------------------
+===========================================
 
 Wszystkie predefiniowane reguły oprócz `Pattern` i `PatternInsensitive` mają domyślny komunikat o błędzie, więc można go pominąć. Jednak wymieniając i formułując wszystkie wiadomości w niestandardowy sposób, sprawisz, że formularz będzie bardziej przyjazny dla użytkownika.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 W Nett bardzo łatwo jest również reagować na spełnienie lub niespełnienie warunku po stronie JavaScript za pomocą metody `toggle()`, patrz [dynamiczny JavaScript |#Dynamic-JavaScript].
 
 
-Odniesienia między elementami .[#toc-references-between-controls]
-=================================================================
+Odniesienie do innego elementu .[#toc-reference-to-another-element]
+===================================================================
 
-Odwołanie do innego elementu może być podane jako argument do reguły lub warunku. Tak więc, na przykład, możliwe jest dynamiczne sprawdzenie, czy element `text` ma tyle znaków, ile wynosi wartość elementu `length`:
+Jako argument reguły lub warunku można również przekazać inny element formularza. Reguła użyje wtedy wartości wprowadzonej później przez użytkownika w przeglądarce. Można to wykorzystać na przykład do dynamicznego sprawdzenia, czy element `password` zawiera ten sam ciąg znaków, co element `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Ten skrypt to `netteForms.js` i jest dostępny z wielu możliwych źródeł:
 Możesz osadzić skrypt bezpośrednio na stronie HTML z CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Albo skopiuj go lokalnie do publicznego folderu projektu (np. z `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/pt/controls.texy b/forms/pt/controls.texy
index 9dcebf3609..ef747f054a 100644
--- a/forms/pt/controls.texy
+++ b/forms/pt/controls.texy
@@ -5,8 +5,8 @@ Controles de formulário
 Visão geral dos controles de formulário incorporados.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Adiciona campo de texto de linha única (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Se o usuário não preencher o campo, retorna uma string vazia `''`, ou usa `setNullable()` para alterá-lo para retornar `null`.
 
@@ -20,13 +20,10 @@ Ela valida automaticamente UTF-8, apara os espaços em branco à esquerda e à d
 
 O comprimento máximo pode ser limitado usando `setMaxLength()`. O [addFilter() |validation#Modifying Input Values] permite alterar o valor inserido pelo usuário.
 
-Use `setHtmlType()` para mudar o [caráter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] do elemento de entrada para `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Em vez dos tipos `number` e `email`, recomendamos usar [addInteger |#addInteger] e [addEmail |#addEmail], que fornecem validação do lado do servidor.
+Você pode alterar o caractere visual de um campo de texto para tipos como `search`, `tel`, ou `url` usando `setHtmlType()`, como visto na [especificação |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Lembre-se de que a alteração do tipo é apenas visual e não executa funções de validação. Para o tipo `url`, é apropriado adicionar uma [regra de URL |validation#Text inputs] específica.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Para outros tipos de entrada, como `number`, `range`, `email`, `date`, `datetime-local`, `time` e `color`, use métodos especializados como [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail], [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] e [addColor |#addColor], que garantem a validação do lado do servidor. Os tipos `month` e `week` ainda não são totalmente compatíveis com todos os navegadores.
 
 O chamado valor vazio pode ser definido para o elemento, que é algo como o valor padrão, mas se o usuário não o sobrescrever, retorna uma string vazia ou `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Adiciona campo de entrada para o número inteiro (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Retorna ou um número inteiro ou `null` se o usuário não inserir nada.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'O ano deve estar no intervalo de %d a %d.', [1900, 2023 |1900, 2023]);
+```
+
+O elemento é renderizado como `<input type="numeric">`. Ao usar o método `setHtmlType()`, você pode alterar o tipo para `range` para exibição como controle deslizante ou para `text` se preferir um campo de texto padrão sem o comportamento especial de `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'O nível deve estar no intervalo de %d a %d.', [0, 100 |0, 100]);
 ```
 
+O elemento é renderizado como `<input type="numeric">`. Ao usar o método `setHtmlType()`, você pode alterar o tipo para `range` para exibição como controle deslizante ou para `text` se preferir um campo de texto padrão sem o comportamento especial de `numeric`.
+
+O Nette e o navegador Chrome aceitam tanto uma vírgula quanto um ponto como separadores decimais. Para disponibilizar essa funcionalidade no Firefox, é recomendável definir o atributo `lang` para o elemento específico ou para a página inteira, por exemplo, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Adiciona campo de endereço de e-mail com verificação de validade (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Se o usuário não preencher o campo, devolve uma string vazia `''`, ou usa `setNullable()` para alterá-lo para retornar `null`.
 
@@ -78,8 +92,8 @@ Verifica que o valor é um endereço de e-mail válido. Não verifica que o dom
 O comprimento máximo pode ser limitado usando `setMaxLength()`. O [addFilter() |validation#Modifying Input Values] permite alterar o valor inserido pelo usuário. Você pode definir o chamado valor vazio usando `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Adiciona o campo de senha (classe [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Adiciona lista de caixas de seleção para selecionar vários itens (classe [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Retorna a matriz de chaves dos itens selecionados. O método `getSelectedItems()` retorna valores em vez de chaves.
 
@@ -125,9 +139,15 @@ O elemento verifica automaticamente que não houve falsificação e que os itens
 
 Quando os valores padrão são definidos, ele também verifica se eles são um dos itens oferecidos, caso contrário, ele lança uma exceção. Esta verificação pode ser desativada com `checkDefaultValue(false)`.
 
+Se estiver enviando um formulário usando o método `GET`, você poderá escolher um método de transferência de dados mais compacto que economize o tamanho da string de consulta. Isso é ativado pela configuração do atributo HTML do formulário:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Acrescenta botões de rádio (classe [RadioList |api:Nette\Forms\Controls\RadioList]). Devolve a chave do item selecionado, ou `null` caso o usuário não tenha selecionado nada. O método `getSelectedItem()` retorna um valor em vez de uma chave.
 
@@ -148,8 +168,8 @@ O elemento verifica automaticamente que não houve falsificação e que o item s
 Quando o valor padrão é definido, ele também verifica se ele é um dos itens oferecidos, caso contrário, ele lança uma exceção. Esta verificação pode ser desativada com `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Adiciona caixa de seleção (classe [SelectBox |api:Nette\Forms\Controls\SelectBox]). Devolve a chave do item selecionado, ou `null` caso o usuário não tenha selecionado nada. O método `getSelectedItem()` retorna um valor em vez de uma chave.
 
@@ -193,8 +213,8 @@ O elemento verifica automaticamente que não houve falsificação e que o item s
 Quando o valor padrão é definido, ele também verifica se ele é um dos itens oferecidos, caso contrário, ele lança uma exceção. Esta verificação pode ser desativada com `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Adiciona caixa de seleção de múltipla escolha (classe [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Devolve a matriz de chaves dos itens selecionados. O método `getSelectedItems()` retorna valores em vez de chaves.
 
@@ -246,8 +266,81 @@ Não confie nos nomes originais dos arquivos devolvidos pelo método `FileUpload
 As regras `MimeType` e `Image` detectam o tipo de arquivo ou imagem exigida por sua assinatura. A integridade do arquivo inteiro não é verificada. Você pode descobrir se uma imagem não está corrompida, por exemplo, ao tentar [carregá-la |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Adiciona um campo que permite ao usuário inserir facilmente uma data composta por ano, mês e dia (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Para o valor padrão, ele aceita objetos que implementam o `DateTimeInterface`, uma cadeia de caracteres com a hora ou um número que representa um carimbo de data/hora do UNIX. O mesmo se aplica aos argumentos de regra `Min`, `Max` ou `Range`, que definem a data mínima e máxima permitida.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Por padrão, ele retorna um objeto `DateTimeImmutable`. Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou um carimbo de data/hora:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Adiciona um campo que permite que o usuário insira facilmente o tempo composto por horas, minutos e, opcionalmente, segundos (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Para o valor padrão, ele aceita objetos que implementam o `DateTimeInterface`, uma cadeia de caracteres com a hora ou um número que representa um carimbo de data/hora do UNIX. Somente as informações de hora dessas entradas são usadas; a data é ignorada. O mesmo se aplica aos argumentos de regra `Min`, `Max` ou `Range`, que definem o tempo mínimo e máximo permitido. Se o valor mínimo definido for maior que o máximo, será criado um intervalo de tempo que vai até a meia-noite.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Por padrão, ele retorna um objeto `DateTimeImmutable` (com data de 1º de janeiro, ano 1). Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Adiciona um campo que permite que o usuário insira facilmente data e hora, consistindo em ano, mês, dia, horas, minutos e, opcionalmente, segundos (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Para o valor padrão, ele aceita objetos que implementam o `DateTimeInterface`, uma cadeia de caracteres com a hora ou um número que representa um carimbo de data/hora do UNIX. O mesmo se aplica aos argumentos de regra `Min`, `Max` ou `Range`, que definem a data mínima e máxima permitida.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Por padrão, ele retorna um objeto `DateTimeImmutable`. Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou um carimbo de data/hora:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Adiciona um campo de seleção de cores (classe [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). A cor é uma cadeia de caracteres no formato `#rrggbb`. Se o usuário não fizer uma seleção, a cor padrão retornada será o preto `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Adiciona campo oculto (classe [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Use `setNullable()` para mudá-lo para retornar `null` ao invés de um fio vazio. O [addFilter() |validation#Modifying Input Values] permite que você altere o valor submetido.
 
+Embora o elemento esteja oculto, é **importante perceber** que seu valor ainda pode ser modificado ou falsificado por um invasor. Sempre verifique e valide minuciosamente todos os valores recebidos no lado do servidor para evitar riscos de segurança associados à manipulação de dados.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Adiciona botão submeter em forma de uma imagem (classe [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Os seguintes métodos podem ser chamados para o `addText()`, `addPassword()`, `a
 
 
 Valores omitidos .[#toc-omitted-values]
----------------------------------------
+=======================================
 
 Se você não estiver interessado no valor inserido pelo usuário, podemos usar `setOmitted()` para omiti-lo do resultado fornecido pelo método `$form->getValues​()` ou passado para os manipuladores. Isto é adequado para várias senhas de verificação, campos antispam, etc.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Desativação de entradas .[#toc-disabling-inputs]
-------------------------------------------------
+================================================
 
-A fim de desativar uma entrada, você pode ligar para `setDisabled()`. Tal campo não pode ser editado pelo usuário.
+As entradas podem ser desativadas usando `setDisabled()`. Uma entrada desativada não pode ser editada pelo usuário.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Note que o navegador não envia os campos desativados para o servidor, portanto você não os encontrará nem mesmo nos dados devolvidos pela função `$form->getValues()`.
+As entradas desabilitadas não são enviadas ao servidor pelo navegador, portanto, você não as encontrará nos dados retornados pela função `$form->getValues()`. Entretanto, se você definir `setOmitted(false)`, a Nette incluirá o valor padrão nesses dados.
 
-Se você estiver definindo um valor padrão para um campo, você deve fazê-lo somente após desativá-lo:
+Quando `setDisabled()` é chamada, **o valor da entrada é apagado** por motivos de segurança. Se estiver definindo um valor padrão, é necessário fazê-lo após sua desativação:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Uma alternativa às entradas desabilitadas são os campos com o atributo HTML `readonly`, que são enviados ao servidor pelo navegador. Embora o campo seja apenas legível, é **importante perceber** que seu valor ainda pode ser modificado ou falsificado por um invasor.
+
 
 Controles personalizados .[#toc-custom-controls]
 ================================================
@@ -428,8 +525,8 @@ Há uma maneira de definir novos métodos de formulário para adicionar elemento
 ```php
 use Nette\Forms\Container;
 
-// adiciona método addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// adiciona método addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/pt/in-presenter.texy b/forms/pt/in-presenter.texy
index 81cf7df2ae..1d865c2f83 100644
--- a/forms/pt/in-presenter.texy
+++ b/forms/pt/in-presenter.texy
@@ -30,7 +30,7 @@ A forma no apresentador é um objeto da classe `Nette\Application\UI\Form`, seu
 
 Do ponto de vista do apresentador, a forma é um componente comum. Portanto, ele é tratado como um componente e incorporado ao apresentador usando [o método de fábrica |application:components#Factory Methods]. Será parecido com isto:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 E a renderização em modelo é feita usando a tag `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ O formulário é sempre validado no lado do servidor, mas a validação JavaScri
 Insira-o no modelo de layout:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Se você olhar no código fonte da página com formulário, você pode notar que Nette insere os campos necessários em elementos com uma classe CSS `required`. Tente adicionar o seguinte estilo ao modelo, e a etiqueta "Name" (Nome) será vermelha. Elegantemente, marcamos os campos requeridos para os usuários:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-A partir do PHP 8.0, você pode usar esta elegante notação que usa um construtor:
+Como alternativa, você pode usar o construtor:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+As propriedades da classe de dados também podem ser enums e serão mapeadas automaticamente. .{data-version:3.2.4}
+
 Como dizer à Nette para retornar dados como objetos desta classe? Mais fácil do que você pensa. Tudo que você precisa fazer é especificar a classe como o tipo do parâmetro `$data` no manipulador:
 
 ```php
@@ -294,6 +296,8 @@ O mapeamento então sabe pelo tipo de propriedade `$person` que deve mapear o co
 $person->setMappedType(PersonFormData::class);
 ```
 
+Você pode gerar uma proposta para a classe de dados de um formulário usando o método `Nette\Forms\Blueprint::dataClass($form)`, que a imprimirá na página do navegador. Em seguida, basta clicar para selecionar e copiar o código em seu projeto. .{data-version:3.1.15}
+
 
 Botões de submissão múltipla .[#toc-multiple-submit-buttons]
 ============================================================
diff --git a/forms/pt/rendering.texy b/forms/pt/rendering.texy
index 37a6d94fdc..fb8de4ffea 100644
--- a/forms/pt/rendering.texy
+++ b/forms/pt/rendering.texy
@@ -11,6 +11,8 @@ Renderização com Latte .[#toc-rendering-with-latte]
 
 O [sistema de modelos Latte |latte:] facilita fundamentalmente a renderização de formulários e seus elementos. Primeiro, mostraremos como renderizar formulários manualmente, elemento por elemento, para obter controle total sobre o código. Mais tarde, mostraremos como [automatizar |#Automatic rendering] tal renderização.
 
+Você pode ter a proposta de um modelo Latte para o formulário gerado usando o método `Nette\Forms\Blueprint::latte($form)`, que o enviará para a página do navegador. Em seguida, basta selecionar o código com um clique e copiá-lo em seu projeto. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Elementos de formulário mais complexos, tais como RadioList ou CheckboxList, po
 ```
 
 
-Proposta de Código `{formPrint}` .[#toc-formprint]
---------------------------------------------------
-
-Você pode gerar um código Latte similar para um formulário usando a tag `{formPrint}`. Se você colocá-lo em um modelo, você verá o rascunho do código ao invés da renderização normal. Então basta selecioná-lo e copiá-lo para seu projeto.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Você só precisa importar o bloco em um lugar, no início do modelo de layout:
 Casos especiais .[#toc-special-cases]
 -------------------------------------
 
-Se você precisar apenas renderizar o conteúdo interno de uma forma sem `<form>` & `</form>` Tags HTML, por exemplo, em um pedido AJAX, você pode abrir e fechar o formulário com `{formContext} … {/formContext}`. Funciona de forma similar a `{form}` em um sentido lógico, aqui permite que você use outras tags para desenhar elementos do formulário, mas ao mesmo tempo não desenha nada.
+Se você precisar renderizar somente a parte interna do formulário sem tags HTML `<form>`por exemplo, ao enviar snippets, oculte-os usando o atributo `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 A etiqueta `formContainer` ajuda na renderização de entradas dentro de um contêiner de formulário.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+O renderizador desenha primeiro os grupos e depois os elementos que não pertencem a nenhum grupo.
+
 
 Suporte de Bootstrap .[#toc-bootstrap-support]
 ----------------------------------------------
@@ -444,7 +442,7 @@ Você pode encontrar [exemplos de |https://github.com/nette/forms/tree/master/ex
 Atributos HTML .[#toc-html-attributes]
 ======================================
 
-Você pode definir quaisquer atributos HTML para controles de formulários usando `setHtmlAttribute(string $name, $value = true)`:
+Para definir atributos HTML arbitrários para elementos de formulário, use o método `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('número', 'Número:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // chama a função JS submit() on change
 
 
-// aplicando em <form>
+// Para definir os atributos do próprio <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Tipo de ajuste de entrada:
+Especificando o tipo de elemento:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-Podemos definir atributo HTML a itens individuais em listas de rádio ou checkbox com valores diferentes para cada um deles.
-Observe os dois pontos após `style:` para garantir que o valor seja selecionado por chave:
+.[warning]
+A definição do tipo e de outros atributos serve apenas para fins visuais. A verificação da exatidão da entrada deve ocorrer no servidor, o que pode ser garantido pela escolha de um [controle de formulário | controls] apropriado e pela especificação de [regras de validação | validation].
+
+Para itens individuais em listas de rádio ou caixas de seleção, podemos definir um atributo HTML com valores diferentes para cada um deles.
+Observe os dois pontos após `style:`, o que garante que o valor seja selecionado com base na chave:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renderizadores:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Para um atributo HTML lógico (que não tem valor, como `readonly`), você pode usar um ponto de interrogação:
+Para definir atributos booleanos, como `readonly`, podemos usar a notação com um ponto de interrogação:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // use array para múltiplas chaves, por exemplo ['r', 'g'].
 ```
@@ -541,9 +541,6 @@ Para os itens Checkbox, CheckboxList e RadioList você pode influenciar o modelo
 
 ```php
 $input = $form->addCheckbox('enviar');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/pt/standalone.texy b/forms/pt/standalone.texy
index 2bcad570b5..d45a268a26 100644
--- a/forms/pt/standalone.texy
+++ b/forms/pt/standalone.texy
@@ -107,7 +107,7 @@ O formulário é sempre validado no lado do servidor, mas a validação JavaScri
 Acrescente-o à página:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Se você olhar no código fonte da página com formulário, você pode notar que Nette insere os campos necessários em elementos com uma classe CSS `required`. Tente adicionar o seguinte estilo ao modelo, e a etiqueta "Name" (Nome) será vermelha. Elegantemente, marcamos os campos requeridos para os usuários:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-A partir do PHP 8.0, você pode usar esta elegante notação que usa um construtor:
+Como alternativa, você pode usar o construtor:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+As propriedades da classe de dados também podem ser enums e serão mapeadas automaticamente. .{data-version:3.2.4}
+
 Como dizer à Nette para nos retornar dados como objetos desta classe? Mais fácil do que você pensa. Tudo que você precisa fazer é especificar o nome da classe ou objeto a ser hidratado como um parâmetro:
 
 ```php
@@ -258,6 +260,8 @@ O mapeamento então sabe pelo tipo de propriedade `$person` que deve mapear o co
 $person->setMappedType(PersonFormData::class);
 ```
 
+Você pode gerar uma proposta para a classe de dados de um formulário usando o método `Nette\Forms\Blueprint::dataClass($form)`, que a imprimirá na página do navegador. Em seguida, basta clicar para selecionar e copiar o código em seu projeto. .{data-version:3.1.15}
+
 
 Botões de submissão múltipla .[#toc-multiple-submit-buttons]
 ============================================================
diff --git a/forms/pt/validation.texy b/forms/pt/validation.texy
index fe1ab31f0d..25e1c29291 100644
--- a/forms/pt/validation.texy
+++ b/forms/pt/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette vem com uma série de regras embutidas cujos nomes são constantes da classe `Nette\Forms\Form`:
+**As regras de validação são verificadas somente se o usuário tiver preenchido o elemento.
 
-Podemos utilizar as seguintes regras para todos os controles:
+O Nette vem com várias regras predefinidas cujos nomes são constantes da classe `Nette\Forms\Form`. Podemos aplicar essas regras a todos os elementos:
 
 | constante | descrição | argumentos
 |-------
@@ -38,7 +38,11 @@ Podemos utilizar as seguintes regras para todos os controles:
 | `IsNotIn` | valor não é igual a nenhum elemento da matriz | `array`
 | `Valid` | validação dos passes de entrada (para [condições |#conditions]) | -
 
-Para os controles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` também podem ser usadas as seguintes regras:
+
+Entradas de texto .[#toc-text-inputs]
+-------------------------------------
+
+Para os elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()`, algumas das regras a seguir também podem ser aplicadas:
 
 | `MinLength` | comprimento mínimo das cordas | `int`
 | `MaxLength` | comprimento máximo das cordas | `int`
@@ -57,9 +61,23 @@ Para os controles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `
 As regras `Integer`, `Numeric` a `Float` convertem automaticamente o valor em inteiro (ou float, respectivamente). Além disso, a regra `URL` também aceita um endereço sem esquema (por exemplo `nette.org`) e completa o esquema (`https://nette.org`).
 As expressões em `Pattern` e `PatternInsensitive` devem ser válidas para todo o valor, ou seja, como se estivesse embrulhado nos caracteres `^` and `$`.
 
+
+Número de itens .[#toc-number-of-items]
+---------------------------------------
+
+Para os elementos `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` você também pode usar as seguintes regras para limitar o número de itens selecionados ou arquivos carregados:
+
+| `MinLength` | número mínimo | `int`
+| `MaxLength` | número máximo | `int`
+| `Length` | número no intervalo ou número exato | pares `[int, int]` ou `int`
+
+
+Upload de arquivos
+------------------
+
 Para controles `addUpload()`, `addMultiUpload()` as seguintes regras também podem ser usadas:
 
-| `MaxFileSize` | tamanho máximo do arquivo | `int`
+| `MaxFileSize` | tamanho máximo do arquivo em bytes | `int`
 | `MimeType` | tipo MIME, aceita wildcards (`'video/*'`) | `string\|string[]`
 | `Image` | o arquivo carregado é JPEG, PNG, GIF, WebP | -
 | `Pattern` | o nome do arquivo corresponde à expressão regular | `string`
@@ -67,15 +85,9 @@ Para controles `addUpload()`, `addMultiUpload()` as seguintes regras também pod
 
 Os sites `MimeType` e `Image` requerem extensão PHP `fileinfo`. Se um arquivo ou imagem é do tipo requerido é detectado por sua assinatura. A integridade do arquivo inteiro não é verificada. Você pode descobrir se uma imagem não está corrompida, por exemplo, ao tentar [carregá-la |http:request#toImage].
 
-Para os controles `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` as seguintes regras também podem ser usadas para limitar o número de itens selecionados, respectivamente arquivos carregados:
-
-| `MinLength` | contagem mínima | `int`
-| `MaxLength` | contagem máxima | `int`
-| `Length` | contagem no intervalo ou contagem exata | par `[int, int]` ou `int`
-
 
 Mensagens de erro .[#toc-error-messages]
-----------------------------------------
+========================================
 
 Todas as regras predefinidas, exceto `Pattern` e `PatternInsensitive`, têm uma mensagem de erro padrão, portanto, ela é omitida. Entretanto, ao passar e formular todas as mensagens personalizadas, você tornará o formulário mais fácil de usar.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 Em Nette, é muito fácil reagir ao cumprimento ou não de uma condição no lado JavaScript usando o método `toggle()`, veja [Dynamic JavaScript |#Dynamic JavaScript].
 
 
-Referências entre controles .[#toc-references-between-controls]
-===============================================================
+Referência a outro elemento .[#toc-reference-to-another-element]
+================================================================
 
-A regra ou argumento de condição pode ser uma referência a outro elemento. Por exemplo, você pode validar dinamicamente que o `text` tem tantos caracteres quanto o valor do campo `length`:
+Como argumento para uma regra ou condição, você também pode passar outro elemento de formulário. A regra usará então o valor inserido posteriormente pelo usuário no navegador. Isso pode ser usado, por exemplo, para validar dinamicamente se o elemento `password` contém a mesma cadeia de caracteres que o elemento `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Este roteiro é `netteForms.js`, que está disponível em várias fontes possív
 Você pode incorporar o script diretamente na página HTML a partir do CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ou copiar localmente para a pasta pública do projeto (por exemplo, de `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/ro/controls.texy b/forms/ro/controls.texy
index e099cf0568..ad7d6c3228 100644
--- a/forms/ro/controls.texy
+++ b/forms/ro/controls.texy
@@ -5,8 +5,8 @@ Controale de formular
 Prezentare generală a controalelor de formular încorporate.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Adaugă un câmp de text cu o singură linie (clasa [TextInput |api:Nette\Forms\Controls\TextInput]). Dacă utilizatorul nu completează câmpul, acesta returnează un șir de caractere gol `''`, sau se poate folosi `setNullable()` pentru a schimba acest câmp și a returna `null`.
 
@@ -20,13 +20,10 @@ Validează automat UTF-8, taie spațiile albe din stânga și din dreapta și el
 
 Lungimea maximă poate fi limitată folosind `setMaxLength()`. [AddFilter() |validation#Modifying Input Values] vă permite să modificați valoarea introdusă de utilizator.
 
-Utilizați `setHtmlType()` pentru a schimba [caracterul |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementului de intrare în `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. În locul tipurilor `number` și `email`, vă recomandăm să utilizați [addInteger |#addInteger] și [addEmail |#addEmail], care oferă validare pe server.
+Puteți schimba caracterul vizual al unui câmp de text în tipuri precum `search`, `tel`, sau `url` folosind `setHtmlType()`, așa cum se vede în [specificație |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Rețineți că schimbarea tipului este doar vizuală și nu îndeplinește funcții de validare. Pentru tipul `url`, este oportun să se adauge o [regulă URL |validation#Text inputs] specifică.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Pentru alte tipuri de intrare, cum ar fi `number`, `range`, `email`, `date`, `datetime-local`, `time` și `color`, utilizați metode specializate, cum ar fi [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] și [addColor |#addColor], care asigură validarea pe partea serverului. Tipurile `month` și `week` nu sunt încă pe deplin acceptate în toate browserele.
 
 Pentru element se poate seta așa-numita "empty-value", care este ceva de genul valorii implicite, dar, dacă utilizatorul nu o suprascrie, returnează un șir de caractere gol sau `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Adaugă un câmp de intrare pentru numere întregi (clasa [TextInput |api:Nette\Forms\Controls\TextInput]). Returnează fie un număr întreg, fie `null` dacă utilizatorul nu introduce nimic.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('an', 'Anul:')
+	->addRule($form::Range, 'Anul trebuie să fie cuprins între %d și %d.', [1900, 2023 |1900, 2023]);
+```
+
+Elementul este redat ca `<input type="numeric">`. Prin utilizarea metodei `setHtmlType()`, puteți schimba tipul la `range` pentru afișarea ca cursor sau la `text` dacă preferați un câmp text standard fără comportamentul special al `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'Nivelul trebuie să fie cuprins între %d și %d.', [0, 100 |0, 100]);
 ```
 
+Elementul este redat ca `<input type="numeric">`. Prin utilizarea metodei `setHtmlType()`, puteți schimba tipul la `range` pentru afișarea ca cursor sau la `text` dacă preferați un câmp text standard fără comportamentul special al `numeric`.
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+Nette și browserul Chrome acceptă atât o virgulă, cât și un punct ca separatori de zecimale. Pentru ca această funcționalitate să fie disponibilă în Firefox, se recomandă să setați atributul `lang` fie pentru elementul specific, fie pentru întreaga pagină, de exemplu, `<html lang="cs">`.
+
+
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Adaugă un câmp de adresă de e-mail cu verificare a validității (clasa [TextInput |api:Nette\Forms\Controls\TextInput]). Dacă utilizatorul nu completează câmpul, acesta returnează un șir de caractere gol `''`, sau se poate folosi `setNullable()` pentru a schimba acest câmp și a returna `null`.
 
@@ -78,8 +92,8 @@ Verifică dacă valoarea este o adresă de e-mail validă. Nu se verifică dacă
 Lungimea maximă poate fi limitată folosind `setMaxLength()`. [AddFilter() |validation#Modifying Input Values] vă permite să modificați valoarea introdusă de utilizator. Puteți seta așa-numita "valoare goală" folosind `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Adaugă câmpul de parolă (clasa [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Adaugă o listă de căsuțe de bifat pentru selectarea mai multor elemente (clasa [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Returnează matricea de chei a elementelor selectate. Metoda `getSelectedItems()` returnează valori în loc de chei.
 
@@ -125,9 +139,15 @@ Elementul verifică în mod automat dacă nu a existat nicio falsificare și dac
 
 În cazul în care sunt stabilite valori implicite, se verifică, de asemenea, dacă acestea sunt unul dintre elementele oferite, în caz contrar se aruncă o excepție. Această verificare poate fi dezactivată cu `checkDefaultValue(false)`.
 
+Dacă trimiteți un formular utilizând metoda `GET`, puteți alege o metodă de transfer de date mai compactă care să economisească dimensiunea șirului de interogare. Aceasta se activează prin setarea atributului HTML al formularului:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Adaugă butoane radio (clasa [RadioList |api:Nette\Forms\Controls\RadioList]). Returnează cheia elementului selectat sau `null` dacă utilizatorul nu a selectat nimic. Metoda `getSelectedItem()` returnează o valoare în loc de o cheie.
 
@@ -148,8 +168,8 @@ Elementul verifică automat dacă nu a existat nicio falsificare și dacă eleme
 În cazul în care este stabilită o valoare implicită, se verifică, de asemenea, dacă este unul dintre elementele oferite, în caz contrar se aruncă o excepție. Această verificare poate fi dezactivată cu `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Adaugă caseta de selectare (clasa [SelectBox |api:Nette\Forms\Controls\SelectBox]). Returnează cheia elementului selectat sau `null` dacă utilizatorul nu a selectat nimic. Metoda `getSelectedItem()` returnează o valoare în loc de o cheie.
 
@@ -193,8 +213,8 @@ Elementul verifică în mod automat dacă nu a existat nicio falsificare și dac
 În cazul în care este stabilită o valoare implicită, se verifică, de asemenea, dacă este unul dintre elementele oferite, în caz contrar se aruncă o excepție. Această verificare poate fi dezactivată cu `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Adaugă caseta de selectare a mai multor opțiuni (clasa [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Returnează matricea de chei a elementelor selectate. Metoda `getSelectedItems()` returnează valori în loc de chei.
 
@@ -246,8 +266,81 @@ Nu vă încredeți în numele de fișier original returnat de metoda `FileUpload
 Regulile `MimeType` și `Image` detectează tipul necesar de fișier sau imagine prin semnătura acestuia. Integritatea întregului fișier nu este verificată. Puteți afla dacă o imagine nu este coruptă, de exemplu, încercând să [o încărcați |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Adaugă un câmp care permite utilizatorului să introducă cu ușurință o dată formată din an, lună și zi (clasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Pentru valoarea implicită, acceptă fie obiecte care implementează `DateTimeInterface`, fie un șir de caractere cu ora, fie un număr reprezentând un timestamp UNIX. Același lucru este valabil și pentru argumentele regulilor `Min`, `Max` sau `Range`, care definesc data minimă și maximă admisă.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+În mod implicit, returnează un obiect `DateTimeImmutable`. Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] sau un timestamp:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Adaugă un câmp care permite utilizatorului să introducă cu ușurință ora constând în ore, minute și, opțional, secunde (clasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Pentru valoarea implicită, acceptă fie obiecte care implementează `DateTimeInterface`, fie un șir de caractere cu ora, fie un număr reprezentând un timestamp UNIX. Se utilizează numai informațiile de timp din aceste intrări; data este ignorată. Același lucru este valabil și pentru argumentele de regulă `Min`, `Max` sau `Range`, care definesc timpul minim și maxim admis. Dacă valoarea minimă setată este mai mare decât cea maximă, se creează un interval de timp care se întinde până la miezul nopții.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+În mod implicit, se returnează un obiect `DateTimeImmutable` (cu data de 1 ianuarie, anul 1). Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Adaugă un câmp care permite utilizatorului să introducă cu ușurință atât data, cât și ora, constând în an, lună, zi, ore, minute și, opțional, secunde (clasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Pentru valoarea implicită, acceptă fie obiecte care implementează `DateTimeInterface`, fie un șir de caractere cu ora, fie un număr reprezentând un timestamp UNIX. Același lucru este valabil și pentru argumentele regulilor `Min`, `Max` sau `Range`, care definesc data minimă și maximă admisă.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+În mod implicit, returnează un obiect `DateTimeImmutable`. Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] sau un timestamp:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Adaugă un câmp de selecție a culorilor (clasa [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Culoarea este un șir de caractere în formatul `#rrggbb`. Dacă utilizatorul nu face o selecție, culoarea implicită returnată este negru `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Adaugă un câmp ascuns (clasa [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Folosiți `setNullable()` pentru a-l schimba pentru a returna `null` în loc de un șir gol. [AddFilter() |validation#Modifying Input Values] vă permite să modificați valoarea trimisă.
 
+Deși elementul este ascuns, este **important de realizat** că valoarea sa poate fi modificată sau falsificată de un atacator. Întotdeauna verificați și validați temeinic toate valorile primite pe partea serverului pentru a preveni riscurile de securitate asociate cu manipularea datelor.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Adaugă un buton de trimitere sub forma unei imagini (clasa [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Următoarele metode pot fi apelate pentru elementele `addText()`, `addPassword()
 
 
 Valori omise .[#toc-omitted-values]
------------------------------------
+===================================
 
 Dacă nu vă interesează valoarea introdusă de utilizator, putem folosi `setOmitted()` pentru a o omite din rezultatul furnizat de metoda `$form->getValues​()` sau transmis către gestionari. Acest lucru este potrivit pentru diverse parole de verificare, câmpuri antispam etc.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Dezactivarea intrărilor .[#toc-disabling-inputs]
-------------------------------------------------
+================================================
 
-Pentru a dezactiva o intrare, puteți apela `setDisabled()`. Un astfel de câmp nu poate fi editat de către utilizator.
+Intrările pot fi dezactivate folosind `setDisabled()`. O intrare dezactivată nu poate fi editată de către utilizator.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Rețineți că browserul nu trimite deloc câmpurile dezactivate către server, astfel încât nici măcar nu le veți găsi în datele returnate de funcția `$form->getValues()`.
+Intrările dezactivate nu sunt trimise la server de către browser, deci nu le veți găsi în datele returnate de funcția `$form->getValues()`. Cu toate acestea, dacă setați `setOmitted(false)`, Nette va include valoarea lor implicită în aceste date.
 
-Dacă setați o valoare implicită pentru un câmp, trebuie să faceți acest lucru numai după ce l-ați dezactivat:
+Când este apelată `setDisabled()`, **valoarea intrării este ștearsă** din motive de securitate. Dacă setați o valoare implicită, este necesar să faceți acest lucru după dezactivarea acesteia:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+O alternativă la intrările dezactivate sunt câmpurile cu atributul HTML `readonly`, care sunt trimise la server de către browser. Deși câmpul este doar lizibil, este **important de realizat** că valoarea sa poate fi în continuare modificată sau falsificată de un atacator.
+
 
 Controale personalizate .[#toc-custom-controls]
 ===============================================
@@ -428,8 +525,8 @@ Există o modalitate de a defini noi metode de formular pentru adăugarea de ele
 ```php
 use Nette\Forms\Container;
 
-// adaugă metoda addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// adaugă metoda addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/ro/in-presenter.texy b/forms/ro/in-presenter.texy
index fb18bf4c66..74b3e875c1 100644
--- a/forms/ro/in-presenter.texy
+++ b/forms/ro/in-presenter.texy
@@ -30,7 +30,7 @@ Formularul din prezentator este un obiect din clasa `Nette\Application\UI\Form`,
 
 Din punctul de vedere al prezentatorului, formularul este o componentă comună. Prin urmare, acesta este tratat ca o componentă și încorporat în prezentator folosind [metoda factory |application:components#Factory Methods]. Acesta va arăta astfel:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Iar redarea în șablon se face cu ajutorul etichetei `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Formularul este întotdeauna validat pe partea serverului, dar este generată ș
 Introduceți-l în șablonul de prezentare:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Dacă vă uitați în codul sursă al paginii cu formular, puteți observa că Nette inserează câmpurile obligatorii în elemente cu o clasă CSS `required`. Încercați să adăugați următorul stil în șablon, iar eticheta "Name" va fi roșie. În mod elegant, marcăm câmpurile obligatorii pentru utilizatori:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Începând cu PHP 8.0, puteți utiliza această notație elegantă care folosește un constructor:
+Alternativ, puteți utiliza constructorul:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Proprietățile clasei de date pot fi, de asemenea, enumuri, iar acestea vor fi mapate automat. .{data-version:3.2.4}
+
 Cum să îi spuneți lui Nette să returneze datele ca obiecte din această clasă? Mai ușor decât credeți. Tot ceea ce trebuie să faceți este să specificați clasa ca tip al parametrului `$data` în handler:
 
 ```php
@@ -294,6 +296,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Puteți genera o propunere pentru clasa de date a unui formular utilizând metoda `Nette\Forms\Blueprint::dataClass($form)`, care o va imprima în pagina browserului. Puteți apoi să dați un simplu clic pentru a selecta și a copia codul în proiectul dumneavoastră. .{data-version:3.1.15}
+
 
 Butoane de trimitere multiple .[#toc-multiple-submit-buttons]
 =============================================================
diff --git a/forms/ro/rendering.texy b/forms/ro/rendering.texy
index 1eb25cc947..cf8feb2be3 100644
--- a/forms/ro/rendering.texy
+++ b/forms/ro/rendering.texy
@@ -11,6 +11,8 @@ Renderizare cu Latte .[#toc-rendering-with-latte]
 
  [Sistemul de modelare Latte |latte:] facilitează în mod fundamental redarea formularelor și a elementelor acestora. În primul rând, vom arăta cum să redăm formularele manual, element cu element, pentru a obține un control total asupra codului. Ulterior vom arăta cum să [automatizăm |#Automatic rendering] această redare.
 
+Puteți obține propunerea unui șablon Latte pentru formularul generat cu ajutorul metodei `Nette\Forms\Blueprint::latte($form)`, care îl va afișa în pagina de browser. Apoi, trebuie doar să selectați codul cu un clic și să îl copiați în proiectul dvs. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Elementele de formular mai complexe, cum ar fi RadioList sau CheckboxList, pot f
 ```
 
 
-Propunere de cod `{formPrint}` .[#toc-formprint]
-------------------------------------------------
-
-Puteți genera un cod Latte similar pentru un formular folosind eticheta `{formPrint}`. Dacă îl plasați într-un șablon, veți vedea proiectul de cod în loc de redarea normală. Apoi, nu trebuie decât să îl selectați și să îl copiați în proiectul dvs.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Trebuie doar să importați blocul într-un singur loc, la începutul modelului
 Cazuri speciale .[#toc-special-cases]
 -------------------------------------
 
-Dacă aveți nevoie doar de redarea conținutului interior al unui formular fără `<form>` & `</form>` HTML, de exemplu, într-o solicitare AJAX, puteți deschide și închide formularul cu `{formContext} … {/formContext}`. Funcționează similar cu `{form}` în sens logic, aici vă permite să utilizați alte etichete pentru a desena elementele formularului, dar în același timp nu desenează nimic.
+Dacă aveți nevoie să redați doar partea interioară a formularului fără etichete HTML `<form>`de exemplu, atunci când trimiteți fragmente, ascundeți-le folosind atributul `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Tag-ul `formContainer` ajută la redarea intrărilor în interiorul unui container de formular.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Dispozitivul de redare desenează mai întâi grupurile și apoi elementele care nu aparțin niciunui grup.
+
 
 Suport Bootstrap .[#toc-bootstrap-support]
 ------------------------------------------
@@ -444,7 +442,7 @@ Puteți găsi [exemple |https://github.com/nette/forms/tree/master/examples] de
 Atribute HTML .[#toc-html-attributes]
 =====================================
 
-Puteți seta orice atribute HTML pentru controalele de formular folosind `setHtmlAttribute(string $name, $value = true)`:
+Pentru a seta atribute HTML arbitrare pentru elementele de formular, utilizați metoda `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // solicită funcția JS submit() la schimbare
 
 
-// se aplică la <form>
+// Pentru a seta atributele <form> în sine
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Setarea tipului de intrare:
+Specificarea tipului de element:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-Putem seta atributul HTML pentru elementele individuale din listele radio sau checkbox cu valori diferite pentru fiecare dintre ele.
-Rețineți două puncte după `style:` pentru a vă asigura că valoarea este selectată prin cheie:
+.[warning]
+Setarea tipului și a altor atribute servește doar în scopuri vizuale. Verificarea corectitudinii intrărilor trebuie să aibă loc pe server, lucru pe care îl puteți asigura prin alegerea unui [control de formular | controls] adecvat și prin specificarea [regulilor de validare | validation].
+
+Pentru elementele individuale din listele de tip radio sau checkbox, putem seta un atribut HTML cu valori diferite pentru fiecare dintre ele.
+Observați cele două puncte după `style:`, care asigură că valoarea este selectată pe baza cheii:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Redă:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Pentru un atribut HTML logic (care nu are nicio valoare, cum ar fi `readonly`), puteți utiliza un semn de întrebare:
+Pentru stabilirea atributelor booleene, cum ar fi `readonly`, se poate utiliza notația cu semnul întrebării:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // se utilizează matrice pentru mai multe chei, de exemplu ['r', 'g']
 ```
@@ -541,9 +541,6 @@ Pentru elementele Checkbox, CheckboxList și RadioList puteți influența șablo
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/ro/standalone.texy b/forms/ro/standalone.texy
index 34ec299bb0..8cac253962 100644
--- a/forms/ro/standalone.texy
+++ b/forms/ro/standalone.texy
@@ -107,7 +107,7 @@ Formularul este întotdeauna validat pe partea serverului, dar este generată ș
 Adăugați-l în pagină:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Dacă vă uitați în codul sursă al paginii cu formular, puteți observa că Nette inserează câmpurile obligatorii în elemente cu o clasă CSS `required`. Încercați să adăugați următorul stil în șablon, iar eticheta "Name" va fi roșie. În mod elegant, marcăm câmpurile obligatorii pentru utilizatori:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Începând cu PHP 8.0, puteți utiliza această notație elegantă care folosește un constructor:
+Alternativ, puteți utiliza constructorul:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Proprietățile clasei de date pot fi, de asemenea, enumuri, iar acestea vor fi mapate automat. .{data-version:3.2.4}
+
 Cum să îi spunem lui Nette să ne returneze datele ca obiecte din această clasă? Mai ușor decât credeți. Tot ce trebuie să faceți este să specificați ca parametru numele clasei sau obiectul de hidratat:
 
 ```php
@@ -258,6 +260,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Puteți genera o propunere pentru clasa de date a unui formular utilizând metoda `Nette\Forms\Blueprint::dataClass($form)`, care o va imprima în pagina browserului. Puteți apoi să dați un simplu clic pentru a selecta și a copia codul în proiectul dumneavoastră. .{data-version:3.1.15}
+
 
 Butoane de trimitere multiple .[#toc-multiple-submit-buttons]
 =============================================================
diff --git a/forms/ro/validation.texy b/forms/ro/validation.texy
index 87d26482db..2ad6144a72 100644
--- a/forms/ro/validation.texy
+++ b/forms/ro/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette vine cu un număr de reguli încorporate ale căror nume sunt constante ale clasei `Nette\Forms\Form`:
+**Regula de validare este verificată numai dacă utilizatorul a completat elementul.**
 
-Putem utiliza următoarele reguli pentru toate controalele:
+Nette vine cu un număr de reguli predefinite ale căror nume sunt constante din clasa `Nette\Forms\Form`. Putem aplica aceste reguli la toate elementele:
 
 | constantă | descriere | argumente
 |-------
@@ -38,7 +38,11 @@ Putem utiliza următoarele reguli pentru toate controalele:
 | `IsNotIn` | valoarea nu este egală cu nici un element din matrice | `array`
 | `Valid` | input passes validation (for [conditions |#conditions]) | -
 
-Pentru controalele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` se pot utiliza, de asemenea, următoarele reguli:
+
+Intrări de text .[#toc-text-inputs]
+-----------------------------------
+
+Pentru elementele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` se pot aplica, de asemenea, unele dintre următoarele reguli:
 
 | `MinLength` | lungime minimă a șirului de caractere | `int`
 | `MaxLength` | lungime maximă a șirului de caractere | `int`
@@ -57,9 +61,23 @@ Pentru controalele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`,
 Regulile `Integer`, `Numeric` și `Float` convertesc automat valoarea în număr întreg (sau, respectiv, flotant). În plus, regula `URL` acceptă și o adresă fără o schemă (de exemplu, `nette.org`) și completează schema (`https://nette.org`).
 Expresiile din `Pattern` și `PatternInsensitive` trebuie să fie valabile pentru întreaga valoare, adică ca și cum ar fi înfășurată în caracterele `^` and `$`.
 
+
+Număr de articole .[#toc-number-of-items]
+-----------------------------------------
+
+Pentru elementele `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` puteți utiliza, de asemenea, următoarele reguli pentru a limita numărul de elemente selectate sau de fișiere încărcate:
+
+| `MinLength` | număr minim | `int`
+| `MaxLength` | număr maxim | `int`
+| `Length` | număr în interval sau număr exact | perechi `[int, int]` sau `int`
+
+
+Încărcare fișier
+----------------
+
 Pentru controalele `addUpload()`, `addMultiUpload()` se pot utiliza, de asemenea, următoarele reguli:
 
-| `MaxFileSize` | dimensiunea maximă a fișierului | `int`
+| `MaxFileSize` | dimensiunea maximă a fișierului în bytes | `int`
 | `MimeType` | tip MIME, acceptă wildcards (`'video/*'`) | `string\|string[]`
 | `Image` | fișierul încărcat este JPEG, PNG, GIF, WebP | -
 | `Pattern` | numele fișierului se potrivește cu o expresie regulată | `string`
@@ -67,15 +85,9 @@ Pentru controalele `addUpload()`, `addMultiUpload()` se pot utiliza, de asemenea
 
  `MimeType` și `Image` necesită extensia PHP `fileinfo`. Dacă un fișier sau o imagine este de tipul cerut este detectat prin semnătura sa. Integritatea întregului fișier nu este verificată. Puteți afla dacă o imagine nu este coruptă, de exemplu, încercând să [o încărcați |http:request#toImage].
 
-Pentru controalele `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` se pot utiliza, de asemenea, următoarele reguli pentru a limita numărul de elemente selectate, respectiv de fișiere încărcate:
-
-| `MinLength` | număr minim | `int`
-| `MaxLength` | număr maxim | `int`
-| `Length` | număr în interval sau număr exact | pereche `[int, int]` sau `int`
-
 
 Mesaje de eroare .[#toc-error-messages]
----------------------------------------
+=======================================
 
 Toate regulile predefinite, cu excepția `Pattern` și `PatternInsensitive`, au un mesaj de eroare implicit, astfel încât acestea pot fi omise. Cu toate acestea, dacă treceți și formulați toate mesajele personalizate, veți face formularul mai ușor de utilizat.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 În Nette, este foarte ușor să reacționați la îndeplinirea sau nu a unei condiții pe partea de JavaScript folosind metoda `toggle()`, consultați [Dynamic JavaScript |#Dynamic JavaScript].
 
 
-Referințe între controale .[#toc-references-between-controls]
-=============================================================
+Trimitere la un alt element .[#toc-reference-to-another-element]
+================================================================
 
-Argumentul regulii sau al condiției poate fi o referință la un alt element. De exemplu, puteți valida în mod dinamic faptul că `text` are atâtea caractere cât este valoarea câmpului `length`:
+Ca argument pentru o regulă sau o condiție, puteți trece și un alt element de formular. Regula va utiliza apoi valoarea introdusă ulterior de utilizator în browser. Acest lucru poate fi utilizat, de exemplu, pentru a valida dinamic faptul că elementul `password` conține același șir de caractere ca elementul `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Acest script este `netteForms.js`, care este disponibil din mai multe surse posi
 Puteți încorpora scriptul direct în pagina HTML din CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Sau copiați local în folderul public al proiectului (de exemplu, de la `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/ru/controls.texy b/forms/ru/controls.texy
index 00e30764f1..d4e26fffc1 100644
--- a/forms/ru/controls.texy
+++ b/forms/ru/controls.texy
@@ -5,8 +5,8 @@
 Обзор встроенных элементов управления формой.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Добавляет однострочное текстовое поле (класс [TextInput |api:Nette\Forms\Controls\TextInput]). Если пользователь не заполнил поле, возвращается пустая строка `''`, или используйте `setNullable()` для возврата `null`.
 
@@ -20,13 +20,10 @@ $form->addText('name', 'Имя:')
 
 Максимальная длина может быть ограничена с помощью `setMaxLength()`. Функция [addFilter()|validation#Modifying-Input-Values] позволяет изменить введенное пользователем значение.
 
-Используйте `setHtmlType()` для изменения [типа|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] элемента ввода на `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Вместо типов `number` и `email` мы рекомендуем использовать [#addInteger] и [#addEmail], которые обеспечивают валидацию на стороне сервера.
+Вы можете изменить визуальный характер текстового поля на такие типы, как `search`, `tel`, или `url` с использованием `setHtmlType()`, как показано в [спецификации |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Помните, что изменение типа является только визуальным и не выполняет функции проверки. Для типа `url` целесообразно добавить специальное [правило URL |validation#Text inputs].
 
-```php
-$form->addText('color', 'Выберите цвет:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'недопустимое значение', '[0-9a-f]{6}');
-```
+.[note]
+Для других типов ввода, таких как `number`, `range`, `email`, `date`, `datetime-local`, `time` и `color`, используйте специализированные методы [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] и [addColor |#addColor], которые обеспечивают валидацию на стороне сервера. Типы `month` и `week` пока не полностью поддерживаются во всех браузерах.
 
 Для элемента может быть установлено так называемое «пустое значение», которое является чем-то вроде значения по умолчанию, но если пользователь не перезаписывает его, возвращает пустую строку или `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Добавляет поле ввода для целого числа (класс [TextInput |api:Nette\Forms\Controls\TextInput]). Возвращает либо целое число, либо `null`, если пользователь ничего не ввел.
 
 ```php
-$form->addInteger('level', 'Уровень:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'Год должен быть в диапазоне от %d до %d.', [1900, 2023 |1900, 2023]);
+```
+
+Элемент отображается как `<input type="numeric">`. Используя метод `setHtmlType()`, вы можете изменить тип на `range` для отображения в виде слайдера или на `text`, если вы предпочитаете обычное текстовое поле без специального поведения `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]);
+->addRule($form::Range, 'Уровень должен находиться в диапазоне от %d до %d.', [0, 100 |0, 100]);
 ```
 
+Элемент отображается как `<input type="numeric">`. Используя метод `setHtmlType()`, вы можете изменить тип на `range` для отображения в виде слайдера или на `text`, если вы предпочитаете обычное текстовое поле без специального поведения `numeric`.
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+Nette и браузер Chrome принимают запятую и точку в качестве десятичных разделителей. Чтобы сделать эту функцию доступной в Firefox, рекомендуется установить атрибут `lang` либо для конкретного элемента, либо для всей страницы, например, `<html lang="cs">`.
+
+
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Добавляет поле адреса электронной почты с проверкой достоверности (класс [TextInput |api:Nette\Forms\Controls\TextInput]). Если пользователь не заполнил поле, возвращается пустая строка `''`, или используйте `setNullable()` для возврата `null`.
 
@@ -78,8 +92,8 @@ $form->addEmail('email', 'Имейл:');
 Максимальная длина может быть ограничена с помощью `setMaxLength()`. Функция [addFilter()|validation#Modifying-Input-Values] позволяет изменить введенное пользователем значение. Вы можете установить так называемое «пустое значение», используя `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Добавляет поле пароля (класс [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'Я согласен с условиями')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Добавляет список флажков для выбора нескольких элементов (класс [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Возвращает массив ключей выбранных элементов. Метод `getSelectedItems()` возвращает значения вместо ключей.
 
@@ -125,9 +139,15 @@ $form->addCheckboxList('colors', 'Цвета:', [
 
 При установке значений по умолчанию также проверяется, что они являются одним из предлагаемых элементов, в противном случае возникает исключение. Эта проверка может быть отключена с помощью `checkDefaultValue(false)`.
 
+Если вы отправляете форму с помощью метода `GET`, вы можете выбрать более компактный способ передачи данных, который позволяет сэкономить на размере строки запроса. Это активируется установкой атрибута HTML формы:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Добавляет радиокнопки (класс [RadioList |api:Nette\Forms\Controls\RadioList]). Возвращает ключ выбранного элемента или `null`, если пользователь ничего не выбрал. Метод `getSelectedItem()` возвращает значение вместо ключа.
 
@@ -148,8 +168,8 @@ $form->addRadioList('gender', 'Пол:', $sex);
 При установке значения по умолчанию проверяется, что оно является одним из предлагаемых элементов, в противном случае возникает исключение. Эта проверка может быть отключена с помощью `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Добавляет поле выбора (класс [SelectBox |api:Nette\Forms\Controls\SelectBox]). Возвращает ключ выбранного элемента или `null`, если пользователь ничего не выбрал. Метод `getSelectedItem()` возвращает значение вместо ключа.
 
@@ -193,8 +213,8 @@ $form->addSelect('country', 'Страна:', $countries)
 При установке значения по умолчанию проверяется, что оно является одним из предлагаемых элементов, в противном случае возникает исключение. Эта проверка может быть отключена с помощью `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Добавляет окно выбора нескольких вариантов (класс [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Возвращает массив ключей выбранных элементов. Метод `getSelectedItems()` возвращает значения вместо ключей.
 
@@ -246,8 +266,81 @@ $form->addMultiUpload('files', 'Файлы:')
 Правила `MimeType` и `Image` определяют необходимый тип файла или изображения по его сигнатуре. Целостность всего файла не проверяется. Вы можете узнать, не повреждено ли изображение, например, попытавшись [загрузить его|http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Добавляет поле, позволяющее пользователю легко вводить дату, состоящую из года, месяца и дня (класс [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+В качестве значения по умолчанию он принимает либо объекты, реализующие `DateTimeInterface`, либо строку с временем, либо число, представляющее временную метку UNIX. То же самое относится и к аргументам правил `Min`, `Max` или `Range`, которые определяют минимально и максимально допустимую дату.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+По умолчанию возвращается объект `DateTimeImmutable`. С помощью метода `setFormat()` можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или временную метку:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Добавляет поле, позволяющее пользователю легко вводить время, состоящее из часов, минут и, по желанию, секунд (класс [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+В качестве значения по умолчанию оно принимает либо объекты, реализующие `DateTimeInterface`, либо строку с временем, либо число, представляющее временную метку UNIX. Используется только информация о времени из этих входов, дата игнорируется. То же самое относится и к аргументам правил `Min`, `Max` или `Range`, которые определяют минимальное и максимальное допустимое время. Если минимальное значение больше максимального, то создается временной диапазон, охватывающий полночь.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+По умолчанию он возвращает объект `DateTimeImmutable` (с датой 1 января, год 1). С помощью метода `setFormat()` можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Добавляет поле, позволяющее пользователю легко вводить дату и время, состоящие из года, месяца, дня, часов, минут и, по желанию, секунд (класс [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+В качестве значения по умолчанию он принимает либо объекты, реализующие `DateTimeInterface`, либо строку с временем, либо число, представляющее временную метку UNIX. То же самое относится и к аргументам правил `Min`, `Max` или `Range`, которые определяют минимально и максимально допустимую дату.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+По умолчанию возвращается объект `DateTimeImmutable`. С помощью метода `setFormat()` можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или временную метку:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Добавляет поле выбора цвета (класс [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Цвет представляет собой строку в формате `#rrggbb`. Если пользователь не делает выбора, то по умолчанию возвращается черный цвет `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Добавляет скрытое поле (класс [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Используйте `setNullable()`, чтобы изменить его так, чтобы он возвращал `null` вместо пустой строки. Функция [addFilter()|validation#Modifying-Input-Values] позволяет изменить представленное значение.
 
+Хотя элемент скрыт, **важно понимать**, что его значение все равно может быть изменено или подделано злоумышленником. Всегда тщательно проверяйте и проверяйте все полученные значения на стороне сервера, чтобы предотвратить риски безопасности, связанные с манипулированием данными.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Поднять зарплату')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Добавляет кнопку отправки в виде изображения (класс [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ $sub2->addEmail('email', 'Имейл:');
 
 
 Опущенные значения .[#toc-omitted-values]
------------------------------------------
+=========================================
 
 Если вас не интересует значение, введенное пользователем, мы можем использовать `setOmitted()`, чтобы опустить его из результата, предоставляемого методом `$form->getValues()` или передаваемого обработчикам. Это подходит для различных паролей для проверки, антиспамовых полей и т. д.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Повторите пароль:')
 
 
 Отключение элементов ввода .[#toc-disabling-inputs]
----------------------------------------------------
+===================================================
 
-Чтобы отключить вход, вы можете вызвать `setDisabled()`. Такое поле не может быть отредактировано пользователем.
+Входы можно отключить с помощью `setDisabled()`. Отключенный вход не может быть отредактирован пользователем.
 
 ```php
 $form->addText('username', 'Имя пользователя:')
 	->setDisabled();
 ```
 
-Обратите внимание, что браузер вообще не отправляет отключенные поля на сервер, поэтому вы даже не найдете их в данных, возвращаемых функцией `$form->getValues()`.
+Отключенные входы не отправляются браузером на сервер, поэтому вы не найдете их в данных, возвращаемых функцией `$form->getValues()`. Однако если вы зададите `setOmitted(false)`, Nette включит их значение по умолчанию в эти данные.
 
-Если вы устанавливаете значение по умолчанию для поля, вы должны сделать это только после его отключения:
+Когда вызывается `setDisabled()`, **значение входных данных стирается** в целях безопасности. Если вы устанавливаете значение по умолчанию, необходимо сделать это после его деактивации:
 
 ```php
 $form->addText('username', 'Имя пользователя:')
@@ -409,6 +504,8 @@ $form->addText('username', 'Имя пользователя:')
 	->setDefaultValue($userName);
 ```
 
+Альтернативой отключенным входам являются поля с атрибутом HTML `readonly`, которые отправляются на сервер браузером. Хотя это поле можно только читать, **важно понимать**, что его значение все равно может быть изменено или подделано злоумышленником.
+
 
 Пользовательские элементы управления .[#toc-custom-controls]
 ============================================================
@@ -428,8 +525,8 @@ $form->addComponent(new DateInput('Дата:'), 'date');
 ```php
 use Nette\Forms\Container;
 
-// добавляет метод addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// добавляет метод addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Не менее 5 номеров', '[0-9]{5}');
 });
diff --git a/forms/ru/in-presenter.texy b/forms/ru/in-presenter.texy
index f8ba0bff66..eb8631fb44 100644
--- a/forms/ru/in-presenter.texy
+++ b/forms/ru/in-presenter.texy
@@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded'];
 
 С точки зрения презентера форма является общим компонентом. Поэтому она рассматривается как компонент и включается в презентер с помощью [фабричного метода |application:components#Factory-Methods]. Это будет выглядеть следующим образом:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 А рендеринг в шаблоне осуществляется с помощью тега `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Регистрация</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ $form->addText('name', 'Имя:')
 Вставьте его в шаблон макета:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Если вы посмотрите в исходный код страницы с формой, вы можете заметить, что Nette вставляет обязательные поля в элементы с CSS-классом `required`. Попробуйте добавить следующий стиль в шаблон, и метка "Имя" будет красного цвета. Мы элегантно помечаем обязательные поля для пользователей:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Начиная с PHP 8.0, вы можете использовать эту элегантную нотацию, которая использует конструктор:
+В качестве альтернативы можно использовать конструктор:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Свойства класса данных также могут быть перечислениями, и они будут автоматически сопоставлены. .{data-version:3.2.4}
+
 Как указать Nette возвращать данные в виде объектов этого класса? Легче, чем вы думаете. Все, что вам нужно сделать, это указать класс в качестве типа параметра `$data` в обработчике:
 
 ```php
@@ -294,6 +296,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Сгенерировать предложение для класса данных формы можно с помощью метода `Nette\Forms\Blueprint::dataClass($form)`, который выведет его на страницу браузера. Затем можно просто щелчком мыши выделить и скопировать код в свой проект. .{data-version:3.1.15}
+
 
 Несколько кнопок отправки .[#toc-multiple-submit-buttons]
 =========================================================
diff --git a/forms/ru/rendering.texy b/forms/ru/rendering.texy
index 0d1a640600..183aeda9f2 100644
--- a/forms/ru/rendering.texy
+++ b/forms/ru/rendering.texy
@@ -11,6 +11,8 @@
 
 [Система шаблонов Latte |latte:] в корне облегчает отрисовку форм и их элементов. Сначала мы покажем, как отрисовывать формы вручную, элемент за элементом, чтобы получить полный контроль над кодом. Позже мы покажем, как [автоматизировать |#Automatic-Rendering] такой рендеринг.
 
+Предложение шаблона Latte для формы можно сгенерировать с помощью метода `Nette\Forms\Blueprint::latte($form)`, который выведет его на страницу браузера. Затем достаточно выделить код щелчком мыши и скопировать его в свой проект. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form
 ```
 
 
-Предложение кода `{formPrint}` .[#toc-formprint]
-------------------------------------------------
-
-Вы можете сгенерировать подобный код Latte для формы, используя тег `{formPrint}`. Если вы поместите его в шаблон, вы увидите проект кода вместо обычного рендеринга. Затем просто выделите его и скопируйте в свой проект.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ protected function createComponentSignInForm(): Form
 Особые случаи .[#toc-special-cases]
 -----------------------------------
 
-Если вам нужно отобразить только внутреннее содержимое формы без `<form>` & `</form>` HTML тегов, например, в AJAX запросе, вы можете открывать и закрывать форму с помощью `{formContext} … {/formContext}`. Он работает аналогично `{form}` в логическом смысле, здесь он позволяет вам использовать другие теги для рисования элементов формы, но в то же время он ничего не рисует.
+Если необходимо отобразить только внутреннюю часть формы без HTML-тегов `<form>`например, при отправке сниппетов, скройте их с помощью атрибута `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Имя пользователя: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Тег `formContainer` помогает при отрисовке вводимых данных внутри контейнера формы.
@@ -434,6 +430,8 @@ $form->addText('city', 'Город:');
 $form->addSelect('country', 'Страна:', $countries);
 ```
 
+Сначала рендерер отрисовывает группы, а затем элементы, не принадлежащие ни к одной из групп.
+
 
 Поддержка Bootstrap .[#toc-bootstrap-support]
 ---------------------------------------------
@@ -444,7 +442,7 @@ $form->addSelect('country', 'Страна:', $countries);
 Атрибуты HTML .[#toc-html-attributes]
 =====================================
 
-Вы можете установить любые атрибуты HTML для элементов управления формы с помощью `setHtmlAttribute(string $name, $value = true)`:
+Чтобы задать произвольные HTML-атрибуты для элементов формы, используйте метод `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Количество:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Заказать:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // вызывает JS-функцию submit() при изменении
 
 
-// применяется на <form>
+// Для установки атрибутов самого <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Установка типа входа:
+Указание типа элемента:
 
 ```php
 $form->addText('tel', 'Ваш телефон:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Ваш телефон:')
 	->setHtmlAttribute('placeholder', 'Пожалуйста, заполните ваш телефон');
 ```
 
-Мы можем установить HTML-атрибут для отдельных элементов в списках радио- или чекбоксов с разными значениями для каждого из них.
-Обратите внимание на двоеточие после `style:`, чтобы убедиться, что значение выбирается по ключу:
+.[warning]
+Установка типа и других атрибутов служит только для визуальных целей. Проверка правильности ввода должна происходить на сервере, что можно обеспечить, выбрав соответствующий [элемент управления формой | controls] и задав [правила проверки | validation].
+
+Для отдельных элементов в списках радио- или чекбоксов мы можем задать HTML-атрибут с разными значениями для каждого из них.
+Обратите внимание на двоеточие после `style:`, которое обеспечивает выбор значения на основе ключа:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ $form->addCheckboxList('colors', 'Цвета:', $colors)
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Для логического атрибута HTML (который не имеет значения, например, `readonly`) можно использовать вопросительный знак:
+Для задания булевых атрибутов, таких как `readonly`, можно использовать обозначение с вопросительным знаком:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Цвета:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // использовать массив для нескольких ключей, например ['r', 'g']
 ```
@@ -541,9 +541,6 @@ $html->class('distinctive');         // <label class="distinctive">
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/ru/standalone.texy b/forms/ru/standalone.texy
index 65912b061e..08a9bf428a 100644
--- a/forms/ru/standalone.texy
+++ b/forms/ru/standalone.texy
@@ -107,7 +107,7 @@ $form->addText('name', 'Имя:')
 Добавьте его на страницу:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Если вы посмотрите в исходный код страницы с формой, вы можете заметить, что Nette вставляет обязательные поля в элементы с CSS-классом `required`. Попробуйте добавить следующий стиль в шаблон, и метка "Имя" будет красного цвета. Мы элегантно помечаем обязательные поля для пользователей:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Начиная с PHP 8.0, вы можете использовать эту элегантную нотацию, которая использует конструктор:
+В качестве альтернативы можно использовать конструктор:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Свойства класса данных также могут быть перечислениями, и они будут автоматически сопоставлены. .{data-version:3.2.4}
+
 Как сказать Nette, чтобы он возвращал нам данные в виде объектов этого класса? Легче, чем вы думаете. Всё, что вам нужно сделать, это указать имя класса или объекта для гидратации в качестве параметра:
 
 ```php
@@ -258,6 +260,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Сгенерировать предложение для класса данных формы можно с помощью метода `Nette\Forms\Blueprint::dataClass($form)`, который выведет его на страницу браузера. Затем можно просто щелчком мыши выделить и скопировать код в свой проект. .{data-version:3.1.15}
+
 
 Несколько кнопок отправки .[#toc-multiple-submit-buttons]
 =========================================================
diff --git a/forms/ru/validation.texy b/forms/ru/validation.texy
index b3f60e1a21..26b6a03f38 100644
--- a/forms/ru/validation.texy
+++ b/forms/ru/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Пароль:')
 	->addRule($form::MinLength, 'Пароль должен состоять не менее чем из %d символов', 8);
 ```
 
-Nette поставляется с рядом встроенных правил, имена которых являются константами класса `Nette\Forms\Form`:
+**Правила валидации проверяются только в том случае, если пользователь заполнил элемент.**
 
-Мы можем использовать следующие правила для всех элементов управления:
+Nette поставляется с рядом предопределенных правил, имена которых являются константами класса `Nette\Forms\Form`. Мы можем применять эти правила ко всем элементам:
 
 | константа | описание | аргументы
 |-------
@@ -38,7 +38,11 @@ Nette поставляется с рядом встроенных правил,
 | `IsNotIn` | значение не равно ни одному элементу массива | `array`
 | `Valid` | ввод проходит валидацию (для [#Условия])  | -
 
-Для элементов управления `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` также могут быть использованы следующие правила:
+
+Текстовые вводы .[#toc-text-inputs]
+-----------------------------------
+
+Для элементов `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` также могут быть применены некоторые из следующих правил:
 
 | `MinLength` | минимальная длина строки | `int`
 | `MaxLength` | максимальная длина строки | `int`
@@ -57,9 +61,23 @@ Nette поставляется с рядом встроенных правил,
 Правила `Integer`, `Numeric` и `Float` автоматически преобразуют значение в целое (или плавающее соответственно). Более того, правило `URL` также принимает адрес без схемы (например, `nette.org`) и дополняет схему (`https://nette.org`).
 Выражения в `Pattern` и `PatternInsensitive` должны быть действительны для всего значения, т. е. как если бы оно было обернуто в символы `^` и `$`.
 
+
+Количество предметов .[#toc-number-of-items]
+--------------------------------------------
+
+Для элементов `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` также можно использовать следующие правила для ограничения количества выбранных элементов или загруженных файлов:
+
+| `MinLength` | минимальное количество | `int`
+| `MaxLength` | максимальное количество | `int`
+| `Length` | число в диапазоне или точное число | пары `[int, int]` или `int`
+
+
+Загрузка файлов
+---------------
+
 Для элементов управления `addUpload()`, `addMultiUpload()` также могут быть использованы следующие правила:
 
-| `MaxFileSize` | максимальный размер файла | `int`
+| `MaxFileSize` | Максимальный размер файла в байтах | `int`
 | `MimeType` | Тип MIME, принимает подстановочные знаки (`'video/*'`) | `string\|string[]`
 | `Image` | загруженный файл является JPEG, PNG, GIF, WebP | -
 | `Pattern` | имя файла соответствует регулярному выражению | `string`
@@ -67,15 +85,9 @@ Nette поставляется с рядом встроенных правил,
 
 Для `MimeType` и `Image` требуется расширение PHP `fileinfo`. Принадлежность файла или изображения к нужному типу определяется по его сигнатуре. Целостность всего файла не проверяется. Вы можете узнать, не повреждено ли изображение, например, попытавшись [загрузить его|http:request#toImage].
 
-Для элементов управления `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` следующие правила также могут быть использованы для ограничения количества выбранных элементов, соответственно загруженных файлов:
-
-| `MinLength` | минимальное количество | `int`
-| `MaxLength` | максимальное количество | `int`
-| `Length` | количество в диапазоне или точное количество | пара `[int, int]` или `int`
-
 
 Сообщения об ошибках .[#toc-error-messages]
--------------------------------------------
+===========================================
 
 Все предопределенные правила, кроме `Pattern` и `PatternInsensitive`, имеют сообщение об ошибке по умолчанию, поэтому их можно опустить. Однако, передав и сформулировав все индивидуальные сообщения, вы сделаете форму более удобной для пользователя.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 В Nette очень легко реагировать на выполнение или невыполнение условия на стороне JavaScript, используя метод `toggle()`, см. [#Динамический JavaScript].
 
 
-Ссылки между элементами управления .[#toc-references-between-controls]
-======================================================================
+Ссылка на другой элемент .[#toc-reference-to-another-element]
+=============================================================
 
-Аргумент правила или условия может быть ссылкой на другой элемент. Например, вы можете динамически подтвердить, что `text` имеет столько символов, сколько указано в поле `length`:
+В качестве аргумента для правила или условия можно также передать другой элемент формы. Тогда правило будет использовать значение, введенное позже пользователем в браузере. Это можно использовать, например, для динамической проверки того, что элемент `password` содержит ту же строку, что и элемент `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ $form->addText('zip', 'Почтовый индекс:')
 Вы можете встроить сценарий непосредственно в HTML-страницу из CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Или скопируйте локально в общую папку проекта (например, с сайта `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/sl/controls.texy b/forms/sl/controls.texy
index 4caa6b7f5c..7d27e68044 100644
--- a/forms/sl/controls.texy
+++ b/forms/sl/controls.texy
@@ -5,8 +5,8 @@ Krmilniki obrazca
 Pregled vgrajenih kontrolnih elementov obrazca.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Doda enovrstično besedilno polje (razred [TextInput |api:Nette\Forms\Controls\TextInput]). Če uporabnik ne izpolni polja, vrne prazen niz `''`, ali pa ga z uporabo `setNullable()` spremeni tako, da vrne `null`.
 
@@ -20,13 +20,10 @@ Samodejno potrdi UTF-8, obreže leve in desne bele prostore ter odstrani prelome
 
 Največjo dolžino lahko omejite z uporabo `setMaxLength()`. S funkcijo [addFilter() |validation#Modifying Input Values] lahko spremenite uporabniško vneseno vrednost.
 
-Z uporabo `setHtmlType()` spremenite [znak |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vhodnega elementa v `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Namesto tipov `number` in `email` priporočamo uporabo tipov [addInteger |#addInteger] in [addEmail |#addEmail], ki zagotavljata preverjanje na strani strežnika.
+Vizualni značaj besedilnega polja lahko spremenite v vrste, kot so `search`, `tel` ali `url` z uporabo `setHtmlType()`, kot je prikazano v [specifikaciji |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Ne pozabite, da je spreminjanje tipa le vizualno in ne opravlja funkcij potrjevanja. Za vrsto `url` je primerno dodati posebno [pravilo URL |validation#Text inputs].
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+Za druge vhodne tipe, kot so `number`, `range`, `email`, `date`, `datetime-local`, `time` in `color`, uporabite specializirane metode, kot so [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] in [addColor |#addColor], ki zagotavljajo preverjanje na strani strežnika. Tipa `month` in `week` še nista v celoti podprta v vseh brskalnikih.
 
 Za element lahko nastavite tako imenovano prazno vrednost, ki je nekaj podobnega kot privzeta vrednost, vendar če je uporabnik ne prepiše, vrne prazen niz ali `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Doda vnosno polje za celo število (razred [TextInput |api:Nette\Forms\Controls\TextInput]). Vrne celo število ali `null`, če uporabnik ne vnese ničesar.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('leto', 'Leto:')
+	->addRule($form::Range, 'Leto mora biti v razponu od %d do %d.', [1900, 2023 |1900, 2023]);
+```
+
+Element se prikaže kot `<input type="numeric">`. Z uporabo metode `setHtmlType()` lahko tip spremenite v `range` za prikaz kot drsnik ali v `text`, če želite standardno besedilno polje brez posebnega obnašanja `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Stopnja:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'Raven mora biti v razponu od %d do %d.', [0, 100 |0, 100]);
 ```
 
+Element se prikaže kot `<input type="numeric">`. Z uporabo metode `setHtmlType()` lahko tip spremenite v `range` za prikaz kot drsnik ali v `text`, če želite standardno besedilno polje brez posebnega obnašanja `numeric`.
+
+Nette in brskalnik Chrome kot decimalno ločilo sprejemata tako vejico kot piko. Če želite, da je ta funkcionalnost na voljo v brskalniku Firefox, je priporočljivo nastaviti atribut `lang` bodisi za določen element bodisi za celotno stran, npr, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Doda polje e-poštnega naslova s preverjanjem veljavnosti (razred [TextInput |api:Nette\Forms\Controls\TextInput]). Če uporabnik ne izpolni polja, vrne prazen niz `''`, ali pa ga z uporabo `setNullable()` spremeni tako, da vrne `null`.
 
@@ -78,8 +92,8 @@ Preveri, ali je vrednost veljavni e-poštni naslov. Ne preveri, ali domena dejan
 Največjo dolžino lahko omejite z uporabo `setMaxLength()`. S funkcijo [addFilter() |validation#Modifying Input Values] lahko spremenite uporabniško vneseno vrednost. Tako imenovano prazno vrednost lahko nastavite z uporabo `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Doda polje za geslo (razred [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Doda seznam potrditvenih polj za izbiro več elementov (razred [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Vrne polje ključev izbranih elementov. Metoda `getSelectedItems()` namesto ključev vrne vrednosti.
 
@@ -125,9 +139,15 @@ Element samodejno preveri, da ni prišlo do ponarejanja in da so izbrani element
 
 Če so nastavljene privzete vrednosti, se prav tako preveri, ali gre za enega od ponujenih elementov, sicer se vrže izjema. To preverjanje je mogoče izklopiti z metodo `checkDefaultValue(false)`.
 
+Če obrazec pošiljate z metodo `GET`, lahko izberete bolj kompakten način prenosa podatkov, ki prihrani pri velikosti niza poizvedb. To aktivirate z nastavitvijo atributa HTML obrazca:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Doda radijske gumbe (razred [RadioList |api:Nette\Forms\Controls\RadioList]). Vrne ključ izbranega elementa ali `null`, če uporabnik ni izbral ničesar. Metoda `getSelectedItem()` namesto ključa vrne vrednost.
 
@@ -148,8 +168,8 @@ Element samodejno preveri, ali ni prišlo do ponarejanja in ali je izbrani eleme
 Če je nastavljena privzeta vrednost, preveri tudi, ali gre za enega od ponujenih elementov, sicer vrže izjemo. To preverjanje je mogoče izklopiti z metodo `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Doda izbirno polje (razred [SelectBox |api:Nette\Forms\Controls\SelectBox]). Vrne ključ izbranega elementa ali `null`, če uporabnik ni izbral ničesar. Metoda `getSelectedItem()` namesto ključa vrne vrednost.
 
@@ -193,8 +213,8 @@ Element samodejno preveri, ali ni prišlo do ponarejanja in ali je izbrani eleme
 Če je nastavljena privzeta vrednost, preveri tudi, ali gre za enega od ponujenih elementov, sicer vrže izjemo. To preverjanje je mogoče izklopiti z metodo `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Doda izbirno polje za več možnosti (razred [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Vrne polje ključev izbranih elementov. Metoda `getSelectedItems()` namesto ključev vrne vrednosti.
 
@@ -246,8 +266,81 @@ Ne zaupajte izvirnim imenom datotek, ki jih vrne metoda `FileUpload::getName()`,
 Pravili `MimeType` in `Image` zahtevano vrsto datoteke ali slike odkrijeta na podlagi njenega podpisa. Celovitost celotne datoteke se ne preverja. Ali slika ni poškodovana, lahko ugotovite na primer tako, da [jo |http:request#toImage] poskusite [naložiti |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Doda polje, ki uporabniku omogoča enostaven vnos datuma, sestavljenega iz leta, meseca in dneva (razred [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Za privzeto vrednost sprejema predmete, ki implementirajo `DateTimeInterface`, niz s časom ali število, ki predstavlja časovni žig UNIX. Enako velja za argumente pravila `Min`, `Max` ali `Range`, ki določajo najmanjši in največji dovoljeni datum.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Privzeto vrne predmet `DateTimeImmutable`. Z metodo `setFormat()` lahko določite [besedilno obliko |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ali časovni žig:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Doda polje, ki uporabniku omogoča enostaven vnos časa, sestavljenega iz ur, minut in po želji sekund (razred [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Za privzeto vrednost sprejema predmete, ki implementirajo `DateTimeInterface`, niz s časom ali število, ki predstavlja časovni žig UNIX. Uporabijo se samo podatki o času iz teh vnosov; datum se ne upošteva. Enako velja za argumente pravil `Min`, `Max` ali `Range`, ki določajo najmanjši in največji dovoljeni čas. Če je najmanjša nastavljena vrednost višja od največje, se ustvari časovno območje, ki zajema polnoč.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Privzeto vrne objekt `DateTimeImmutable` (z datumom 1. januar, leto 1). Z metodo `setFormat()` lahko določite [obliko besedila |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Doda polje, ki uporabniku omogoča enostaven vnos datuma in časa, sestavljenega iz leta, meseca, dneva, ur, minut in po želji sekund (razred [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+Za privzeto vrednost sprejema predmete, ki implementirajo `DateTimeInterface`, niz s časom ali število, ki predstavlja časovni žig UNIX. Enako velja za argumente pravila `Min`, `Max` ali `Range`, ki določajo najmanjši in največji dovoljeni datum.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Privzeto vrne predmet `DateTimeImmutable`. Z metodo `setFormat()` lahko določite [besedilno obliko |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ali časovni žig:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Doda polje za izbiro barve (razred [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Barva je niz v obliki `#rrggbb`. Če uporabnik ne opravi izbire, je privzeta vrnjena barva črna `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Doda skrito polje (razred [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Uporabite `setNullable()`, da ga spremenite tako, da vrne `null` namesto praznega niza. S funkcijo [addFilter() |validation#Modifying Input Values] lahko spremenite oddano vrednost.
 
+Čeprav je element skrit, se je **pomembno zavedati**, da lahko napadalec še vedno spremeni ali ponaredi njegovo vrednost. Vedno temeljito preverite in potrdite vse prejete vrednosti na strani strežnika, da preprečite varnostna tveganja, povezana z manipulacijo podatkov.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Doda gumb za oddajo v obliki slike (razred [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ Za elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInt
 
 
 Izpuščene vrednosti .[#toc-omitted-values]
-------------------------------------------
+==========================================
 
 Če vas vrednost, ki jo je vnesel uporabnik, ne zanima, jo lahko z uporabo `setOmitted()` izpustimo iz rezultata, ki ga zagotovi metoda `$form->getValues​()` ali posreduje obdelovalcem. To je primerno za različna gesla za preverjanje, antispam polja itd.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Onemogočanje vnosov .[#toc-disabling-inputs]
---------------------------------------------
+============================================
 
-Če želite onemogočiti vhod, lahko pokličete `setDisabled()`. Takšnega polja uporabnik ne more urejati.
+Vhode lahko onemogočite z uporabo spletne strani `setDisabled()`. Onemogočenega vnosa uporabnik ne more urejati.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Upoštevajte, da brskalnik onemogočenih polj sploh ne pošlje strežniku, zato jih ne boste našli niti v podatkih, ki jih vrne funkcija `$form->getValues()`.
+Brskalnik onemogočenih vnosov ne pošlje strežniku, zato jih ne boste našli v podatkih, ki jih vrne funkcija `$form->getValues()`. Če pa nastavite `setOmitted(false)`, bo Nette v te podatke vključil njihovo privzeto vrednost.
 
-Če polju določate privzeto vrednost, morate to storiti šele potem, ko ste ga onemogočili:
+Ko se pokliče `setDisabled()`, se **vrednost vnosa zaradi varnostnih razlogov izbriše**. Če nastavljate privzeto vrednost, je treba to storiti po njenem izklopu:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Alternativa onemogočenim vnosom so polja z atributom HTML `readonly`, ki jih brskalnik pošlje strežniku. Čeprav je polje samo berljivo, se je **pomembno zavedati**, da lahko napadalec še vedno spremeni ali ponaredi njegovo vrednost.
+
 
 Prilagojeni gumbi .[#toc-custom-controls]
 =========================================
@@ -428,8 +525,8 @@ Za dodajanje elementov po meri (npr. `$form->addZip()`) lahko določite nove met
 ```php
 use Nette\Forms\Container;
 
-// doda metodo addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// doda metodo addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/sl/in-presenter.texy b/forms/sl/in-presenter.texy
index bf919a5eb2..319929672a 100644
--- a/forms/sl/in-presenter.texy
+++ b/forms/sl/in-presenter.texy
@@ -30,7 +30,7 @@ Obrazec v predstavitvi je objekt razreda `Nette\Application\UI\Form`, njegov pre
 
 Z vidika predstavnika je obrazec skupna komponenta. Zato ga obravnavamo kot komponento in ga vključimo v predstavitveni program z uporabo [tovarniške metode |application:components#Factory Methods]. To bo videti takole:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Prikaz v predlogi pa se izvede z uporabo oznake `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Obrazec se vedno potrdi na strani strežnika, vendar se ustvari tudi potrditev J
 Vstavite jo v predlogo postavitve:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Če pogledate izvorno kodo strani z obrazcem, lahko opazite, da Nette vstavi zahtevana polja v elemente z razredom CSS `required`. Poskusite v predlogo dodati naslednji slog in oznaka "Ime" bo rdeča. Na eleganten način označimo zahtevana polja za uporabnike:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Od različice PHP 8.0 lahko uporabite eleganten zapis, ki uporablja konstruktor:
+Uporabite lahko tudi konstruktor:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Lastnosti podatkovnega razreda so lahko tudi enumi in bodo samodejno preslikani. .{data-version:3.2.4}
+
 Kako reči Nette, naj vrne podatke kot predmete tega razreda? Lažje, kot si mislite. Vse, kar morate storiti, je določiti razred kot tip parametra `$data` v izvajalcu:
 
 ```php
@@ -294,6 +296,8 @@ Prikazovanje nato na podlagi vrste lastnosti `$person` ugotovi, da mora vsebnik
 $person->setMappedType(PersonFormData::class);
 ```
 
+Predlog podatkovnega razreda obrazca lahko ustvarite z metodo `Nette\Forms\Blueprint::dataClass($form)`, ki ga izpiše na strani brskalnika. Nato lahko preprosto kliknete, da izberete in kopirate kodo v svoj projekt. .{data-version:3.1.15}
+
 
 Več gumbov za pošiljanje .[#toc-multiple-submit-buttons]
 ========================================================
diff --git a/forms/sl/rendering.texy b/forms/sl/rendering.texy
index 680af79ddd..e4a923dfc5 100644
--- a/forms/sl/rendering.texy
+++ b/forms/sl/rendering.texy
@@ -11,6 +11,8 @@ Renderiranje z Latte .[#toc-rendering-with-latte]
 
  [Sistem predlog Latte |latte:] bistveno olajša upodabljanje obrazcev in njihovih elementov. Najprej bomo pokazali, kako ročno upodabljati obrazce, element za elementom, da bi pridobili popoln nadzor nad kodo. Kasneje bomo pokazali, kako takšno upodabljanje [avtomatizirati |#Automatic rendering].
 
+Predlog Latte predloge za obrazec lahko generirate z metodo `Nette\Forms\Blueprint::latte($form)`, ki ga bo izpisala na stran brskalnika. Nato morate kodo preprosto izbrati s klikom in jo kopirati v svoj projekt. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ Kompleksnejše elemente obrazca, kot sta RadioList ali CheckboxList, lahko prika
 ```
 
 
-Predlog kode `{formPrint}` .[#toc-formprint]
---------------------------------------------
-
-Podobno kodo Latte lahko ustvarite za obrazec z uporabo oznake `{formPrint}`. Če jo vstavite v predlogo, se bo namesto običajnega izrisa prikazal predlog kode. Nato jo preprosto izberite in kopirajte v svoj projekt.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Blok morate uvoziti le na enem mestu, na začetku predloge za postavitev:
 Posebni primeri .[#toc-special-cases]
 -------------------------------------
 
-Če morate prikazati samo notranjo vsebino obrazca brez `<form>` & `</form>` HTML, na primer v zahtevi AJAX, lahko obrazec odprete in zaprete s `{formContext} … {/formContext}`. V logičnem smislu deluje podobno kot `{form}`, tu vam omogoča uporabo drugih oznak za izris elementov obrazca, vendar hkrati ne izrisuje ničesar.
+Če želite prikazati samo notranji del obrazca brez oznak HTML `<form>`na primer pri pošiljanju izsekov, jih skrijte s pomočjo atributa `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Oznaka `formContainer` pomaga pri izrisovanju vnosov znotraj vsebnika obrazca.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Renderer najprej izriše skupine, nato pa elemente, ki ne pripadajo nobeni skupini.
+
 
 Podpora Bootstrap .[#toc-bootstrap-support]
 -------------------------------------------
@@ -444,7 +442,7 @@ Najdete lahko [primere |https://github.com/nette/forms/tree/master/examples] kon
 Atributi HTML .[#toc-html-attributes]
 =====================================
 
-Z uporabo spletne strani `setHtmlAttribute(string $name, $value = true)` lahko kontrolnim elementom obrazca nastavite poljubne atribute HTML:
+Če želite nastaviti poljubne atribute HTML za elemente obrazca, uporabite metodo `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // ob spremembi pokliče funkcijo JS submit().
 
 
-// uporaba na <form>
+// Za nastavitev atributov samega <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Nastavitev vrste vnosa:
+Določanje vrste elementa:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-V seznamih z radijskimi ali potrditvenimi polji lahko posameznim elementom nastavimo atribut HTML z različnimi vrednostmi za vsakega od njih.
-Upoštevajte dvopičje za `style:`, ki zagotavlja, da je vrednost izbrana po ključu:
+.[warning]
+Nastavitev vrste in drugih atributov služi le za vizualne namene. Pravilnost vnosa je treba preveriti v strežniku, kar lahko zagotovite z izbiro ustreznega [nadzora obrazca | controls] in določitvijo [pravil potrjevanja | validation].
+
+Za posamezne elemente v radijskih ali potrditvenih seznamih lahko nastavimo atribut HTML z različnimi vrednostmi za vsakega od njih.
+Opazite dvopičje za `style:`, ki zagotavlja, da je vrednost izbrana na podlagi ključa:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Renders:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Za logični atribut HTML (ki nima vrednosti, na primer `readonly`), lahko uporabite vprašalnik:
+Za nastavljanje logičnih atributov, kot je `readonly`, lahko uporabimo zapis z vprašalnikom:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // uporabite polje za več ključev, npr. ['r', 'g']
 ```
@@ -541,9 +541,6 @@ Za elemente Checkbox, CheckboxList in RadioList lahko vplivate na predlogo eleme
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/sl/standalone.texy b/forms/sl/standalone.texy
index a68ac0a15e..6d4913afe4 100644
--- a/forms/sl/standalone.texy
+++ b/forms/sl/standalone.texy
@@ -107,7 +107,7 @@ Obrazec se vedno potrdi na strani strežnika, vendar se ustvari tudi potrditev J
 Dodajte jo na stran:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Če pogledate izvorno kodo strani z obrazcem, lahko opazite, da Nette vstavi zahtevana polja v elemente z razredom CSS `required`. Poskusite v predlogo dodati naslednji slog in oznaka "Ime" bo rdeča. Na eleganten način označimo zahtevana polja za uporabnike:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Od različice PHP 8.0 lahko uporabite eleganten zapis, ki uporablja konstruktor:
+Uporabite lahko tudi konstruktor:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Lastnosti podatkovnega razreda so lahko tudi enumi in bodo samodejno preslikani. .{data-version:3.2.4}
+
 Kako reči Nettu, naj nam podatke vrne kot predmete tega razreda? Lažje, kot si mislite. Vse, kar morate storiti, je, da kot parameter navedete ime razreda ali objekta, ki ga želite hidrirati:
 
 ```php
@@ -258,6 +260,8 @@ Prikazovanje nato na podlagi vrste lastnosti `$person` ugotovi, da mora vsebnik
 $person->setMappedType(PersonFormData::class);
 ```
 
+Predlog podatkovnega razreda obrazca lahko ustvarite z metodo `Nette\Forms\Blueprint::dataClass($form)`, ki ga izpiše na strani brskalnika. Nato lahko preprosto kliknete, da izberete in kopirate kodo v svoj projekt. .{data-version:3.1.15}
+
 
 Več gumbov za pošiljanje .[#toc-multiple-submit-buttons]
 ========================================================
diff --git a/forms/sl/validation.texy b/forms/sl/validation.texy
index a1f35438fb..96ff85860a 100644
--- a/forms/sl/validation.texy
+++ b/forms/sl/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette ima na voljo številna vgrajena pravila, katerih imena so konstante razreda `Nette\Forms\Form`:
+**Pravila potrjevanja se preverijo le, če je uporabnik izpolnil element.**
 
-Naslednja pravila lahko uporabimo za vse kontrole:
+Nette ima na voljo številna vnaprej določena pravila, katerih imena so konstante razreda `Nette\Forms\Form`. Ta pravila lahko uporabimo za vse elemente:
 
 | konstanta | opis | argumenti
 |-------
@@ -38,7 +38,11 @@ Naslednja pravila lahko uporabimo za vse kontrole:
 | `IsNotIn` | vrednost ni enaka nobenemu elementu v polju | `array`
 | `Valid` | vhodni podatki so uspešno preverjeni (za [pogoje |#conditions]) | -
 
-Za kontrole `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` se lahko uporabijo tudi naslednja pravila:
+
+Besedilni vnosi .[#toc-text-inputs]
+-----------------------------------
+
+Za elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` se lahko uporabijo tudi nekatera od naslednjih pravil:
 
 | `MinLength` | minimalna dolžina niza | `int`
 | `MaxLength` | največja dolžina niza | `int`
@@ -57,9 +61,23 @@ Za kontrole `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInt
 Pravila `Integer`, `Numeric` in `Float` samodejno pretvorijo vrednost v celo število (oziroma plavajoče število). Poleg tega pravilo `URL` sprejme tudi naslov brez sheme (npr. `nette.org`) in dopolni shemo (`https://nette.org`).
 Izraza v `Pattern` in `PatternInsensitive` morata biti veljavna za celotno vrednost, tj. kot da bi bila zavita v znake `^` and `$`.
 
+
+Število elementov .[#toc-number-of-items]
+-----------------------------------------
+
+Za elemente `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lahko za omejitev števila izbranih elementov ali naloženih datotek uporabite tudi naslednja pravila:
+
+| `MinLength` | najmanjše število | `int`
+| `MaxLength` | največje število | `int`
+| `Length` | število v razponu ali natančno število | pari `[int, int]` ali `int`
+
+
+Prenos datotek
+--------------
+
 Za kontrole `addUpload()`, `addMultiUpload()` se lahko uporabljajo tudi naslednja pravila:
 
-| `MaxFileSize` | največja velikost datoteke | `int`
+| `MaxFileSize` | največja velikost datoteke v bajtih | `int`
 | `MimeType` | vrsta MIME, sprejema nadomestne znake (`'video/*'`) | `string\|string[]`
 | `Image` | naložena datoteka je JPEG, PNG, GIF, WebP | -
 | `Pattern` | ime datoteke ustreza regularnemu izrazu | `string`
@@ -67,15 +85,9 @@ Za kontrole `addUpload()`, `addMultiUpload()` se lahko uporabljajo tudi naslednj
 
 Za `MimeType` in `Image` je potrebna razširitev PHP `fileinfo`. Ali je datoteka ali slika zahtevane vrste, se ugotovi na podlagi njenega podpisa. Celovitost celotne datoteke se ne preverja. Ali slika ni poškodovana, lahko ugotovite na primer tako, da [jo |http:request#toImage] poskusite [naložiti |http:request#toImage].
 
-Za kontrolnike `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lahko za omejitev števila izbranih elementov oziroma naloženih datotek uporabite tudi naslednja pravila:
-
-| `MinLength` | minimalno število | `int`
-| `MaxLength` | maksimalno število | `int`
-| `Length` | število v razponu ali natančno število | par `[int, int]` ali `int`
-
 
 Sporočila o napakah .[#toc-error-messages]
-------------------------------------------
+==========================================
 
 Vsa vnaprej določena pravila, razen `Pattern` in `PatternInsensitive`, imajo privzeto sporočilo o napaki, zato jih lahko izpustite. Vendar pa boste s posredovanjem in oblikovanjem vseh prilagojenih sporočil naredili obrazec prijaznejši do uporabnika.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 V Nette je zelo enostavno reagirati na izpolnitev ali neizpolnitev pogoja na strani JavaScript z uporabo metode `toggle()`, glejte [Dinamični JavaScript |#Dynamic JavaScript].
 
 
-Sklicevanja med kontrolniki .[#toc-references-between-controls]
-===============================================================
+Sklicevanje na drug element .[#toc-reference-to-another-element]
+================================================================
 
-Argument pravila ali pogoja je lahko sklic na drug element. Na primer, dinamično lahko preverite, da ima `text` toliko znakov, kolikor je vrednost polja `length`:
+Kot argument za pravilo ali pogoj lahko posredujete tudi drug element obrazca. Pravilo bo nato uporabilo vrednost, ki jo bo uporabnik kasneje vnesel v brskalnik. To lahko na primer uporabite za dinamično preverjanje, ali element `password` vsebuje isti niz kot element `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Ta skripta je `netteForms.js`, ki je na voljo iz več možnih virov:
 Skripto lahko vstavite neposredno v stran HTML iz CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Lahko pa jo kopirate lokalno v javno mapo projekta (npr. s spletne strani `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/forms/tr/controls.texy b/forms/tr/controls.texy
index fe5264d994..f430b95d5c 100644
--- a/forms/tr/controls.texy
+++ b/forms/tr/controls.texy
@@ -5,8 +5,8 @@ Form Kontrolleri
 Yerleşik form kontrollerine genel bakış.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Tek satırlık metin alanı ekler ( [TextInput |api:Nette\Forms\Controls\TextInput] sınıfı). Kullanıcı alanı doldurmazsa, boş bir dize döndürür `''` veya `null` döndürmek üzere değiştirmek için `setNullable()` kullanın.
 
@@ -20,13 +20,10 @@ UTF-8'i otomatik olarak doğrular, sol ve sağ boşlukları keser ve bir saldır
 
 Maksimum uzunluk `setMaxLength()` kullanılarak sınırlandırılabilir. [addFilter() |validation#Modifying Input Values] kullanıcı tarafından girilen değeri değiştirmenize olanak tanır.
 
-Giriş öğesinin [karakterini |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color` olarak değiştirmek için `setHtmlType()` kullanın. `number` ve `email` türleri yerine, sunucu tarafı doğrulama sağlayan [addInteger |#addInteger] ve [addEmail'i |#addEmail] kullanmanızı öneririz.
+Bir metin alanının görsel karakterini, [spesifikasyonda |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] görüldüğü gibi `setHtmlType()` kullanarak `search`, `tel` veya `url` gibi türlere değiştirebilirsiniz. Türü değiştirmenin yalnızca görsel olduğunu ve doğrulama işlevlerini yerine getirmediğini unutmayın. `url` türü için belirli bir [URL kuralı |validation#Text inputs] eklemek uygundur.
 
-```php
-$form->addText('color', 'Choose color:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}');
-```
+.[note]
+ `number`, `range`, `email`, `date`, `datetime-local`, `time` ve `color` gibi diğer girdi türleri için sunucu tarafı doğrulama sağlayan [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] ve [addColor |#addColor] gibi özel yöntemleri kullanın. `month` ve `week` türleri henüz tüm tarayıcılarda tam olarak desteklenmemektedir.
 
 Varsayılan değer gibi bir şey olan boş değer öğe için ayarlanabilir, ancak kullanıcı bunun üzerine yazmazsa boş dize veya `null` döndürür.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Tamsayı için giriş alanı ekler ( [TextInput |api:Nette\Forms\Controls\TextInput] sınıfı). Kullanıcı hiçbir şey girmezse bir tamsayı veya `null` döndürür.
 
 ```php
-$form->addInteger('level', 'Level:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'Yıl %d ile %d aralığında olmalıdır.', [1900, 2023 |1900, 2023]);
+```
+
+Öğe şu şekilde oluşturulur `<input type="numeric">`. `setHtmlType()` yöntemini kullanarak, kaydırıcı olarak görüntülemek için türü `range` olarak veya `numeric` özel davranışı olmadan standart bir metin alanı tercih ediyorsanız `text` olarak değiştirebilirsiniz.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]);
+->addRule($form::Range, 'The level must be in the range %d to %d.', [0, 100 |0, 100]);
 ```
 
+Öğe şu şekilde oluşturulur `<input type="numeric">`. `setHtmlType()` yöntemini kullanarak, kaydırıcı olarak görüntülemek için türü `range` olarak veya `numeric` özel davranışı olmadan standart bir metin alanı tercih ediyorsanız `text` olarak değiştirebilirsiniz.
+
+Nette ve Chrome tarayıcısı ondalık ayırıcı olarak hem virgül hem de nokta kabul eder. Bu işlevi Firefox'ta kullanılabilir hale getirmek için, örneğin belirli bir öğe veya tüm sayfa için `lang` özniteliğinin ayarlanması önerilir, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Geçerlilik kontrolü ile e-posta adresi alanı ekler (class [TextInput |api:Nette\Forms\Controls\TextInput]). Kullanıcı alanı doldurmazsa, boş bir dize döndürür `''` veya `null` döndürmek üzere değiştirmek için `setNullable()` kullanın.
 
@@ -78,8 +92,8 @@ Değerin geçerli bir e-posta adresi olduğunu doğrular. Etki alanının gerçe
 Maksimum uzunluk `setMaxLength()` kullanılarak sınırlandırılabilir. [addFilter() |validation#Modifying Input Values] kullanıcı tarafından girilen değeri değiştirmenize olanak tanır. Boş değer olarak adlandırılan değeri `setEmptyValue()` adresini kullanarak ayarlayabilirsiniz.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Parola alanı ekler ( [TextInput |api:Nette\Forms\Controls\TextInput] sınıfı).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'I agree with terms')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Birden fazla öğe seçmek için onay kutuları listesi ekler (sınıf [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Seçilen öğelerin anahtar dizisini döndürür. `getSelectedItems()` yöntemi anahtarlar yerine değerler döndürür.
 
@@ -125,9 +139,15 @@ Kullanabilirsiniz `setDisabled(['r', 'g'])` tek tek öğeleri devre dışı bır
 
 Varsayılan değerler ayarlandığında, bunların sunulan öğelerden biri olup olmadığını da kontrol eder, aksi takdirde bir istisna atar. Bu kontrol `checkDefaultValue(false)` ile kapatılabilir.
 
+Bir formu `GET` yöntemini kullanarak gönderiyorsanız, sorgu dizesinin boyutundan tasarruf sağlayan daha kompakt bir veri aktarım yöntemi seçebilirsiniz. Bu, formun HTML özniteliğinin ayarlanmasıyla etkinleştirilir:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 [Radyo |api:Nette\Forms\Controls\RadioList] düğmeleri ekler ( [RadioList |api:Nette\Forms\Controls\RadioList] sınıfı). Seçilen öğenin anahtarını veya kullanıcı herhangi bir şey seçmediyse `null` adresini döndürür. `getSelectedItem()` yöntemi, anahtar yerine bir değer döndürür.
 
@@ -148,8 +168,8 @@ Kullanabilirsiniz `setDisabled(['m'])` tek tek öğeleri devre dışı bırakmak
 Varsayılan değer ayarlandığında, bunun sunulan öğelerden biri olup olmadığını da kontrol eder, aksi takdirde bir istisna atar. Bu kontrol `checkDefaultValue(false)` ile kapatılabilir.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Seçme kutusu ekler ( [SelectBox |api:Nette\Forms\Controls\SelectBox] sınıfı). Seçilen öğenin anahtarını veya kullanıcı herhangi bir şey seçmediyse `null` adresini döndürür. `getSelectedItem()` yöntemi, anahtar yerine bir değer döndürür.
 
@@ -193,8 +213,8 @@ Kullanabilirsiniz `setDisabled(['CZ', 'SK'])` tek tek öğeleri devre dışı b
 Varsayılan değer ayarlandığında, bunun sunulan öğelerden biri olup olmadığını da kontrol eder, aksi takdirde bir istisna atar. Bu kontrol `checkDefaultValue(false)` ile kapatılabilir.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Çok seçenekli seçim kutusu ekler ( [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox] sınıfı). Seçilen öğelerin anahtar dizisini döndürür. `getSelectedItems()` yöntemi anahtarlar yerine değerler döndürür.
 
@@ -246,8 +266,81 @@ Dosyalardan biri doğru şekilde yüklenemezse, form başarıyla gönderilmemiş
 Kurallar `MimeType` ve `Image` gerekli dosya veya görüntü türünü imzasına göre tespit eder. Tüm dosyanın bütünlüğü kontrol edilmez. Bir görüntünün bozuk olup olmadığını örneğin [yüklemeye |http:request#toImage] çalışarak öğrenebilirsiniz.
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Kullanıcının yıl, ay ve günden oluşan bir tarihi kolayca girmesini sağlayan bir alan ekler ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] sınıfı).
+
+Varsayılan değer için, `DateTimeInterface` adresini uygulayan nesneleri, zaman içeren bir dizeyi veya UNIX zaman damgasını temsil eden bir sayıyı kabul eder. Aynı durum, izin verilen minimum ve maksimum tarihi tanımlayan `Min`, `Max` veya `Range` kural bağımsız değişkenleri için de geçerlidir.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür. `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] veya zaman damgası belirtebilirsiniz:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Kullanıcının saat, dakika ve isteğe bağlı olarak saniyelerden oluşan zamanı kolayca girmesini sağlayan bir alan ekler ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] sınıfı).
+
+Varsayılan değer için, `DateTimeInterface` adresini uygulayan nesneleri, zaman içeren bir dizeyi veya UNIX zaman damgasını temsil eden bir sayıyı kabul eder. Bu girdilerden yalnızca zaman bilgisi kullanılır; tarih göz ardı edilir. Aynı durum, izin verilen minimum ve maksimum zamanı tanımlayan `Min`, `Max` veya `Range` kural bağımsız değişkenleri için de geçerlidir. Ayarlanan minimum değer maksimum değerden yüksekse, gece yarısını kapsayan bir zaman aralığı oluşturulur.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür (tarih 1 Ocak, yıl 1). `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] belirtebilirsiniz:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Kullanıcının yıl, ay, gün, saat, dakika ve isteğe bağlı olarak saniyeden oluşan tarih ve saati kolayca girmesini sağlayan bir alan ekler ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] sınıfı).
+
+Varsayılan değer için, `DateTimeInterface` adresini uygulayan nesneleri, zaman içeren bir dizeyi veya UNIX zaman damgasını temsil eden bir sayıyı kabul eder. Aynı durum, izin verilen minimum ve maksimum tarihi tanımlayan `Min`, `Max` veya `Range` kural bağımsız değişkenleri için de geçerlidir.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür. `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] veya zaman damgası belirtebilirsiniz:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Bir renk seçim alanı ekler ( [ColorPicker |api:Nette\Forms\Controls\ColorPicker] sınıfı). Renk, `#rrggbb` biçiminde bir dizedir. Kullanıcı bir seçim yapmazsa, döndürülen varsayılan renk siyahtır `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Gizli alan ekler ( [HiddenField |api:Nette\Forms\Controls\HiddenField] sınıfı).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Boş bir dize yerine `null` döndürmek üzere değiştirmek için `setNullable()` adresini kullanın. [addFilter() |validation#Modifying Input Values], gönderilen değeri değiştirmenize olanak tanır.
 
+Öğe gizli olsa da, değerinin bir saldırgan tarafından değiştirilebileceğini veya yanıltılabileceğini **fark etmek önemlidir**. Veri manipülasyonuyla ilişkili güvenlik risklerini önlemek için sunucu tarafında alınan tüm değerleri her zaman kapsamlı bir şekilde doğrulayın ve onaylayın.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Raise salary')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Resim biçiminde gönder düğmesi ekler ( [ImageButton |api:Nette\Forms\Controls\ImageButton] sınıfı).
 
@@ -377,7 +472,7 @@ Aşağıdaki yöntemler `addText()`, `addPassword()`, `addTextArea()`, `addEmail
 
 
 Atlanan Değerler .[#toc-omitted-values]
----------------------------------------
+=======================================
 
 Kullanıcı tarafından girilen değerle ilgilenmiyorsanız, `$form->getValues​()` yöntemi tarafından sağlanan veya işleyicilere aktarılan sonuçtan çıkarmak için `setOmitted()` adresini kullanabiliriz. Bu, doğrulama için çeşitli parolalar, antispam alanları vb. için uygundur.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Password again:')
 
 
 Girişleri Devre Dışı Bırakma .[#toc-disabling-inputs]
------------------------------------------------------
+=====================================================
 
-Bir girişi devre dışı bırakmak için `setDisabled()` adresini çağırabilirsiniz. Böyle bir alan kullanıcı tarafından düzenlenemez.
+Girişler `setDisabled()` kullanılarak devre dışı bırakılabilir. Devre dışı bırakılan bir girdi kullanıcı tarafından düzenlenemez.
 
 ```php
 $form->addText('username', 'User name:')
 	->setDisabled();
 ```
 
-Tarayıcının devre dışı bırakılan alanları sunucuya göndermediğini unutmayın, bu nedenle bunları `$form->getValues()` işlevi tarafından döndürülen verilerde bile bulamazsınız.
+Devre dışı bırakılan girişler tarayıcı tarafından sunucuya gönderilmez, bu nedenle `$form->getValues()` işlevi tarafından döndürülen verilerde bunları bulamazsınız. Ancak, `setOmitted(false)` adresini ayarlarsanız, Nette varsayılan değerlerini bu verilere dahil edecektir.
 
-Bir alan için varsayılan bir değer ayarlıyorsanız, bunu yalnızca devre dışı bıraktıktan sonra yapmalısınız:
+ `setDisabled()` çağrıldığında, güvenlik nedeniyle **girişin değeri silinir**. Varsayılan bir değer ayarlıyorsanız, bunu devre dışı bırakıldıktan sonra yapmanız gerekir:
 
 ```php
 $form->addText('username', 'User name:')
@@ -409,6 +504,8 @@ $form->addText('username', 'User name:')
 	->setDefaultValue($userName);
 ```
 
+Devre dışı bırakılmış girdilere alternatif olarak, tarayıcı tarafından sunucuya gönderilen HTML `readonly` özniteliğine sahip alanlar kullanılabilir. Alan yalnızca okunabilir olsa da, değerinin bir saldırgan tarafından değiştirilebileceğini veya yanıltılabileceğini **fark etmek önemlidir**.
+
 
 Özel Kontroller .[#toc-custom-controls]
 =======================================
@@ -428,8 +525,8 @@ Form, [Container | component-model:#Container] sınıfının bir torunudur ve el
 ```php
 use Nette\Forms\Container;
 
-// addZip(string $name, string $label = null) yöntemini ekler
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// addZip(string $name, ?string $label = null) yöntemini ekler
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
 });
diff --git a/forms/tr/in-presenter.texy b/forms/tr/in-presenter.texy
index cef4cc8ee8..4fe237cb6f 100644
--- a/forms/tr/in-presenter.texy
+++ b/forms/tr/in-presenter.texy
@@ -30,7 +30,7 @@ Sunucudaki form `Nette\Application\UI\Form` sınıfının bir nesnesidir, selefi
 
 Sunucunun bakış açısından, form ortak bir bileşendir. Bu nedenle, bir bileşen olarak ele alınır ve [fabrika yöntemi |application:components#Factory Methods] kullanılarak sunucuya dahil edilir. Bu şekilde görünecektir:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 Ve şablonda render işlemi `{control}` etiketi kullanılarak yapılır:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Registration</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ Form her zaman sunucu tarafında doğrulanır, ancak JavaScript doğrulaması da
 Bunu düzen şablonuna ekleyin:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Formun bulunduğu sayfanın kaynak koduna bakarsanız, Nette'in gerekli alanları `required` CSS sınıfına sahip öğelere eklediğini fark edebilirsiniz. Aşağıdaki stili şablona eklemeyi deneyin, "Ad" etiketi kırmızı olacaktır. Kullanıcılar için gerekli alanları zarif bir şekilde işaretliyoruz:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-PHP 8.0'dan itibaren, bir kurucu kullanan bu zarif gösterimi kullanabilirsiniz:
+Alternatif olarak, kurucuyu kullanabilirsiniz:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Veri sınıfının özellikleri de enum olabilir ve otomatik olarak eşleştirilirler. .{data-version:3.2.4}
+
 Nette'e verileri bu sınıfın nesneleri olarak döndürmesini nasıl söyleyebilirim? Düşündüğünüzden daha kolay. Tek yapmanız gereken, işleyicideki `$data` parametresinin türü olarak sınıfı belirtmektir:
 
 ```php
@@ -294,6 +296,8 @@ Eşleme daha sonra `$person` özellik türünden konteyneri `PersonFormData` sı
 $person->setMappedType(PersonFormData::class);
 ```
 
+Tarayıcı sayfasına yazdıracak olan `Nette\Forms\Blueprint::dataClass($form)` yöntemini kullanarak bir formun veri sınıfı için bir öneri oluşturabilirsiniz. Daha sonra kodu seçmek ve projenize kopyalamak için tıklamanız yeterlidir. .{data-version:3.1.15}
+
 
 Çoklu Gönder Düğmeleri .[#toc-multiple-submit-buttons]
 ======================================================
diff --git a/forms/tr/rendering.texy b/forms/tr/rendering.texy
index 2835653df8..2c70c5e5b4 100644
--- a/forms/tr/rendering.texy
+++ b/forms/tr/rendering.texy
@@ -11,6 +11,8 @@ Latte ile Rendering .[#toc-rendering-with-latte]
 
 [Latte şablonlama sistemi |latte:], formların ve öğelerinin oluşturulmasını temel olarak kolaylaştırır. İlk olarak, kod üzerinde tam kontrol elde etmek için formların öğe öğe manuel olarak nasıl oluşturulacağını göstereceğiz. Daha sonra bu işlemin nasıl [otomatikleştirileceğini |#Automatic rendering] göstereceğiz.
 
+`Nette\Forms\Blueprint::latte($form)` yöntemini kullanarak oluşturulan form için bir Latte şablonu önerisine sahip olabilirsiniz, bu da tarayıcı sayfasına çıktı verecektir. Ardından, kodu bir tıklama ile seçmeniz ve projenize kopyalamanız yeterlidir. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ RadioList veya CheckboxList gibi daha karmaşık form öğeleri öğe öğe işl
 ```
 
 
-Kod Önerisi `{formPrint}` .[#toc-formprint]
--------------------------------------------
-
-`{formPrint}` etiketini kullanarak bir form için benzer bir Latte kodu oluşturabilirsiniz. Bunu bir şablona yerleştirirseniz, normal oluşturma yerine taslak kodu görürsünüz. Sonra onu seçin ve projenize kopyalayın.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ Bloğu yalnızca bir yerde, düzen şablonunun başında içe aktarmanız gereki
 Özel Durumlar .[#toc-special-cases]
 -----------------------------------
 
-Bir formun yalnızca iç içeriğini oluşturmanız gerekiyorsa `<form>` & `</form>` HTML etiketleri, örneğin bir AJAX isteğinde, formu `{formContext} … {/formContext}` ile açıp kapatabilirsiniz. Mantıksal anlamda `{form}` ile benzer şekilde çalışır, burada form öğelerini çizmek için diğer etiketleri kullanmanıza izin verir, ancak aynı zamanda hiçbir şey çizmez.
+Formun yalnızca iç kısmını HTML etiketleri olmadan oluşturmanız gerekiyorsa `<form>`örneğin snippet gönderirken, `n:tag-if` özniteliğini kullanarak bunları gizleyin:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Username: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Etiket `formContainer` bir form konteyneri içindeki girdilerin oluşturulmasına yardımcı olur.
@@ -434,6 +430,8 @@ $form->addText('city', 'City:');
 $form->addSelect('country', 'Country:', $countries);
 ```
 
+Oluşturucu önce grupları, ardından da herhangi bir gruba ait olmayan öğeleri çizer.
+
 
 Bootstrap Desteği .[#toc-bootstrap-support]
 -------------------------------------------
@@ -444,7 +442,7 @@ Bootstrap Desteği .[#toc-bootstrap-support]
 HTML Nitelikleri .[#toc-html-attributes]
 ========================================
 
-`setHtmlAttribute(string $name, $value = true)` adresini kullanarak form denetimlerine herhangi bir HTML niteliği atayabilirsiniz:
+Form öğeleri için rastgele HTML nitelikleri ayarlamak için `setHtmlAttribute(string $name, $value = true)` yöntemini kullanın:
 
 ```php
 $form->addInteger('number', 'Number:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Order by:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // değişiklik üzerine JS fonksiyonu submit()'i çağırır
 
 
-// <form> üzerinde uygulama
+// <form> 'un kendi niteliklerini ayarlamak için
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Giriş türünü ayarlama:
+Eleman türünün belirtilmesi:
 
 ```php
 $form->addText('tel', 'Your telephone:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Your telephone:')
 	->setHtmlAttribute('placeholder', 'Please, fill in your telephone');
 ```
 
-HTML niteliğini radyo veya onay kutusu listelerindeki her bir öğe için farklı değerlerle ayarlayabiliriz.
-Değerin anahtara göre seçildiğinden emin olmak için `style:` adresinden sonra iki nokta üst üste işaretine dikkat edin:
+.[warning]
+Tür ve diğer niteliklerin ayarlanması yalnızca görsel amaçlara hizmet eder. Girdi doğruluğunun doğrulanması sunucuda gerçekleşmelidir; bunu uygun bir [form denetimi | controls] seçerek ve [doğrulama kuralları | validation] belirleyerek sağlayabilirsiniz.
+
+Radyo veya onay kutusu listelerindeki ayrı öğeler için, her biri için farklı değerlere sahip bir HTML niteliği ayarlayabiliriz.
+Değerin anahtara göre seçilmesini sağlayan `style:` adresinden sonraki iki nokta üst üste işaretine dikkat edin:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ Render:
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Mantıksal bir HTML niteliği için (değeri olmayan, örneğin `readonly`), bir soru işareti kullanabilirsiniz:
+`readonly` gibi boolean nitelikleri ayarlamak için soru işaretli gösterimi kullanabiliriz:
 
 ```php
-$colors = ['r' => 'kırmızı', 'g' => 'yeşil', 'b' => 'mavi'];
 $form->addCheckboxList('colors', 'Colors:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // birden fazla anahtar için dizi kullanın, örneğin ['r', 'g']
 ```
@@ -541,9 +541,6 @@ Checkbox, CheckboxList ve RadioList öğeleri için öğeyi saran öğe şablonu
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/tr/standalone.texy b/forms/tr/standalone.texy
index ffbe8fbea5..80f027847c 100644
--- a/forms/tr/standalone.texy
+++ b/forms/tr/standalone.texy
@@ -107,7 +107,7 @@ Form her zaman sunucu tarafında doğrulanır, ancak JavaScript doğrulaması da
 Bunu sayfaya ekleyin:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Formun bulunduğu sayfanın kaynak koduna bakarsanız, Nette'in gerekli alanları `required` CSS sınıfına sahip öğelere eklediğini fark edebilirsiniz. Aşağıdaki stili şablona eklemeyi deneyin, "Ad" etiketi kırmızı olacaktır. Kullanıcılar için gerekli alanları zarif bir şekilde işaretliyoruz:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-PHP 8.0'dan itibaren, bir kurucu kullanan bu zarif gösterimi kullanabilirsiniz:
+Alternatif olarak, kurucuyu kullanabilirsiniz:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Veri sınıfının özellikleri de enum olabilir ve otomatik olarak eşleştirilirler. .{data-version:3.2.4}
+
 Nette'e verileri bize bu sınıfın nesneleri olarak döndürmesini nasıl söyleyebiliriz? Düşündüğünüzden daha kolay. Tek yapmanız gereken parametre olarak hidrate edilecek sınıf adını veya nesneyi belirtmek:
 
 ```php
@@ -258,6 +260,8 @@ Eşleme daha sonra `$person` özellik türünden konteyneri `PersonFormData` sı
 $person->setMappedType(PersonFormData::class);
 ```
 
+Tarayıcı sayfasına yazdıracak olan `Nette\Forms\Blueprint::dataClass($form)` yöntemini kullanarak bir formun veri sınıfı için bir öneri oluşturabilirsiniz. Daha sonra kodu seçmek ve projenize kopyalamak için tıklamanız yeterlidir. .{data-version:3.1.15}
+
 
 Çoklu Gönder Düğmeleri .[#toc-multiple-submit-buttons]
 ======================================================
diff --git a/forms/tr/validation.texy b/forms/tr/validation.texy
index 2d02efe8a3..ee6bf35514 100644
--- a/forms/tr/validation.texy
+++ b/forms/tr/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:')
 	->addRule($form::MinLength, 'Password must be at least %d characters', 8);
 ```
 
-Nette, adları `Nette\Forms\Form` sınıfının sabitleri olan bir dizi yerleşik kuralla birlikte gelir:
+**Doğrulama kuralları yalnızca kullanıcı öğeyi doldurduysa kontrol edilir.**
 
-Tüm kontroller için aşağıdaki kuralları kullanabiliriz:
+Nette, isimleri `Nette\Forms\Form` sınıfının sabitleri olan bir dizi önceden tanımlanmış kuralla birlikte gelir. Bu kuralları tüm öğelere uygulayabiliriz:
 
 | sabit | açıklama | argümanlar
 |-------
@@ -38,7 +38,11 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz:
 | `IsNotIn` | değer dizideki herhangi bir elemana eşit değil | `array`
 | `Valid` | girdi doğrulamayı geçer ( [koşullar |#conditions] için) | -
 
-`addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` denetimleri için aşağıdaki kurallar da kullanılabilir:
+
+Metin girişleri .[#toc-text-inputs]
+-----------------------------------
+
+`addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` öğeleri için aşağıdaki kurallardan bazıları da uygulanabilir:
 
 | `MinLength` | minimum dize uzunluğu | `int`
 | `MaxLength` | maksimum dize uzunluğu | `int`
@@ -57,9 +61,23 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz:
 `Integer`, `Numeric` a `Float` kuralları değeri otomatik olarak tamsayıya (veya sırasıyla float) dönüştürür. Ayrıca, `URL` kuralı da şeması olmayan bir adresi kabul eder (örneğin `nette.org`) ve şemayı tamamlar (`https://nette.org`).
 `Pattern` ve `PatternInsensitive` içindeki ifadeler tüm değer için geçerli olmalıdır, yani `^` and `$` karakterlerine sarılmış gibi olmalıdır.
 
+
+Ürün Sayısı .[#toc-number-of-items]
+-----------------------------------
+
+ `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` öğeleri için, seçilen öğelerin veya yüklenen dosyaların sayısını sınırlamak üzere aşağıdaki kuralları da kullanabilirsiniz:
+
+| `MinLength` | minimum sayı | `int`
+| `MaxLength` | maksimum sayı | `int`
+| `Length` | aralıktaki sayı veya tam sayı | çiftleri `[int, int]` veya `int`
+
+
+Dosya Yükleme
+-------------
+
 `addUpload()`, `addMultiUpload()` kontrolleri için aşağıdaki kurallar da kullanılabilir:
 
-| `MaxFileSize` | maksimum dosya boyutu | `int`
+| `MaxFileSize` | bayt cinsinden maksimum dosya boyutu | `int`
 | `MimeType` | MIME türü, joker karakterleri kabul eder (`'video/*'`) | `string\|string[]`
 | `Image` | yüklenen dosya JPEG, PNG, GIF, WebP | -
 | `Pattern` | dosya adı düzenli ifadeyle eşleşiyor | `string`
@@ -67,15 +85,9 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz:
 
 `MimeType` ve `Image` PHP uzantısı `fileinfo` gerektirir. Bir dosya veya resmin gerekli türde olup olmadığı imzasından anlaşılır. Tüm dosyanın bütünlüğü kontrol edilmez. Bir resmin bozuk olup olmadığını örneğin [yüklemeye |http:request#toImage] çalışarak öğrenebilirsiniz.
 
-`addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` kontrolleri için, sırasıyla yüklenen dosyalar olmak üzere seçilen öğelerin sayısını sınırlamak için aşağıdaki kurallar da kullanılabilir:
-
-| `MinLength` | minimum sayı | `int`
-| `MaxLength` | maksimum sayı | `int`
-| `Length` | aralıktaki sayı veya tam sayı | çifti `[int, int]` veya `int`
-
 
 Hata Mesajları .[#toc-error-messages]
--------------------------------------
+=====================================
 
 `Pattern` ve `PatternInsensitive` dışındaki tüm önceden tanımlanmış kuralların varsayılan bir hata mesajı vardır, bu nedenle bunlar atlanabilir. Bununla birlikte, tüm özelleştirilmiş mesajları ileterek ve formüle ederek, formu daha kullanıcı dostu hale getireceksiniz.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 Nette, `toggle()` yöntemini kullanarak [JavaScript |#Dynamic JavaScript] tarafında bir koşulun yerine getirilip getirilmemesine tepki vermek çok kolaydır, bkz.
 
 
-Kontroller Arasındaki Referanslar .[#toc-references-between-controls]
-=====================================================================
+Başka Bir Öğeye Referans .[#toc-reference-to-another-element]
+=============================================================
 
-Kural veya koşul bağımsız değişkeni başka bir öğeye referans olabilir. Örneğin, `text` adresinin `length` alanının değeri kadar karaktere sahip olduğunu dinamik olarak doğrulayabilirsiniz:
+Bir kural veya koşul için bağımsız değişken olarak başka bir form öğesi de iletebilirsiniz. Kural daha sonra kullanıcı tarafından tarayıcıda girilen değeri kullanacaktır. Bu, örneğin, `password` öğesinin `password_confirm` öğesiyle aynı dizeyi içerdiğini dinamik olarak doğrulamak için kullanılabilir:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ Bu komut dosyası, birkaç olası kaynaktan temin edilebilen `netteForms.js` adr
 Komut dosyasını CDN'den doğrudan HTML sayfasına gömebilirsiniz:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Ya da yerel olarak projenin ortak klasörüne kopyalayın (örneğin `vendor/nette/forms/src/assets/netteForms.min.js` adresinden):
diff --git a/forms/uk/controls.texy b/forms/uk/controls.texy
index 26af421a00..31182bceb0 100644
--- a/forms/uk/controls.texy
+++ b/forms/uk/controls.texy
@@ -5,8 +5,8 @@
 Огляд вбудованих елементів керування формою.
 
 
-addText(string|int $name, $label=null): TextInput .[method]
-===========================================================
+addText(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+========================================================================================
 
 Додає однорядкове текстове поле (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Якщо користувач не заповнив поле, повертається порожній рядок `''`, або використовуйте `setNullable()` для повернення `null`.
 
@@ -20,13 +20,10 @@ $form->addText('name', 'Имя:')
 
 Максимальна довжина може бути обмежена за допомогою `setMaxLength()`. Функція [addFilter() |validation#Modifying-Input-Values] дозволяє змінити введене користувачем значення.
 
-Використовуйте `setHtmlType()` для зміни [типу |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] елемента введення на `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Замість типів `number` і `email` ми рекомендуємо використовувати [addInteger |#addInteger] і [addEmail |#addEmail], які забезпечують валідацію на стороні сервера.
+Ви можете змінити візуальний вигляд текстового поля на типи `search`, `tel` або `url` за допомогою `setHtmlType()`, як показано у [специфікації |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Пам'ятайте, що зміна типу є лише візуальною і не виконує функцій перевірки. Для типу `url` доречно додати спеціальне [правило URL-адреси |validation#Text inputs].
 
-```php
-$form->addText('color', 'Выберите цвет:')
-	->setHtmlType('color')
-	->addRule($form::Pattern, 'недопустимое значение', '[0-9a-f]{6}');
-```
+.[note]
+Для інших типів вводу, таких як `number`, `range`, `email`, `date`, `datetime-local`, `time` і `color`, використовуйте спеціалізовані методи, такі як [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail], [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] і [addColor |#addColor], які забезпечують валідацію на стороні сервера. Типи `month` та `week` ще не повністю підтримуються всіма браузерами.
 
 Для елемента може бути встановлено так зване "порожнє значення", яке є чимось на зразок значення за замовчуванням, але якщо користувач не перезаписує його, повертає порожній рядок або `null`.
 
@@ -58,14 +55,31 @@ addInteger(string|int $name, $label=null): TextInput .[method]
 Додає поле введення для цілого числа (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Повертає або ціле число, або `null`, якщо користувач нічого не ввів.
 
 ```php
-$form->addInteger('level', 'Уровень:')
+$form->addInteger('year', 'Year:')
+	->addRule($form::Range, 'Рік має бути в діапазоні від %d до %d.', [1900, 2023 |1900, 2023]);
+```
+
+Елемент рендериться як `<input type="numeric">`. За допомогою методу `setHtmlType()` ви можете змінити тип на `range` для відображення у вигляді слайдера, або на `text`, якщо ви віддаєте перевагу стандартному текстовому полю без особливої поведінки `numeric`.
+
+
+addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12}
+=================================================================================
+
+Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything.
+
+```php
+$form->addFloat('level', 'Level:')
 	->setDefaultValue(0)
-	->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]);
+->addRule($form::Range, 'Рівень повинен бути в діапазоні від %d до %d.', [0, 100 |0, 100]);
 ```
 
+Елемент рендериться як `<input type="numeric">`. За допомогою методу `setHtmlType()` ви можете змінити тип на `range` для відображення у вигляді слайдера, або на `text`, якщо ви віддаєте перевагу стандартному текстовому полю без особливої поведінки `numeric`.
+
+Nette і браузер Chrome приймають як кому, так і крапку в якості десяткових роздільників. Щоб зробити цю функціональність доступною у Firefox, рекомендується встановити атрибут `lang` або для конкретного елемента, або, наприклад, для всієї сторінки, `<html lang="cs">`.
+
 
-addEmail(string|int $name, $label=null): TextInput .[method]
-============================================================
+addEmail(string|int $name, $label=null, int $maxLength=255): TextInput .[method]
+================================================================================
 
 Додає поле адреси електронної пошти з перевіркою достовірності (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Якщо користувач не заповнив поле, повертається порожній рядок `''`, або використовуйте `setNullable()` для повернення `null`.
 
@@ -78,8 +92,8 @@ $form->addEmail('email', 'Имейл:');
 Максимальна довжина може бути обмежена за допомогою `setMaxLength()`. Функція [addFilter() |validation#Modifying-Input-Values] дозволяє змінити введене користувачем значення. Ви можете встановити так зване "порожнє значення", використовуючи `setEmptyValue()`.
 
 
-addPassword(string|int $name, $label=null): TextInput .[method]
-===============================================================
+addPassword(string|int $name, $label=null, $cols, ?int $maxLength=null): TextInput .[method]
+============================================================================================
 
 Додає поле пароля (клас [TextInput |api:Nette\Forms\Controls\TextInput]).
 
@@ -104,8 +118,8 @@ $form->addCheckbox('agree', 'Я согласен с условиями')
 ```
 
 
-addCheckboxList(string|int $name, $label=null, array $items=null): CheckboxList .[method]
-=========================================================================================
+addCheckboxList(string|int $name, $label=null, ?array $items=null): CheckboxList .[method]
+==========================================================================================
 
 Додає список прапорців для вибору кількох елементів (клас [CheckboxList |api:Nette\Forms\Controls\CheckboxList]). Повертає масив ключів обраних елементів. Метод `getSelectedItems()` повертає значення замість ключів.
 
@@ -125,9 +139,15 @@ $form->addCheckboxList('colors', 'Цвета:', [
 
 Під час встановлення значень за замовчуванням також перевіряється, що вони є одним із запропонованих елементів, інакше виникає виняток. Цю перевірку можна вимкнути за допомогою `checkDefaultValue(false)`.
 
+Якщо ви відправляєте форму методом `GET`, ви можете вибрати більш компактний метод передачі даних, який дозволяє заощадити на розмірі рядка запиту. Це активується за допомогою налаштування атрибута HTML форми:
+
+```php
+$form->setHtmlAttribute('data-nette-compact');
+```
 
-addRadioList(string|int $name, $label=null, array $items=null): RadioList .[method]
-===================================================================================
+
+addRadioList(string|int $name, $label=null, ?array $items=null): RadioList .[method]
+====================================================================================
 
 Додає радіокнопки (клас [RadioList |api:Nette\Forms\Controls\RadioList]). Повертає ключ обраного елемента або `null`, якщо користувач нічого не вибрав. Метод `getSelectedItem()` повертає значення замість ключа.
 
@@ -148,8 +168,8 @@ $form->addRadioList('gender', 'Пол:', $sex);
 Під час встановлення значення за замовчуванням перевіряється, що воно є одним із запропонованих елементів, інакше виникає виняток. Цю перевірку можна вимкнути за допомогою `checkDefaultValue(false)`.
 
 
-addSelect(string|int $name, $label=null, array $items=null): SelectBox .[method]
-================================================================================
+addSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox .[method]
+==================================================================================================
 
 Додає поле вибору (клас [SelectBox |api:Nette\Forms\Controls\SelectBox]). Повертає ключ обраного елемента або `null`, якщо користувач нічого не вибрав. Метод `getSelectedItem()` повертає значення замість ключа.
 
@@ -193,8 +213,8 @@ $form->addSelect('country', 'Страна:', $countries)
 Під час встановлення значення за замовчуванням перевіряється, що воно є одним із запропонованих елементів, інакше виникає виняток. Цю перевірку можна вимкнути за допомогою `checkDefaultValue(false)`.
 
 
-addMultiSelect(string|int $name, $label=null, array $items=null): MultiSelectBox .[method]
-==========================================================================================
+addMultiSelect(string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox .[method]
+============================================================================================================
 
 Додає вікно вибору кількох варіантів (клас [MultiSelectBox |api:Nette\Forms\Controls\MultiSelectBox]). Повертає масив ключів обраних елементів. Метод `getSelectedItems()` повертає значення замість ключів.
 
@@ -246,8 +266,81 @@ $form->addMultiUpload('files', 'Файлы:')
 Правила `MimeType` і `Image` визначають необхідний тип файлу або зображення за його сигнатурою. Цілісність усього файлу не перевіряється. Ви можете дізнатися, чи не пошкоджено зображення, наприклад, спробувавши [завантажити його |http:request#toImage].
 
 
-addHidden(string|int $name, string $default=null): HiddenField .[method]
-========================================================================
+addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14}
+======================================================================================
+
+Додає поле, яке дозволяє користувачеві легко ввести дату, що складається з року, місяця і дня (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+За замовчуванням приймаються або об'єкти, що реалізують `DateTimeInterface`, або рядок з часом, або число, що представляє мітку часу UNIX. Те саме стосується аргументів правила `Min`, `Max` або `Range`, які визначають мінімальну та максимальну допустиму дату.
+
+```php
+$form->addDate('date', 'Date:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+За замовчуванням повертається об'єкт `DateTimeImmutable`. За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] або мітку часу:
+
+```php
+$form->addDate('date', 'Date:')
+	->setFormat('Y-m-d');
+```
+
+
+addTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===============================================================================================================
+
+Додає поле, яке дозволяє користувачеві легко вводити час, що складається з годин, хвилин і необов'язково секунд (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+За замовчуванням приймаються або об'єкти, що реалізують `DateTimeInterface`, або рядок з часом, або число, що представляє часову мітку UNIX. Використовується лише інформація про час з цих входів; дата ігнорується. Те саме стосується аргументів правил `Min`, `Max` або `Range`, які визначають мінімальний і максимальний дозволений час. Якщо мінімальне значення перевищує максимальне, створюється часовий діапазон, що охоплює опівніч.
+
+```php
+$form->addTime('time', 'Time:', withSeconds: true)
+	->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']);
+```
+
+За замовчуванням він повертає об'єкт `DateTimeImmutable` (з датою 1 січня, рік 1). За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]:
+
+```php
+$form->addTime('time', 'Time:')
+	->setFormat('H:i');
+```
+
+
+addDateTime(string|int $name, $label=null, bool $withSeconds=false): DateTimeControl .[method]{data-version:3.1.14}
+===================================================================================================================
+
+Додає поле, яке дозволяє користувачеві легко вводити як дату, так і час, що складається з року, місяця, дня, годин, хвилин і необов'язково секунд (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]).
+
+За замовчуванням приймаються або об'єкти, що реалізують `DateTimeInterface`, або рядок з часом, або число, що представляє часову мітку UNIX. Те саме стосується аргументів правила `Min`, `Max` або `Range`, які визначають мінімальну та максимальну допустиму дату.
+
+```php
+$form->addDateTime('datetime', 'Date and Time:')
+	->setDefaultValue(new DateTime)
+	->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month'));
+```
+
+За замовчуванням повертається об'єкт `DateTimeImmutable`. За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] або мітку часу:
+
+```php
+$form->addDateTime('datetime')
+	->setFormat(DateTimeControl::FormatTimestamp);
+```
+
+
+addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14}
+===================================================================================
+
+Додає поле вибору кольору (клас [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Колір є рядком у форматі `#rrggbb`. Якщо користувач не зробив вибір, за замовчуванням повертається чорний колір `#000000`.
+
+```php
+$form->addColor('color', 'Color:')
+	->setDefaultValue('#3C8ED7');
+```
+
+
+addHidden(string|int $name, ?string $default=null): HiddenField .[method]
+=========================================================================
 
 Додає приховане поле (клас [HiddenField |api:Nette\Forms\Controls\HiddenField]).
 
@@ -257,6 +350,8 @@ $form->addHidden('userid');
 
 Використовуйте `setNullable()`, щоб змінити його так, щоб він повертав `null` замість порожнього рядка. Функція [addFilter() |validation#Modifying-Input-Values] дозволяє змінити представлене значення.
 
+Хоча елемент прихований, важливо розуміти, що його значення все одно може бути змінено або підроблено зловмисником. Завжди ретельно перевіряйте і підтверджуйте всі отримані значення на стороні сервера, щоб запобігти ризикам безпеки, пов'язаним з маніпуляціями з даними.
+
 
 addSubmit(string|int $name, $caption=null): SubmitButton .[method]
 ==================================================================
@@ -296,8 +391,8 @@ $form->addButton('raise', 'Поднять зарплату')
 ```
 
 
-addImageButton(string|int $name, string $src=null, string $alt=null): ImageButton .[method]
-===========================================================================================
+addImageButton(string|int $name, ?string $src=null, ?string $alt=null): ImageButton .[method]
+=============================================================================================
 
 Додає кнопку відправлення у вигляді зображення (клас [ImageButton |api:Nette\Forms\Controls\ImageButton]).
 
@@ -377,7 +472,7 @@ $sub2->addEmail('email', 'Имейл:');
 
 
 Опущені значення .[#toc-omitted-values]
----------------------------------------
+=======================================
 
 Якщо вас не цікавить значення, введене користувачем, ми можемо використовувати `setOmitted()`, щоб опустити його з результату, який надається методом `$form->getValues()` або передається обробникам. Це підходить для різних паролів для перевірки, антиспамових полів тощо.
 
@@ -390,18 +485,18 @@ $form->addPassword('passwordVerify', 'Повторите пароль:')
 
 
 Вимкнення елементів введення .[#toc-disabling-inputs]
------------------------------------------------------
+=====================================================
 
-Щоб вимкнути вхід, ви можете викликати `setDisabled()`. Таке поле не може бути відредаговане користувачем.
+Входи можна вимкнути за допомогою `setDisabled()`. Вимкнений вхід не може бути відредагований користувачем.
 
 ```php
 $form->addText('username', 'Имя пользователя:')
 	->setDisabled();
 ```
 
-Зверніть увагу, що браузер узагалі не надсилає відключені поля на сервер, тому ви навіть не знайдете їх у даних, які повертає функція `$form->getValues()`.
+Вимкнені входи не надсилаються браузером на сервер, тому ви не знайдете їх у даних, що повертаються функцією `$form->getValues()`. Однак, якщо ви задасте `setOmitted(false)`, Nette включить їх значення за замовчуванням у ці дані.
 
-Якщо ви встановлюєте значення за замовчуванням для поля, ви повинні зробити це тільки після його вимкнення:
+Коли викликається `setDisabled()`, **значення вводу стирається** з міркувань безпеки. Якщо ви встановлюєте значення за замовчуванням, це необхідно зробити після його деактивації:
 
 ```php
 $form->addText('username', 'Имя пользователя:')
@@ -409,6 +504,8 @@ $form->addText('username', 'Имя пользователя:')
 	->setDefaultValue($userName);
 ```
 
+Альтернативою відключеним полям є поля з атрибутом HTML `readonly`, які браузер надсилає на сервер. Хоча це поле доступне лише для читання, важливо розуміти, що його значення все одно може бути змінено або підроблено зловмисником.
+
 
 Користувацькі елементи керування .[#toc-custom-controls]
 ========================================================
@@ -428,8 +525,8 @@ $form->addComponent(new DateInput('Дата:'), 'date');
 ```php
 use Nette\Forms\Container;
 
-// додає метод addZip(string $name, string $label = null)
-Container::extensionMethod('addZip', function (Container $form, string $name, string $label = null) {
+// додає метод addZip(string $name, ?string $label = null)
+Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
 	return $form->addText($name, $label)
 		->addRule($form::Pattern, 'Не менше 5 номерів', '[0-9]{5}');
 });
diff --git a/forms/uk/in-presenter.texy b/forms/uk/in-presenter.texy
index ed89773929..a47dc3bcbf 100644
--- a/forms/uk/in-presenter.texy
+++ b/forms/uk/in-presenter.texy
@@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded'];
 
 З точки зору презентера форма є загальним компонентом. Тому вона розглядається як компонент і включається в презентер за допомогою [фабричного методу |application:components#Factory-Methods]. Це виглядатиме наступним чином:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 use Nette;
 use Nette\Application\UI\Form;
 
@@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter
 
 А рендеринг у шаблоні здійснюється за допомогою тега `{control}`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 <h1>Регистрация</h1>
 
 {control registrationForm}
@@ -132,7 +132,7 @@ $form->addText('name', 'Имя:')
 Вставте його в шаблон макета:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Якщо ви подивитеся у вихідний код сторінки з формою, ви можете помітити, що Nette вставляє обов'язкові поля в елементи з CSS-класом `required`. Спробуйте додати наступний стиль у шаблон, і мітка "Ім'я" буде червоного кольору. Ми елегантно позначаємо обов'язкові поля для користувачів:
@@ -232,7 +232,7 @@ class RegistrationFormData
 }
 ```
 
-Починаючи з PHP 8.0, ви можете використовувати цю елегантну нотацію, яка використовує конструктор:
+Крім того, ви можете скористатися конструктором:
 
 ```php
 class RegistrationFormData
@@ -246,6 +246,8 @@ class RegistrationFormData
 }
 ```
 
+Властивості класу даних також можуть бути переліченими, і вони будуть автоматично відображені. .{data-version:3.2.4}
+
 Як вказати Nette повертати дані у вигляді об'єктів цього класу? Легше, ніж ви думаєте. Все, що вам потрібно зробити, це вказати клас як тип параметра `$data` в обробнику:
 
 ```php
@@ -294,6 +296,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Ви можете згенерувати пропозицію для класу даних форми за допомогою методу `Nette\Forms\Blueprint::dataClass($form)`, який роздрукує її на сторінку браузера. Потім ви можете просто натиснути, щоб вибрати і скопіювати код у свій проект. .{data-version:3.1.15}
+
 
 Кілька кнопок надсилання .[#toc-multiple-submit-buttons]
 ========================================================
diff --git a/forms/uk/rendering.texy b/forms/uk/rendering.texy
index 95bf703c4d..7e84412b24 100644
--- a/forms/uk/rendering.texy
+++ b/forms/uk/rendering.texy
@@ -11,6 +11,8 @@
 
 [Система шаблонів Latte |latte:] докорінно полегшує відтворення форм та їхніх елементів. Спочатку ми покажемо, як відтворювати форми вручну, елемент за елементом, щоб отримати повний контроль над кодом. Пізніше ми покажемо, як [автоматизувати |#Automatic-Rendering] такий рендеринг.
 
+Ви можете отримати пропозицію шаблону Latte для форми, згенерованої за допомогою методу `Nette\Forms\Blueprint::latte($form)`, який виведе її на сторінку браузера. Потім вам просто потрібно вибрати код одним клацанням миші і скопіювати його в свій проект. .{data-version:3.1.15}
+
 
 `{control}`
 -----------
@@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form
 ```
 
 
-Пропозиція коду `{formPrint}` .[#toc-formprint]
------------------------------------------------
-
-Ви можете згенерувати подібний код Latte для форми, використовуючи тег `{formPrint}`. Якщо ви помістите його в шаблон, ви побачите проєкт коду замість звичайного рендерингу. Потім просто виділіть його та скопіюйте у свій проект.
-
-
 `{label}` `{input}`
 -------------------
 
@@ -237,15 +233,15 @@ protected function createComponentSignInForm(): Form
 Особливі випадки .[#toc-special-cases]
 --------------------------------------
 
-Якщо вам потрібно відобразити тільки внутрішній вміст форми без `<form>` & `</form>` HTML тегів, наприклад, в AJAX запиті, ви можете відкривати і закривати форму за допомогою `{formContext} … {/formContext}`. Він працює аналогічно `{form}` в логічному сенсі, тут він дозволяє вам використовувати інші теги для малювання елементів форми, але в той же час він нічого не малює.
+Якщо вам потрібно відобразити тільки внутрішню частину форми без HTML-тегів `<form>`наприклад, при надсиланні фрагментів, приховайте їх за допомогою атрибута `n:tag-if`:
 
 ```latte
-{formContext signForm}
+<form n:name=signInForm n:tag-if=false>
 	<div>
 		<label n:name=username>Имя пользователя: <input n:name=username></label>
 		{inputError username}
 	</div>
-{/formContext}
+</form>
 ```
 
 Тег `formContainer` допомагає при відтворенні даних, що вводяться, всередині контейнера форми.
@@ -434,6 +430,8 @@ $form->addText('city', 'Город:');
 $form->addSelect('country', 'Страна:', $countries);
 ```
 
+Рендер спочатку малює групи, а потім елементи, які не належать до жодної групи.
+
 
 Підтримка Bootstrap .[#toc-bootstrap-support]
 ---------------------------------------------
@@ -444,7 +442,7 @@ $form->addSelect('country', 'Страна:', $countries);
 Атрибути HTML .[#toc-html-attributes]
 =====================================
 
-Ви можете встановити будь-які атрибути HTML для елементів управління форми за допомогою `setHtmlAttribute(string $name, $value = true)`:
+Щоб задати довільні HTML-атрибути для елементів форми, скористайтеся методом `setHtmlAttribute(string $name, $value = true)`:
 
 ```php
 $form->addInteger('number', 'Кількість:')
@@ -454,11 +452,11 @@ $form->addSelect('rank', 'Замовити:', ['price', 'name'])
 	->setHtmlAttribute('onchange', 'submit()'); // викликає JS-функцію submit() у разі зміни
 
 
-// застосовується на <form>
+// Задати атрибути самого <form>
 $form->setHtmlAttribute('id', 'myForm');
 ```
 
-Встановлення типу входу:
+Вказівка типу елемента:
 
 ```php
 $form->addText('tel', 'Ваш телефон:')
@@ -466,8 +464,11 @@ $form->addText('tel', 'Ваш телефон:')
 	->setHtmlAttribute('placeholder', 'Пожалуйста, заполните ваш телефон');
 ```
 
-Ми можемо встановити HTML-атрибут для окремих елементів у списках радіо- або чекбоксів із різними значеннями для кожного з них.
-Зверніть увагу на двокрапку після `style:`, щоб переконатися, що значення вибирається за ключем:
+.[warning]
+Встановлення типу та інших атрибутів слугує лише для візуальних цілей. Перевірка коректності введення повинна відбуватися на сервері, що ви можете забезпечити, вибравши відповідний елемент [управління формою | controls] і вказавши [правила | validation] перевірки.
+
+Для окремих елементів у перемикачах або списках ми можемо встановити HTML-атрибут з різними значеннями для кожного з них.
+Зверніть увагу на двокрапку після `style:`, яка забезпечує вибір значення на основі ключа:
 
 ```php
 $colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
@@ -484,10 +485,9 @@ $form->addCheckboxList('colors', 'Цвета:', $colors)
 <label><input type="checkbox" name="colors[]" value="b">blue</label>
 ```
 
-Для логічного атрибута HTML (який не має значення, наприклад, `readonly`) можна використовувати знак питання:
+Для задання булевих атрибутів, таких як `readonly`, ми можемо використовувати позначення зі знаком питання:
 
 ```php
-$colors = ['r' => 'red', 'g' => 'green', 'b' => 'blue'];
 $form->addCheckboxList('colors', 'Кольори:', $colors)
 	->setHtmlAttribute('readonly?', 'r'); // використовувати масив для кількох ключів, наприклад ['r', 'g']
 ```
@@ -541,9 +541,6 @@ $html->class('distinctive');         // <label class="distinctive">
 
 ```php
 $input = $form->addCheckbox('send');
-echo $input->getControl();
-// <label><input type="checkbox" name="send"></label>
-
 $html = $input->getContainerPrototype();
 $html->setName('div'); // <div>
 $html->class('check'); // <div class="check">
diff --git a/forms/uk/standalone.texy b/forms/uk/standalone.texy
index ccd1872f46..c6f6a2562f 100644
--- a/forms/uk/standalone.texy
+++ b/forms/uk/standalone.texy
@@ -107,7 +107,7 @@ $form->addText('name', 'Имя:')
 Додайте його на сторінку:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Якщо ви подивитеся у вихідний код сторінки з формою, ви можете помітити, що Nette вставляє обов'язкові поля в елементи з CSS-класом `required`. Спробуйте додати наступний стиль у шаблон, і мітка "Ім'я" буде червоного кольору. Ми елегантно позначаємо обов'язкові поля для користувачів:
@@ -207,7 +207,7 @@ class RegistrationFormData
 }
 ```
 
-Починаючи з PHP 8.0, ви можете використовувати цю елегантну нотацію, яка використовує конструктор:
+Крім того, ви можете скористатися конструктором:
 
 ```php
 class RegistrationFormData
@@ -221,6 +221,8 @@ class RegistrationFormData
 }
 ```
 
+Властивості класу даних також можуть бути переліченими, і вони будуть автоматично відображені. .{data-version:3.2.4}
+
 Як сказати Nette, щоб він повертав нам дані у вигляді об'єктів цього класу? Легше, ніж ви думаєте. Все, що вам потрібно зробити, це вказати ім'я класу або об'єкта для гідратації як параметр:
 
 ```php
@@ -258,6 +260,8 @@ class RegistrationFormData
 $person->setMappedType(PersonFormData::class);
 ```
 
+Ви можете згенерувати пропозицію для класу даних форми за допомогою методу `Nette\Forms\Blueprint::dataClass($form)`, який роздрукує її на сторінку браузера. Потім ви можете просто натиснути, щоб вибрати і скопіювати код у свій проект. .{data-version:3.1.15}
+
 
 Кілька кнопок надсилання .[#toc-multiple-submit-buttons]
 ========================================================
diff --git a/forms/uk/validation.texy b/forms/uk/validation.texy
index a9ca94d241..493745cbfc 100644
--- a/forms/uk/validation.texy
+++ b/forms/uk/validation.texy
@@ -23,9 +23,9 @@ $form->addPassword('password', 'Пароль:')
 	->addRule($form::MinLength, 'Пароль должен состоять не менее чем из %d символов', 8);
 ```
 
-Nette постачається з низкою вбудованих правил, імена яких є константами класу `Nette\Forms\Form`:
+**Правила перевірки перевіряються тільки в тому випадку, якщо користувач заповнив елемент.**
 
-Ми можемо використовувати такі правила для всіх елементів керування:
+Nette постачається з низкою попередньо визначених правил, імена яких є константами класу `Nette\Forms\Form`. Ми можемо застосувати ці правила до всіх елементів:
 
 | константа | опис | аргументи
 |-------
@@ -38,7 +38,11 @@ Nette постачається з низкою вбудованих правил
 | `IsNotIn` | значення не дорівнює жодному елементу масиву | `array`
 | `Valid` | введення проходить валідацію (для [Умови |#Условия])| -
 
-Для елементів керування `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` також можуть бути використані такі правила:
+
+Текстові дані .[#toc-text-inputs]
+---------------------------------
+
+Для елементів `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` також можна застосувати деякі з наступних правил:
 
 | `MinLength` | мінімальна довжина рядка | `int`
 | `MaxLength` | максимальна довжина рядка | `int`
@@ -57,9 +61,23 @@ Nette постачається з низкою вбудованих правил
 Правила `Integer`, `Numeric` і `Float` автоматично перетворюють значення в ціле (або плаваюче відповідно). Більше того, правило `URL` також приймає адресу без схеми (наприклад, `nette.org`) і доповнює схему (`https://nette.org`).
 Вирази в `Pattern` і `PatternInsensitive` мають бути дійсними для всього значення, тобто так, ніби воно було обгорнуте в символи `^` и `$`.
 
+
+Кількість позицій .[#toc-number-of-items]
+-----------------------------------------
+
+Для елементів `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` ви також можете використовувати наступні правила для обмеження кількості обраних елементів або завантажених файлів:
+
+| `MinLength` | мінімальна кількість `int`
+| `MaxLength` | максимальна кількість `int`
+| `Length` | кількість в діапазоні або точна кількість | пар `[int, int]` або `int`
+
+
+Завантаження файлу
+------------------
+
 Для елементів керування `addUpload()`, `addMultiUpload()` також можуть бути використані такі правила:
 
-| `MaxFileSize` | максимальний розмір файлу | `int`
+| `MaxFileSize` | максимальний розмір файлу в байтах | `int`
 | `MimeType` | Тип MIME, приймає підстановні знаки (`'video/*'`) | `string\|string[]`
 | `Image` | завантажений файл є JPEG, PNG, GIF, WebP | -
 | `Pattern` | ім'я файлу відповідає регулярному виразу | `string`
@@ -67,15 +85,9 @@ Nette постачається з низкою вбудованих правил
 
 Для `MimeType` і `Image` потрібне розширення PHP `fileinfo`. Належність файлу або зображення до потрібного типу визначається за його сигнатурою. Цілісність усього файлу не перевіряється. Ви можете дізнатися, чи не пошкоджено зображення, наприклад, спробувавши [завантажити його |http:request#toImage].
 
-Для елементів керування `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` такі правила також можуть бути використані для обмеження кількості обраних елементів, відповідно завантажених файлів:
-
-| `MinLength` | мінімальна кількість | `int`
-| `MaxLength` | максимальна кількість | `int`
-| `Length` | кількість у діапазоні або точна кількість | пара `[int, int]` або `int`
-
 
 Повідомлення про помилки .[#toc-error-messages]
------------------------------------------------
+===============================================
 
 Усі зумовлені правила, крім `Pattern` і `PatternInsensitive`, мають повідомлення про помилку за замовчуванням, тому їх можна опустити. Однак, передавши і сформулювавши всі індивідуальні повідомлення, ви зробите форму зручнішою для користувача.
 
@@ -143,15 +155,15 @@ $form->addText(/* ... */)
 У Nette дуже легко реагувати на виконання або невиконання умови на стороні JavaScript, використовуючи метод `toggle()`, див. [Динамічний JavaScript |#Динамический JavaScript].
 
 
-Посилання між елементами керування .[#toc-references-between-controls]
-======================================================================
+Посилання на інший елемент .[#toc-reference-to-another-element]
+===============================================================
 
-Аргумент правила або умови може бути посиланням на інший елемент. Наприклад, ви можете динамічно підтвердити, що `text` має стільки символів, скільки вказано в полі `length`:
+Як аргумент для правила або умови ви також можете передати інший елемент форми. Тоді правило буде використовувати значення, яке користувач введе пізніше в браузері. Це можна використовувати, наприклад, для динамічної перевірки того, що елемент `password` містить той самий рядок, що й елемент `password_confirm`:
 
 ```php
-$form->addInteger('length');
-$form->addText('text')
-	->addRule($form::Length, null, $form['length']);
+$form->addPassword('password', 'Password');
+$form->addPassword('password_confirm', 'Confirm Password')
+    ->addRule($form::Equal, 'The passwords do not match', $form['password']);
 ```
 
 
@@ -281,7 +293,7 @@ $form->addText('zip', 'Поштовий індекс:')
 Ви можете вбудувати сценарій безпосередньо в HTML-сторінку з CDN:
 
 ```latte
-<script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
+<script src="https://unpkg.com/nette-forms@3"></script>
 ```
 
 Або скопіюйте локально в загальну папку проєкту (наприклад, із сайту `vendor/nette/forms/src/assets/netteForms.min.js`):
diff --git a/http/bg/request.texy b/http/bg/request.texy
index 44fd5475f7..f3821edcd2 100644
--- a/http/bg/request.texy
+++ b/http/bg/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Браузърите не изпращат откъса към сървъра, така че `$url->getFragment()` ще върне празен низ.
+Предупреждение: Браузърите не изпращат фрагмент към сървъра, така че `$url->getFragment()` ще върне празен низ.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Връща параметрите на заявката GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // връща GET параметър 'id' (
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Връща параметрите на заявката POST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-От кой URL адрес е дошъл потребителят? Внимавайте, това изобщо не е надеждно.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Криптирана ли е връзката (HTTPS)? Може да се наложи да конфигурирате [прокси сървър |configuration#HTTP-Proxy], за да работи правилно.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Връща обработено име на файл. Той съдържа само ASCII символи. `[a-zA-Z0-9.-]`. Ако името не съдържа такива знаци, се връща символът 'unknown'. Ако файлът е JPEG, PNG, GIF или WebP изображение, се връща правилното разширение на файла.
 
+.[caution]
+Изисква разширение на PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Връща съответното разширение на файла (без точка), съответстващо на открития тип MIME.
+
+.[caution]
+Изисква PHP разширение `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/bg/response.texy b/http/bg/response.texy
index 53743a6bd4..3f9b042847 100644
--- a/http/bg/response.texy
+++ b/http/bg/response.texy
@@ -15,8 +15,8 @@ Nette капсулира HTTP отговора в обекти с ясен API,
 За разлика от [Nette\Http\Request |request], този обект е променлив, така че можете да използвате сетъри, за да промените състоянието, т.е. да изпратите заглавия. Не забравяйте, че всички задаващи устройства **трябва да бъдат извикани преди да бъде изпратен какъвто и да е действителен изход.** Методът `isSent()` показва дали изходът е изпратен. Ако той връща `true`, всеки опит за изпращане на заглавие хвърля изключение `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Променя [кода на отговора на |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] състоянието. За по-добра четливост на изходния код се препоръчва да се използват [предварително дефинирани константи |api:Nette\Http\IResponse] вместо реални числа.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Изпраща заглавието `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Изпраща бисквитка. Стойности на параметрите по подразбиране:
 
 | `$path` | `'/'` | с покритие на всички пътища в (под)домейна *(може да се конфигурира)*.
@@ -138,8 +138,8 @@ $httpResponse->setCookie('lang', 'en', '100 days');
 Константите `Response::SameSiteLax`, `SameSiteStrict` и `SameSiteNone` могат да се използват за стойността `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Изтрива "бисквитката". Настройките по подразбиране имат следните стойности:
 - `$path` с обхват върху всички директории (`'/'`)
 - `$domain` с обхват в текущия (под)домейн, но не и в неговите поддомейни.
diff --git a/http/bg/sessions.texy b/http/bg/sessions.texy
index 03fb06e43e..1a8af7dcf7 100644
--- a/http/bg/sessions.texy
+++ b/http/bg/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Задава времето за неактивност, след което сесията се затваря.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Задава параметрите за бисквитките. Настройките по подразбиране могат да бъдат променени в раздела за [конфигурация |configuration#Session-Cookie].
 
 
diff --git a/http/bg/urls.texy b/http/bg/urls.texy
index 677dbec0f0..3ca69df876 100644
--- a/http/bg/urls.texy
+++ b/http/bg/urls.texy
@@ -62,6 +62,8 @@ $url = new Url(
 | | `getHostUrl(): string`| `'http://nette.org:8080'
 | | `getAbsoluteUrl(): string` | пълен URL адрес
 
+Предупреждение: Когато работите с URL, получен от [HTTP заявка |request], имайте предвид, че той няма да съдържа фрагмента, тъй като браузърът не го изпраща на сървъра.
+
 Можем да работим и с отделни параметри на заявката, като използваме:
 
 .[language-php]
diff --git a/http/cs/request.texy b/http/cs/request.texy
index 6a23793c3f..b5f46a1902 100644
--- a/http/cs/request.texy
+++ b/http/cs/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://doc.nette.org/cs/?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Prohlížeče neodesílají na server fragment, takže `$url->getFragment()` bude vracet prázdný řetězec.
+Upozornění: prohlížeče neodesílají na server fragment, takže `$url->getFragment()` bude vracet prázdný řetězec.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Vrací parametry GET požadavku.
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // vrací GET parametr 'id' (nebo null)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Vrací parametry POST požadavku.
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Z jaké URL uživatel přišel? Pozor, není vůbec spolehlivé.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Je spojení šifrované (HTTPS)? Pro správnou funkčnost může být potřeba [nastavit proxy|configuration#HTTP proxy].
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Vrací sanitizovaný název souboru. Obsahuje pouze ASCII znaky `[a-zA-Z0-9.-]`. Pokud název takové znaky neobsahuje, vrátí `'unknown'`. Pokud je soubor obrázek ve formátu JPEG, PNG, GIF, WebP nebo AVIF, vrátí i správnou příponu.
 
+.[caution]
+Vyžaduje PHP rozšíření `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Vrací vhodnou příponu souboru (bez tečky) odpovídající zjištěnému MIME typu.
+
+.[caution]
+Vyžaduje PHP rozšíření `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/cs/response.texy b/http/cs/response.texy
index ef4f008eca..6e243a9282 100644
--- a/http/cs/response.texy
+++ b/http/cs/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response
 Objekt je na rozdíl od [Nette\Http\Request|request] mutable, tedy pomocí setterů můžete měnit stav, tedy např. odesílat hlavičky. Nezapomeňte, že všechny settery musí být volány **před odesláním jakéhokoli výstupu.** Jestli už byl výstup odeslán prozradí metoda `isSent()`. Pokud vrací `true`, každý pokus o odeslání hlavičky vyvolá výjimku `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Změní stavový [kód odpovědi |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10]. Kvůli lepší srozumitelnosti zdrojového kódu doporučujeme pro kód používat místo čísel [předdefinované konstanty |api:Nette\Http\IResponse].
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Mění hlavičku `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('faktura.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Odešle cookie. Výchozí hodnoty parametrů:
 
 | `$path`     | `'/'`   | cookie má dosah na všechny cesty v (sub)doméně *(konfigurovatelné)*
@@ -138,8 +138,8 @@ Parametr `$domain` určuje, které domény mohou cookie přijímat. Není-li uve
 Pro hodnotu `$sameSite` můžete použít konstanty `Response::SameSiteLax`, `SameSiteStrict` a `SameSiteNone`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Smaže cookie. Výchozí hodnoty parametrů jsou:
 - `$path` s dosahem na všechny adresáře (`'/'`)
 - `$domain` s dosahem na aktuální (sub)doménu, ale nikoliv její subdomény
diff --git a/http/cs/sessions.texy b/http/cs/sessions.texy
index 2580cca56e..695b163cc7 100644
--- a/http/cs/sessions.texy
+++ b/http/cs/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Nastaví dobu neaktivity po které session vyexpiruje.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Nastavení parametrů pro cookie. Výchozí hodnoty parametrů můžete změnit v [konfiguraci|configuration#Session cookie].
 
 
diff --git a/http/cs/urls.texy b/http/cs/urls.texy
index 4f1095f896..8b453d13e2 100644
--- a/http/cs/urls.texy
+++ b/http/cs/urls.texy
@@ -62,6 +62,8 @@ Pro vrácení nebo změnu jednotlivých komponent URL jsou vám k dispozici tyto
 | 											| `getHostUrl(): string`		| `'http://nette.org:8080'`
 | 											| `getAbsoluteUrl(): string` 	| celá URL
 
+Upozornění: Když pracujete s URL, které je získáno z [HTTP requestu|request], mějte na paměti, že nebude obsahovat fragment, protože prohlížeč jej neodesílá na server.
+
 Můžeme pracovat i s jednotlivými query parametry pomocí:
 
 .[language-php]
diff --git a/http/de/request.texy b/http/de/request.texy
index b93dbdde68..593fb749ce 100644
--- a/http/de/request.texy
+++ b/http/de/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Browser senden kein Fragment an den Server, daher gibt `$url->getFragment()` einen leeren String zurück.
+Warnung: Browser senden keine Fragmente an den Server, so dass `$url->getFragment()` einen leeren String zurückgibt.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Gibt GET-Anfrageparameter zurück:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // liefert den GET-Parameter 'id' (oder null
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Gibt die Parameter der POST-Anforderung zurück:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Von welcher URL kam der Benutzer? Vorsicht, diese Angabe ist nicht zuverlässig.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Ist die Verbindung verschlüsselt (HTTPS)? Möglicherweise müssen Sie [einen Proxy ein |configuration#HTTP proxy] richten, damit die Verbindung funktioniert.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Gibt den bereinigten Dateinamen zurück. Er enthält nur ASCII-Zeichen `[a-zA-Z0-9.-]`. Enthält der Name keine solchen Zeichen, wird "unbekannt" zurückgegeben. Wenn die Datei ein JPEG-, PNG-, GIF- oder WebP-Bild ist, wird die korrekte Dateierweiterung zurückgegeben.
 
+.[caution]
+Erfordert die PHP-Erweiterung `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Gibt die entsprechende Dateierweiterung (ohne Punkt) zurück, die dem erkannten MIME-Typ entspricht.
+
+.[caution]
+Erfordert die PHP-Erweiterung `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/de/response.texy b/http/de/response.texy
index 4dff8b879d..5de925759e 100644
--- a/http/de/response.texy
+++ b/http/de/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 Im Gegensatz zu [Nette\Http\Request |request] ist dieses Objekt veränderbar, so dass Sie Setter verwenden können, um den Status zu ändern, d.h. um Header zu senden. Denken Sie daran, dass alle Setter **aufgerufen werden müssen, bevor die eigentliche Ausgabe gesendet wird.** Die Methode `isSent()` zeigt an, ob die Ausgabe gesendet wurde. Wenn sie `true` zurückgibt, löst jeder Versuch, eine Kopfzeile zu senden, eine `Nette\InvalidStateException` Ausnahme aus.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Ändert einen [Status-Antwort-Code |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10]. Zur besseren Lesbarkeit des Quellcodes wird empfohlen, [vordefinierte Konstanten |api:Nette\Http\IResponse] anstelle von tatsächlichen Zahlen zu verwenden.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Sendet den Header `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Sendet ein Cookie. Standard-Parameterwerte:
 
 | `$path` | `'/'` | mit Geltungsbereich auf alle Pfade der (Sub-)Domain *(konfigurierbar)*
@@ -138,8 +138,8 @@ Die Option `$domain` bestimmt, welche Domänen (Ursprünge) Cookies akzeptieren
 Sie können die Konstanten `Response::SameSiteLax`, `SameSiteStrict` und `SameSiteNone` für den Wert `$sameSite` verwenden.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Löscht ein Cookie. Die Standardwerte der Parameter sind:
 - `$path` mit Geltungsbereich für alle Verzeichnisse (`'/'`)
 - `$domain` mit Geltungsbereich der aktuellen (Sub-)Domain, aber nicht deren Subdomains
diff --git a/http/de/sessions.texy b/http/de/sessions.texy
index 30f15791ec..54903bff75 100644
--- a/http/de/sessions.texy
+++ b/http/de/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Legt die Zeit der Inaktivität fest, nach der die Session abläuft.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Legt Parameter für Cookies fest. Sie können die Standardparameterwerte in [configuration |configuration#Session cookie] ändern.
 
 
diff --git a/http/de/urls.texy b/http/de/urls.texy
index 6a6647d450..3526ac33b1 100644
--- a/http/de/urls.texy
+++ b/http/de/urls.texy
@@ -62,6 +62,8 @@ Die folgenden Methoden stehen zur Verfügung, um einzelne URL-Komponenten zu erh
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | vollständige URL
 
+Warnung: Bei der Arbeit mit einer URL, die aus einer [HTTP-Anfrage |request] stammt, ist zu beachten, dass sie das Fragment nicht enthält, da der Browser es nicht an den Server sendet.
+
 Wir können auch mit einzelnen Abfrageparametern arbeiten:
 
 .[language-php]
diff --git a/http/el/request.texy b/http/el/request.texy
index 5b215f84c1..d1a7ee93fc 100644
--- a/http/el/request.texy
+++ b/http/el/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Οι φυλλομετρητές δεν στέλνουν ένα τμήμα στον διακομιστή, οπότε το `$url->getFragment()` θα επιστρέψει ένα κενό αλφαριθμητικό.
+Προειδοποίηση: Οι φυλλομετρητές δεν στέλνουν ένα τμήμα στον διακομιστή, οπότε το `$url->getFragment()` θα επιστρέψει μια κενή συμβολοσειρά.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Επιστρέφει τις παραμέτρους της αίτησης GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // επιστρέφει την παράμε
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Επιστρέφει παραμέτρους αίτησης POST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Από ποια διεύθυνση URL ήρθε ο χρήστης; Προσοχή, δεν είναι καθόλου αξιόπιστο.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Είναι η σύνδεση κρυπτογραφημένη (HTTPS); Ενδέχεται να χρειαστεί να [ρυθμίσετε έναν διακομιστή μεσολάβησης |configuration#HTTP proxy] για τη σωστή λειτουργία.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Επιστρέφει το καθαρισμένο όνομα αρχείου. Περιέχει μόνο χαρακτήρες ASCII `[a-zA-Z0-9.-]`. Εάν το όνομα δεν περιέχει τέτοιους χαρακτήρες, επιστρέφει 'unknown'. Εάν το αρχείο είναι εικόνα JPEG, PNG, GIF ή WebP, επιστρέφει τη σωστή επέκταση αρχείου.
 
+.[caution]
+Απαιτεί την επέκταση PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Επιστρέφει την κατάλληλη επέκταση αρχείου (χωρίς την τελεία) που αντιστοιχεί στον τύπο MIME που εντοπίστηκε.
+
+.[caution]
+Απαιτεί την επέκταση PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/el/response.texy b/http/el/response.texy
index dfd85f5a6c..d7e7c946aa 100644
--- a/http/el/response.texy
+++ b/http/el/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 Σε αντίθεση με το [Nette\Http\Request |request], αυτό το αντικείμενο είναι μεταβλητό, οπότε μπορείτε να χρησιμοποιήσετε ρυθμιστές για να αλλάξετε την κατάσταση, δηλαδή να στείλετε κεφαλίδες. Να θυμάστε ότι όλοι οι ρυθμιστές **πρέπει να κληθούν πριν από την αποστολή της πραγματικής εξόδου.** Η μέθοδος `isSent()` δηλώνει αν η έξοδος έχει σταλεί. Εάν επιστρέφει `true`, κάθε προσπάθεια αποστολής κεφαλίδας προκαλεί μια εξαίρεση `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Αλλάζει έναν [κωδικό απόκρισης |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] κατάστασης. Για καλύτερη αναγνωσιμότητα του πηγαίου κώδικα συνιστάται η χρήση [προκαθορισμένων σταθερών |api:Nette\Http\IResponse] αντί πραγματικών αριθμών.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Αποστέλλει την επικεφαλίδα `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Αποστέλλει ένα cookie. Προεπιλεγμένες τιμές παραμέτρων:
 
 | `$path` | `'/'` | με εμβέλεια σε όλες τις διαδρομές στον (υπο)τομέα *(διαμορφώσιμο)*
@@ -138,8 +138,8 @@ $httpResponse->setCookie('lang', 'en', '100 days');
 Μπορείτε να χρησιμοποιήσετε τις σταθερές `Response::SameSiteLax`, `SameSiteStrict` και `SameSiteNone` για την τιμή `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Διαγράφει ένα cookie. Οι προεπιλεγμένες τιμές των παραμέτρων είναι:
 - `$path` με εμβέλεια σε όλους τους καταλόγους (`'/'`)
 - `$domain` με πεδίο εφαρμογής τον τρέχοντα (υπο)τομέα, αλλά όχι τους υποτομείς του
diff --git a/http/el/sessions.texy b/http/el/sessions.texy
index c3d21ff3b6..338f3046cd 100644
--- a/http/el/sessions.texy
+++ b/http/el/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Ορίζει το χρόνο αδράνειας μετά τον οποίο λήγει η σύνοδος.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Ορίζει παραμέτρους για τα cookies. Μπορείτε να αλλάξετε τις προεπιλεγμένες τιμές των παραμέτρων στο [configuration |configuration#Session cookie].
 
 
diff --git a/http/el/urls.texy b/http/el/urls.texy
index eff9550e24..4f4c9fd929 100644
--- a/http/el/urls.texy
+++ b/http/el/urls.texy
@@ -62,6 +62,8 @@ $url = new Url(
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | πλήρες URL
 
+Προειδοποίηση: Όταν εργάζεστε με μια διεύθυνση URL που λαμβάνεται από μια [αίτηση HTTP |request], να έχετε υπόψη σας ότι δεν θα περιέχει το θραύσμα, καθώς το πρόγραμμα περιήγησης δεν το στέλνει στον διακομιστή.
+
 Μπορούμε επίσης να λειτουργήσουμε με μεμονωμένες παραμέτρους ερωτήματος χρησιμοποιώντας:
 
 .[language-php]
diff --git a/http/en/request.texy b/http/en/request.texy
index 080b6d54ff..68b6ff95fc 100644
--- a/http/en/request.texy
+++ b/http/en/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Browsers do not send a fragment to the server, so `$url->getFragment()` will return an empty string.
+Warning: Browsers do not send a fragment to the server, so `$url->getFragment()` will return an empty string.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Returns GET request parameters:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // returns GET parameter 'id' (or null)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Returns POST request parameters:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-What URL did the user come from? Beware, it is not reliable at all.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Is the connection encrypted (HTTPS)? You may need to [set up a proxy|configuration#HTTP proxy] for proper functionality.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Returns the sanitized file name. It contains only ASCII characters `[a-zA-Z0-9.-]`. If the name does not contain such characters, it returns 'unknown'. If the file is JPEG, PNG, GIF, WebP or AVIF image, it returns the correct file extension.
 
+.[caution]
+Requires PHP extension `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Returns the appropriate file extension (without the period) corresponding to the detected MIME type.
+
+.[caution]
+Requires PHP extension `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/en/response.texy b/http/en/response.texy
index 58d61af63e..88afd3812d 100644
--- a/http/en/response.texy
+++ b/http/en/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response
 Unlike [Nette\Http\Request|request], this object is mutable, so you can use setters to change the state, ie to send headers. Remember that all setters **must be called before any actual output is sent.** The `isSent()` method tells if output have been sent. If it returns `true`, each attempt to send a header throws an `Nette\InvalidStateException` exception.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Changes a status [response code |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10]. For better source code readability it is recommended to use [predefined constants |api:Nette\Http\IResponse] instead of actual numbers.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Sends the header `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Sends a cookie. Default parameter values:
 
 | `$path`     | `'/'`   | with scope to all paths on (sub)domain *(configurable)*
@@ -138,8 +138,8 @@ The `$domain` option determines which domains (origins) can accept cookies. If n
 You can use the `Response::SameSiteLax`, `SameSiteStrict` and `SameSiteNone` constants for the `$sameSite` value.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Deletes a cookie. The default values ​​of the parameters are:
 - `$path` with scope to all directories (`'/'`)
 - `$domain` with scope of the current (sub)domain, but not its subdomains
diff --git a/http/en/sessions.texy b/http/en/sessions.texy
index 697105fc43..7d57c8599a 100644
--- a/http/en/sessions.texy
+++ b/http/en/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Sets the time of inactivity after which the session expires.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Sets parameters for cookies. You can change the default parameter values in [configuration#Session cookie].
 
 
diff --git a/http/en/urls.texy b/http/en/urls.texy
index 71385836a8..61523b3d13 100644
--- a/http/en/urls.texy
+++ b/http/en/urls.texy
@@ -62,6 +62,8 @@ The following methods are available to get or change individual URL components:
 | 											| `getHostUrl(): string`		| `'http://nette.org:8080'`
 | 											| `getAbsoluteUrl(): string` 	| full URL
 
+Warning: When working with a URL obtained from an [HTTP request|request], keep in mind that it will not contain the fragment, as the browser does not send it to the server.
+
 We can also operate with individual query parameters using:
 
 .[language-php]
diff --git a/http/es/request.texy b/http/es/request.texy
index 99f1351f48..301b14b851 100644
--- a/http/es/request.texy
+++ b/http/es/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Los navegadores no envían un fragmento al servidor, por lo que `$url->getFragment()` devolverá una cadena vacía.
+Advertencia: Los navegadores no envían fragmentos al servidor, por lo que `$url->getFragment()` devolverá una cadena vacía.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Devuelve los parámetros de la petición GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // devuelve el parámetro GET 'id' (o null)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Devuelve los parámetros de la solicitud POST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-¿De qué URL procede el usuario? Cuidado, no es nada fiable.
-
-
 isSecured(): bool .[method]
 ---------------------------
 ¿Está cifrada la conexión (HTTPS)? Es posible que tenga que [configurar un proxy |configuration#HTTP proxy] para que funcione correctamente.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Devuelve el nombre de archivo desinfectado. Sólo contiene caracteres ASCII `[a-zA-Z0-9.-]`. Si el nombre no contiene tales caracteres, devuelve 'desconocido'. Si el archivo es una imagen JPEG, PNG, GIF o WebP, devuelve la extensión de archivo correcta.
 
+.[caution]
+Requiere la extensión PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Devuelve la extensión de archivo apropiada (sin el punto) correspondiente al tipo MIME detectado.
+
+.[caution]
+Requiere la extensión PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/es/response.texy b/http/es/response.texy
index 8ae2418680..aa7869ce5e 100644
--- a/http/es/response.texy
+++ b/http/es/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 A diferencia de [Nette\Http\Request |request], este objeto es mutable, por lo que puede utilizar setters para cambiar el estado, es decir, para enviar cabeceras. Recuerde que todos los setters **deben ser llamados antes de que cualquier salida real sea enviada.** El método `isSent()` dice si la salida ha sido enviada. Si devuelve `true`, cada intento de enviar una cabecera lanza una excepción `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Cambia un [código de |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] estado de [respuesta |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10]. Para una mejor legibilidad del código fuente se recomienda utilizar [constantes predefinidas |api:Nette\Http\IResponse] en lugar de números reales.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Envía la cabecera `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Envía una cookie. Valores por defecto de los parámetros:
 
 | `$path` | `'/'` | con alcance a todas las rutas del (sub)dominio *(configurable)*
@@ -138,8 +138,8 @@ La opción `$domain` determina qué dominios (orígenes) pueden aceptar cookies.
 Puede utilizar las constantes `Response::SameSiteLax`, `SameSiteStrict` y `SameSiteNone` para el valor `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Elimina una cookie. Los valores por defecto de los parámetros son
 - `$path` con alcance a todos los directorios (`'/'`)
 - `$domain` con alcance al (sub)dominio actual, pero no a sus subdominios
diff --git a/http/es/sessions.texy b/http/es/sessions.texy
index 74e7998749..8a6976b0db 100644
--- a/http/es/sessions.texy
+++ b/http/es/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Establece el tiempo de inactividad tras el cual expira la sesión.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Establece los parámetros para las cookies. Puede cambiar los valores predeterminados de los parámetros en [configuration |configuration#Session cookie].
 
 
diff --git a/http/es/urls.texy b/http/es/urls.texy
index 818bd9c551..b0e53b67ec 100644
--- a/http/es/urls.texy
+++ b/http/es/urls.texy
@@ -62,6 +62,8 @@ Los siguientes métodos están disponibles para obtener o cambiar componentes in
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | URL completa
 
+Atención: Cuando trabaje con una URL obtenida de una [petición HTTP |request], tenga en cuenta que no contendrá el fragmento, ya que el navegador no lo envía al servidor.
+
 También podemos operar con parámetros de consulta individuales utilizando:
 
 .[language-php]
diff --git a/http/fr/request.texy b/http/fr/request.texy
index 8f6dc7b848..8836be0815 100644
--- a/http/fr/request.texy
+++ b/http/fr/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Les navigateurs n'envoient pas de fragment au serveur, donc `$url->getFragment()` retournera une chaîne vide.
+Attention : Les navigateurs n'envoient pas de fragment au serveur, de sorte que `$url->getFragment()` renvoie une chaîne vide.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Renvoie les paramètres de la requête GET :
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // renvoie le paramètre GET 'id' (ou null)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Renvoie les paramètres de la demande POST :
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-De quelle URL l'utilisateur provient-il ? Attention, ce n'est pas du tout fiable.
-
-
 isSecured(): bool .[method]
 ---------------------------
 La connexion est-elle cryptée (HTTPS) ? Vous devrez peut-être configurer [un proxy |configuration#HTTP proxy] pour une bonne fonctionnalité.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Renvoie le nom de fichier aseptisé. Il ne contient que des caractères ASCII `[a-zA-Z0-9.-]`. Si le nom ne contient pas de tels caractères, il renvoie "inconnu". Si le fichier est une image JPEG, PNG, GIF ou WebP, il renvoie l'extension de fichier correcte.
 
+.[caution]
+Requiert l'extension PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Renvoie l'extension de fichier appropriée (sans le point) correspondant au type MIME détecté.
+
+.[caution]
+Requiert l'extension PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/fr/response.texy b/http/fr/response.texy
index c42a4ac920..44bb6cda81 100644
--- a/http/fr/response.texy
+++ b/http/fr/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Réponse .[#toc-nette-http-response]
 Contrairement à [Nette\Http\Request |request], cet objet est mutable, donc vous pouvez utiliser des setters pour changer l'état, c'est-à-dire pour envoyer des en-têtes. Rappelez-vous que tous les setters **doivent être appelés avant l'envoi de toute sortie réelle.** La méthode `isSent()` indique si la sortie a été envoyée. Si elle renvoie `true`, chaque tentative d'envoyer un en-tête lève une exception `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Modifie un [code de réponse |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] d'état. Pour une meilleure lisibilité du code source, il est recommandé d'utiliser des [constantes prédéfinies |api:Nette\Http\IResponse] plutôt que des nombres réels.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Envoie l'en-tête `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Envoie un cookie. Valeurs par défaut des paramètres :
 
 | `$path` | `'/'` | avec une portée à tous les chemins sur le (sous-)domaine *(configurable)*
@@ -138,8 +138,8 @@ L'option `$domain` détermine quels domaines (origines) peuvent accepter les coo
 Vous pouvez utiliser les constantes `Response::SameSiteLax`, `SameSiteStrict` et `SameSiteNone` pour la valeur `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Supprime un cookie. Les valeurs par défaut des paramètres sont :
 - `$path` avec une portée à tous les répertoires (`'/'`)
 - `$domain` avec la portée du (sous-)domaine actuel, mais pas de ses sous-domaines
diff --git a/http/fr/sessions.texy b/http/fr/sessions.texy
index ab9a8c8144..225667b025 100644
--- a/http/fr/sessions.texy
+++ b/http/fr/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Définit le temps d'inactivité après lequel la session expire.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Définit les paramètres des cookies. Vous pouvez modifier les valeurs par défaut des paramètres dans [configuration |configuration#Session cookie].
 
 
diff --git a/http/fr/urls.texy b/http/fr/urls.texy
index 2d5a0c35fa..6340d5b64c 100644
--- a/http/fr/urls.texy
+++ b/http/fr/urls.texy
@@ -62,6 +62,8 @@ Les méthodes suivantes sont disponibles pour obtenir ou modifier des composants
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | URL complète
 
+Attention : Lorsque vous travaillez avec une URL obtenue à partir d'une [requête HTTP |request], gardez à l'esprit qu'elle ne contiendra pas le fragment, car le navigateur ne l'envoie pas au serveur.
+
 Nous pouvons également opérer avec des paramètres de requête individuels en utilisant :
 
 .[language-php]
diff --git a/http/hu/request.texy b/http/hu/request.texy
index e8e9a3931c..35cf2534f9 100644
--- a/http/hu/request.texy
+++ b/http/hu/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-A böngészők nem küldenek töredéket a kiszolgálónak, ezért a `$url->getFragment()` üres karakterláncot ad vissza.
+Figyelmeztetés: A böngészők nem küldenek töredéket a kiszolgálónak, ezért a `$url->getFragment()` egy üres karakterláncot fog visszaadni.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Visszaadja a GET-kérelem paramétereit:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // visszaadja a GET paramétert 'id' (vagy n
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 POST kérés paramétereinek visszaadása:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Milyen URL-ről érkezett a felhasználó? Vigyázat, egyáltalán nem megbízható.
-
-
 isSecured(): bool .[method]
 ---------------------------
 A kapcsolat titkosított (HTTPS)? Lehet, hogy a megfelelő működéshez [proxy-t |configuration#HTTP proxy] kell beállítania.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Visszaadja a szanált fájlnevet. Csak ASCII karaktereket tartalmaz. `[a-zA-Z0-9.-]`. Ha a név nem tartalmaz ilyen karaktereket, akkor az 'unknown' értéket adja vissza. Ha a fájl JPEG, PNG, GIF vagy WebP kép, akkor a megfelelő fájlkiterjesztést adja vissza.
 
+.[caution]
+PHP kiterjesztés szükséges `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Visszaadja az észlelt MIME-típusnak megfelelő fájlkiterjesztést (pont nélkül).
+
+.[caution]
+PHP-bővítményt igényel `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/hu/response.texy b/http/hu/response.texy
index b01f95c733..23810055ed 100644
--- a/http/hu/response.texy
+++ b/http/hu/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 A [Nette\Http\Request-tel |request] ellentétben ez az objektum változtatható, így az állapot megváltoztatásához, azaz a fejlécek elküldéséhez használhatsz állítót. Ne feledje, hogy minden beállítót **a tényleges kimenet elküldése előtt kell meghívni.** A `isSent()` metódus megmondja, hogy a kimenet elküldésre került-e. Ha a `true` visszatér, akkor minden egyes fejléc küldési kísérlet `Nette\InvalidStateException` kivételt dob.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Megváltoztatja a státusz [válaszkódot |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10]. A forráskód jobb olvashatósága érdekében ajánlott a tényleges számok helyett [előre definiált konstansokat |api:Nette\Http\IResponse] használni.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Elküldi a `Content-Type` fejlécet.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Cookie-t küld. Alapértelmezett paraméterértékek:
 
 | `$path` | `'/'` | az (al)tartomány összes elérési útvonalára kiterjedő hatállyal *(konfigurálható)*.
@@ -138,8 +138,8 @@ A `$domain` opció határozza meg, hogy mely tartományok (származási helyek)
 A `$sameSite` értékhez használhatja a `Response::SameSiteLax`, `SameSiteStrict` és `SameSiteNone` konstansokat.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Töröl egy sütit. A paraméterek alapértelmezett értékei a következők:
 - `$path` minden könyvtárra kiterjedő hatállyal (`'/'`).
 - `$domain` az aktuális (al)tartomány hatókörével, de nem az aldomainek hatókörével.
diff --git a/http/hu/sessions.texy b/http/hu/sessions.texy
index 65dcc2393f..483ccf2008 100644
--- a/http/hu/sessions.texy
+++ b/http/hu/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Beállítja az inaktivitás idejét, amely után a munkamenet lejár.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 A sütik paramétereinek beállítása. Az alapértelmezett paraméterértékeket a [configuration#Session cookie |configuration#Session cookie] menüpontban módosíthatja.
 
 
diff --git a/http/hu/urls.texy b/http/hu/urls.texy
index fe7f6cf7c8..b39ac25fa1 100644
--- a/http/hu/urls.texy
+++ b/http/hu/urls.texy
@@ -62,6 +62,8 @@ A következő módszerek állnak rendelkezésre az egyes URL-komponensek lekérd
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | teljes URL
 
+Figyelmeztetés: Ha egy [HTTP-kérésből |request] kapott URL-címmel dolgozol, ne feledd, hogy az nem tartalmazza a töredéket, mivel a böngésző nem küldi el a kiszolgálónak.
+
 Az egyes lekérdezési paraméterekkel is operálhatunk a következőkkel:
 
 .[language-php]
diff --git a/http/it/request.texy b/http/it/request.texy
index c76f283b0f..33ed760871 100644
--- a/http/it/request.texy
+++ b/http/it/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-I browser non inviano un frammento al server, quindi `$url->getFragment()` restituirà una stringa vuota.
+Attenzione: I browser non inviano un frammento al server, quindi `$url->getFragment()` restituirà una stringa vuota.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Restituisce i parametri della richiesta GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // restituisce il parametro GET 'id' (o null
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Restituisce i parametri della richiesta POST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Da quale URL proviene l'utente? Attenzione, non è affatto affidabile.
-
-
 isSecured(): bool .[method]
 ---------------------------
 La connessione è criptata (HTTPS)? Potrebbe essere necessario [impostare un proxy |configuration#HTTP proxy] per una corretta funzionalità.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Restituisce il nome del file sanificato. Contiene solo caratteri ASCII `[a-zA-Z0-9.-]`. Se il nome non contiene tali caratteri, restituisce "unknown". Se il file è un'immagine JPEG, PNG, GIF o WebP, restituisce l'estensione corretta.
 
+.[caution]
+Richiede l'estensione PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Restituisce l'estensione di file appropriata (senza il punto) corrispondente al tipo MIME rilevato.
+
+.[caution]
+Richiede l'estensione PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/it/response.texy b/http/it/response.texy
index 8b1f115827..ce4f7da461 100644
--- a/http/it/response.texy
+++ b/http/it/response.texy
@@ -15,8 +15,8 @@ Nettezza Http Risposta .[#toc-nette-http-response]
 A differenza di [Nette\Http\Request |request], questo oggetto è mutabile, quindi si possono usare i setter per cambiare lo stato, cioè per inviare le intestazioni. Ricordare che tutti i setter **devono essere chiamati prima dell'invio di qualsiasi output effettivo.** Il metodo `isSent()` dice se l'output è stato inviato. Se restituisce `true`, ogni tentativo di inviare un'intestazione lancia un'eccezione `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Cambia un [codice di risposta |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] di stato. Per una migliore leggibilità del codice sorgente, si consiglia di utilizzare [costanti predefinite |api:Nette\Http\IResponse] anziché numeri reali.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Invia l'intestazione `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Invia un cookie. Valori predefiniti dei parametri:
 
 | `$path` | `'/'` | con estensione a tutti i percorsi del (sotto)dominio *(configurabile)*
@@ -138,8 +138,8 @@ L'opzione `$domain` determina quali domini (origini) possono accettare i cookie.
 È possibile utilizzare le costanti `Response::SameSiteLax`, `SameSiteStrict` e `SameSiteNone` per il valore `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Elimina un cookie. I valori predefiniti dei parametri sono:
 - `$path` con estensione a tutte le directory (`'/'`)
 - `$domain` con ambito del (sotto)dominio corrente, ma non dei suoi sottodomini
diff --git a/http/it/sessions.texy b/http/it/sessions.texy
index d3b8637bab..e0b5c490dd 100644
--- a/http/it/sessions.texy
+++ b/http/it/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Imposta il tempo di inattività dopo il quale la sessione scade.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Imposta i parametri per i cookie. È possibile modificare i valori dei parametri predefiniti in [configuration#Session cookie |configuration#Session cookie].
 
 
diff --git a/http/it/urls.texy b/http/it/urls.texy
index 01319b8c8b..434e067515 100644
--- a/http/it/urls.texy
+++ b/http/it/urls.texy
@@ -62,6 +62,8 @@ Per ottenere o modificare singoli componenti dell'URL sono disponibili i seguent
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | URL completo
 
+Attenzione: Quando si lavora con un URL ottenuto da una [richiesta HTTP |request], tenere presente che non conterrà il frammento, poiché il browser non lo invia al server.
+
 Possiamo anche operare con singoli parametri di query utilizzando:
 
 .[language-php]
diff --git a/http/pl/request.texy b/http/pl/request.texy
index c8d899a45f..581894a707 100644
--- a/http/pl/request.texy
+++ b/http/pl/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://doc.nette.org/en/?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Przeglądarki nie wysyłają fragmentu do serwera, więc `$url->getFragment()` zwróci pusty ciąg.
+Ostrzeżenie: Przeglądarki nie wysyłają fragmentu do serwera, więc `$url->getFragment()` zwróci pusty ciąg znaków.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Zwraca parametry żądania GET.
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // zwraca parametr GET 'id' (lub null)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Zwraca parametry żądania POST.
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Z jakiego adresu URL przyszedł użytkownik? Uważaj, w ogóle nie jest niezawodny.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Czy połączenie jest szyfrowane (HTTPS)? Może być konieczne skonfigurowanie [proxy |configuration#HTTP-Proxy] dla prawidłowej funkcjonalności.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Zwraca oczyszczoną nazwę pliku. Zawiera tylko znaki ASCII `[a-zA-Z0-9.-]`. Jeśli nazwa nie zawiera takich znaków, zwraca `'unknown'`. Jeśli plik jest obrazem JPEG, PNG, GIF lub WebP, zwraca również prawidłowe rozszerzenie.
 
+.[caution]
+Wymaga rozszerzenia PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Zwraca odpowiednie rozszerzenie pliku (bez kropki) odpowiadające wykrytemu typowi MIME.
+
+.[caution]
+Wymaga rozszerzenia PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/pl/response.texy b/http/pl/response.texy
index 363f21bd36..7d8bc72b7a 100644
--- a/http/pl/response.texy
+++ b/http/pl/response.texy
@@ -15,8 +15,8 @@ Odpowiedź sieci .[#toc-nette-http-response]
 W przeciwieństwie do Nette: [HttpRequest |request], ten obiekt jest zmienny, więc możesz użyć seterów do zmiany stanu, tj. do wysłania nagłówków. Pamiętaj, że wszystkie setery **muszą być wywołane przed wysłaniem jakichkolwiek danych wyjściowych.** Metoda `isSent()` mówi, czy dane wyjściowe zostały wysłane. Jeśli zwraca `true`, to każda próba wysłania nagłówka rzuca wyjątek `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Zmienia [kod |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] statusu [odpowiedzi |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10]. Dla lepszej czytelności kodu źródłowego zalecamy używanie [predefiniowanych stałych |api:Nette\Http\IResponse] zamiast liczb.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Zmienia nagłówek na `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('faktura.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Wysyła ciasteczko. Domyślne wartości parametrów:
 
 | `$path` | `'/'` | cookie dociera do wszystkich ścieżek w (pod)domenie *(konfigurowalne)*
@@ -138,8 +138,8 @@ Parametr `$domain` określa, które domeny mogą akceptować pliki cookie. Jeśl
 Dla wartości `$sameSite`, można użyć stałych `Response::SameSiteLax`, `SameSiteStrict`, oraz `SameSiteNone`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Usuwa plik cookie. Domyślne wartości parametrów to:
 - `$path` z zasięgiem do wszystkich katalogów (`'/'`)
 - `$domain` z zasięgiem do bieżącej (sub)domeny, ale nie do jej subdomen
diff --git a/http/pl/sessions.texy b/http/pl/sessions.texy
index 79f3b2a4e6..e3b6d39edd 100644
--- a/http/pl/sessions.texy
+++ b/http/pl/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Ustawia okres bezczynności, po którym sesja wygasa.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Ustawia parametry dla pliku cookie. Można zmienić domyślne wartości parametrów w [konfiguracji |configuration#Session-Cookie].
 
 
diff --git a/http/pl/urls.texy b/http/pl/urls.texy
index 595a64b01b..031cfbc265 100644
--- a/http/pl/urls.texy
+++ b/http/pl/urls.texy
@@ -62,6 +62,8 @@ Aby zwrócić lub zmienić poszczególne składniki adresu URL, dostępne są na
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | pełny adres URL
 
+Ostrzeżenie: Podczas pracy z adresem URL uzyskanym z [żądania |request] HTTP należy pamiętać, że nie będzie on zawierał fragmentu, ponieważ przeglądarka nie wysyła go do serwera.
+
 Możemy również pracować z poszczególnymi parametrami zapytania za pomocą:
 
 .[language-php]
diff --git a/http/pt/request.texy b/http/pt/request.texy
index 7e36306737..3de79bb3a2 100644
--- a/http/pt/request.texy
+++ b/http/pt/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Os navegadores não enviam um fragmento para o servidor, portanto `$url->getFragment()` retornará uma cadeia vazia.
+Aviso: Os navegadores não enviam um fragmento ao servidor, portanto, o site `$url->getFragment()` retornará uma cadeia de caracteres vazia.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Retorna os parâmetros de solicitação GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // retorna o parâmetro GET 'id' (ou nulo)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Retorna os parâmetros de solicitação de PÓS-PST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-De que URL o usuário veio? Cuidado, ela não é confiável em absoluto.
-
-
 isSecured(): bool .[method]
 ---------------------------
 A conexão é criptografada (HTTPS)? Talvez seja necessário [configurar um proxy |configuration#HTTP proxy] para uma funcionalidade adequada.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Devolve o nome do arquivo higienizado. Contém apenas caracteres ASCII `[a-zA-Z0-9.-]`. Se o nome não contiver tais caracteres, ele retorna "desconhecido". Se o arquivo for JPEG, PNG, GIF, ou imagem WebP, ele retorna a extensão correta do arquivo.
 
+.[caution]
+Requer a extensão PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Retorna a extensão de arquivo apropriada (sem o ponto) correspondente ao tipo MIME detectado.
+
+.[caution]
+Requer a extensão PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/pt/response.texy b/http/pt/response.texy
index 828fe5722d..f223725b0a 100644
--- a/http/pt/response.texy
+++ b/http/pt/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Resposta .[#toc-nette-http-response]
 Unlike [Nette\Http\Request |request], this object is mutable, so you can use setters to change the state, ie to send headers. Lembre-se que todos os setters **devem ser chamados antes que qualquer saída real seja enviada.** O método `isSent()` informa se a saída foi enviada. Se ele retornar `true`, cada tentativa de enviar um cabeçalho lançará uma exceção `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Altera um [código de resposta de |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] status. Para melhor legibilidade do código fonte, é recomendado o uso de [constantes pré-definidas |api:Nette\Http\IResponse] em vez de números reais.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Envia o cabeçalho `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Envia um cookie. Valores de parâmetros padrão:
 
 | `$path` | `'/'` | com escopo para todos os caminhos no (sub)domínio *(configurável)*
@@ -138,8 +138,8 @@ A opção `$domain` determina quais domínios (origens) podem aceitar cookies. S
 Você pode usar as constantes `Response::SameSiteLax`, `SameSiteStrict` e `SameSiteNone` para o valor `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Elimina um cookie. Os valores padrão dos parâmetros são:
 - `$path` com escopo para todos os diretórios (`'/'`)
 - `$domain` com escopo do (sub)domínio atual, mas não de seus subdomínios
diff --git a/http/pt/sessions.texy b/http/pt/sessions.texy
index c073b1c7fe..d325ca10e5 100644
--- a/http/pt/sessions.texy
+++ b/http/pt/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Define o tempo de inatividade após o qual a sessão expira.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Estabelece parâmetros para cookies. Você pode alterar os valores padrão dos parâmetros na [configuração#Bookie de sessão |configuration#Session cookie].
 
 
diff --git a/http/pt/urls.texy b/http/pt/urls.texy
index 10ee166de8..820671e9c0 100644
--- a/http/pt/urls.texy
+++ b/http/pt/urls.texy
@@ -62,6 +62,8 @@ Os seguintes métodos estão disponíveis para obter ou alterar os componentes i
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | URL completa
 
+Aviso: Ao trabalhar com um URL obtido de uma [solicitação HTTP |request], lembre-se de que ele não conterá o fragmento, pois o navegador não o envia para o servidor.
+
 Também podemos operar com parâmetros de consulta individuais usando:
 
 .[language-php]
diff --git a/http/ro/request.texy b/http/ro/request.texy
index 9579a906de..1c9e43a669 100644
--- a/http/ro/request.texy
+++ b/http/ro/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Browserele nu trimit un fragment către server, astfel încât `$url->getFragment()` va returna un șir gol.
+Avertisment: Browserele nu trimit un fragment către server, astfel încât `$url->getFragment()` va returna un șir gol.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Returnează parametrii cererii GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // returnează parametrul GET "id" (sau nul)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Returnează parametrii cererii POST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-De la ce URL a venit utilizatorul? Atenție, nu este deloc de încredere.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Conexiunea este criptată (HTTPS)? Este posibil să fie necesar să configurați [un proxy |configuration#HTTP proxy] pentru o funcționalitate corespunzătoare.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Returnează numele de fișier curățat. Acesta conține numai caractere ASCII `[a-zA-Z0-9.-]`. Dacă numele nu conține astfel de caractere, se returnează "necunoscut". Dacă fișierul este o imagine JPEG, PNG, GIF sau WebP, se returnează extensia corectă a fișierului.
 
+.[caution]
+Necesită extensia PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Returnează extensia de fișier corespunzătoare (fără punct) care corespunde tipului MIME detectat.
+
+.[caution]
+Necesită extensia PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/ro/response.texy b/http/ro/response.texy
index 6f315787f7..70715bc041 100644
--- a/http/ro/response.texy
+++ b/http/ro/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Răspuns .[#toc-nette-http-response]
 Spre deosebire de [Nette\Http\Request |request], acest obiect este mutabil, astfel încât puteți utiliza setori pentru a schimba starea, adică pentru a trimite antetele. Nu uitați că toți cei care setează **trebuie să fie apelați înainte de a trimite orice ieșire efectivă.** Metoda `isSent()` indică dacă au fost trimise ieșirile. Dacă returnează `true`, fiecare încercare de a trimite un antet aruncă o excepție `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Modifică un [cod de răspuns de |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] stare. Pentru o mai bună lizibilitate a codului sursă, se recomandă utilizarea unor [constante predefinite |api:Nette\Http\IResponse] în locul numerelor reale.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Trimite antetul `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Trimite un cookie. Valori implicite ale parametrilor:
 
 | `$path` | `'/'` | cu domeniul de aplicare pentru toate căile de acces pe (sub)domeniu *(configurabil)*.
@@ -138,8 +138,8 @@ Opțiunea `$domain` determină domeniile (originile) care pot accepta cookie-uri
 Puteți utiliza constantele `Response::SameSiteLax`, `SameSiteStrict` și `SameSiteNone` pentru valoarea `$sameSite`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Șterge un modul cookie. Valorile implicite ale parametrilor sunt:
 - `$path` cu domeniul de aplicare la toate directoarele (`'/'`)
 - `$domain` cu domeniul de aplicare al (sub)domeniului curent, dar nu și al subdomeniilor sale
diff --git a/http/ro/sessions.texy b/http/ro/sessions.texy
index 60dbff9906..c712dff6aa 100644
--- a/http/ro/sessions.texy
+++ b/http/ro/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Stabilește timpul de inactivitate după care expiră sesiunea.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Stabilește parametrii pentru cookie-uri. Puteți modifica valorile implicite ale parametrilor în [configuration |configuration#Session cookie].
 
 
diff --git a/http/ro/urls.texy b/http/ro/urls.texy
index 5984e73fa7..4330b9aa92 100644
--- a/http/ro/urls.texy
+++ b/http/ro/urls.texy
@@ -62,6 +62,8 @@ Setter | Getter | Getter | Valoare returnată
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | URL complet
 
+Avertisment: Atunci când lucrați cu o adresă URL obținută în urma unei [cereri HTTP |request], rețineți că aceasta nu va conține fragmentul, deoarece browserul nu îl trimite către server.
+
 De asemenea, putem opera cu parametri de interogare individuali folosind:
 
 .[language-php]
diff --git a/http/ru/request.texy b/http/ru/request.texy
index ed5afba54d..8b38fd3257 100644
--- a/http/ru/request.texy
+++ b/http/ru/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Браузеры не отправляют фрагмент на сервер, поэтому `$url->getFragment()` вернет пустую строку.
+Внимание: Браузеры не отправляют фрагмент на сервер, поэтому `$url->getFragment()` вернет пустую строку.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Возвращает параметры GET-запроса:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // возвращает GET-параметр
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Возвращает параметры POST-запроса:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-С какого URL пришел пользователь? Остерегайтесь, это совсем не надежно.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Зашифровано ли соединение (HTTPS)? Возможно, вам потребуется настроить [прокси-сервер |configuration#HTTP-Proxy] для правильной работы.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Возвращает санированное имя файла. Оно содержит только символы ASCII `[a-zA-Z0-9.-]`. Если имя не содержит таких символов, возвращается 'unknown'. Если файл является изображением JPEG, PNG, GIF или WebP, возвращается правильное расширение файла.
 
+.[caution]
+Требуется расширение PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Возвращает соответствующее расширение файла (без точки), соответствующее обнаруженному MIME-типу.
+
+.[caution]
+Требуется расширение PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/ru/response.texy b/http/ru/response.texy
index 1a69ea4ab9..cf80cb6718 100644
--- a/http/ru/response.texy
+++ b/http/ru/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 В отличие от [Nette\Http\Request |request], этот объект является изменяемым, поэтому вы можете использовать сеттеры для изменения состояния, т.е. для отправки заголовков. Помните, что все сеттеры **должны быть вызваны до отправки фактического вывода.** Метод `isSent()` показывает, был ли отправлен вывод. Если он возвращает `true`, то каждая попытка отправить заголовок вызывает исключение `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Изменяет [код ответа |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] статуса. Для лучшей читаемости исходного кода рекомендуется использовать [предопределенные константы |api:Nette\Http\IResponse] вместо реальных чисел.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Отправляет заголовок `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Отправляет cookie. Значения параметров по умолчанию:
 
 | `$path` | `'/'` | с охватом всех путей на (под)домене *(настраивается)*.
@@ -138,8 +138,8 @@ $httpResponse->setCookie('lang', 'en', '100 days');
 Для значения `$sameSite` можно использовать константы `Response::SameSiteLax`, `SameSiteStrict` и `SameSiteNone`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Удаляет файл cookie. По умолчанию параметры имеют следующие значения:
 - `$path` с областью действия на все каталоги (`'/'`)
 - `$domain` с областью действия на текущий (под)домен, но не на его поддомены.
diff --git a/http/ru/sessions.texy b/http/ru/sessions.texy
index 78719bdc8b..7f65265352 100644
--- a/http/ru/sessions.texy
+++ b/http/ru/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Устанавливает время бездействия, после которого сессия завершается.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Устанавливает параметры для куки. Значения параметров по умолчанию можно изменить в разделе [configuration|configuration#Session-Cookie].
 
 
diff --git a/http/ru/urls.texy b/http/ru/urls.texy
index 3b3f370eea..b8a5c275bb 100644
--- a/http/ru/urls.texy
+++ b/http/ru/urls.texy
@@ -62,6 +62,8 @@ $url = new Url(
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | полный URL
 
+Внимание: При работе с URL, полученным из [HTTP-запроса |request], имейте в виду, что он не будет содержать фрагмент, поскольку браузер не отправляет его на сервер.
+
 Мы также можем работать с отдельными параметрами запроса, используя:
 
 .[language-php]
diff --git a/http/sl/request.texy b/http/sl/request.texy
index 6198c956f8..36fee1fc89 100644
--- a/http/sl/request.texy
+++ b/http/sl/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Brskalniki strežniku ne pošljejo fragmenta, zato `$url->getFragment()` vrne prazen niz.
+Opozorilo: Brskalniki strežniku ne pošiljajo fragmentov, zato bo `$url->getFragment()` vrnil prazen niz.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Vrne parametre zahteve GET:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // vrne parameter GET 'id' (ali null)
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Vrne parametre zahteve POST:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-S katerega naslova URL je prišel uporabnik? Pazite, ni zanesljivo.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Ali je povezava šifrirana (HTTPS)? Za pravilno delovanje boste morda morali nastaviti [posrednika |configuration#HTTP proxy].
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Vrne prečiščeno ime datoteke. Vsebuje samo znake ASCII `[a-zA-Z0-9.-]`. Če ime ne vsebuje takih znakov, vrne 'unknown'. Če je datoteka slika JPEG, PNG, GIF ali WebP, vrne pravilno končnico datoteke.
 
+.[caution]
+Zahteva razširitev PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Vrne ustrezno razširitev datoteke (brez pike), ki ustreza zaznani vrsti MIME.
+
+.[caution]
+Zahteva razširitev PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/sl/response.texy b/http/sl/response.texy
index 53c9ba207e..5241b31657 100644
--- a/http/sl/response.texy
+++ b/http/sl/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 Za razliko od [Nette\Http\Request |request] je ta objekt spremenljiv, zato lahko za spremembo stanja, tj. za pošiljanje glave, uporabite nastavitve. Ne pozabite, da je treba vse nastavljalnike **poklicati, preden se pošlje dejanski izhod.** Metoda `isSent()` pove, ali je bil izhod poslan. Če vrne `true`, vsak poskus pošiljanja glave vrže izjemo `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Spremeni [odzivno kodo |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] stanja. Za boljšo berljivost izvorne kode je priporočljivo uporabljati [vnaprej določene konstante |api:Nette\Http\IResponse] namesto dejanskih številk.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Pošlje glavo `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Pošlje piškotek. Privzete vrednosti parametrov:
 
 | `$path` | `'/'` | s področjem uporabe za vse poti v (pod)domeni *(nastavljivo)*
@@ -138,8 +138,8 @@ Možnost `$domain` določa, katere domene (izvori) lahko sprejmejo piškotke. Č
 Za vrednost `$sameSite` lahko uporabite konstante `Response::SameSiteLax`, `SameSiteStrict` in `SameSiteNone`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Izbriše piškotek. Privzete vrednosti parametrov so:
 - `$path` s področjem uporabe za vse imenike (`'/'`)
 - `$domain` s področjem uporabe trenutne (pod)domene, vendar ne njenih poddomen
diff --git a/http/sl/sessions.texy b/http/sl/sessions.texy
index 5ed29e881a..8841a6c352 100644
--- a/http/sl/sessions.texy
+++ b/http/sl/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Nastavi čas neaktivnosti, po katerem se seja izteče.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Nastavi parametre za piškotke. Privzete vrednosti parametrov lahko spremenite v [konfiguraciji |configuration#Session cookie].
 
 
diff --git a/http/sl/urls.texy b/http/sl/urls.texy
index 03f088eed4..90e7305095 100644
--- a/http/sl/urls.texy
+++ b/http/sl/urls.texy
@@ -62,6 +62,8 @@ Za pridobivanje ali spreminjanje posameznih komponent URL so na voljo naslednje
 | | `getHostUrl(): string`| `http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | polni URL
 
+Opozorilo: Pri delu z URL-jem, pridobljenim z [zahtevo HTTP |request], upoštevajte, da ne bo vseboval fragmenta, saj ga brskalnik ne pošlje strežniku.
+
 S posameznimi parametri poizvedbe lahko operiramo tudi z uporabo:
 
 .[language-php]
diff --git a/http/tr/request.texy b/http/tr/request.texy
index 75192ba3e4..2033fe4790 100644
--- a/http/tr/request.texy
+++ b/http/tr/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Tarayıcılar sunucuya bir parça göndermez, bu nedenle `$url->getFragment()` boş bir dize döndürür.
+Uyarı: Tarayıcılar sunucuya bir parça göndermez, bu nedenle `$url->getFragment()` boş bir dize döndürecektir.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 GET istek parametrelerini döndürür:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // GET parametresi 'id' (veya null) döndür
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 POST istek parametrelerini döndürür:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-Kullanıcı hangi URL'den geldi? Dikkat edin, hiç güvenilir değil.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Bağlantı şifreli mi (HTTPS)? Düzgün işlevsellik için [bir proxy ayarlamanız |configuration#HTTP proxy] gerekebilir.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Temizlenmiş dosya adını döndürür. Yalnızca ASCII karakterleri içerir `[a-zA-Z0-9.-]`. Ad bu tür karakterler içermiyorsa, 'bilinmeyen' döndürür. Dosya JPEG, PNG, GIF veya WebP görüntüsüyse, doğru dosya uzantısını döndürür.
 
+.[caution]
+PHP uzantısı gerektirir `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Algılanan MIME türüne karşılık gelen uygun dosya uzantısını (nokta olmadan) döndürür.
+
+.[caution]
+PHP uzantısı gerektirir `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/tr/response.texy b/http/tr/response.texy
index e0811471fc..4859af5e87 100644
--- a/http/tr/response.texy
+++ b/http/tr/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Yanıt .[#toc-nette-http-response]
  [Nette\Http\Request |request]'in aksine, bu nesne değişkendir, bu nedenle durumu değiştirmek, yani başlıkları göndermek için ayarlayıcıları kullanabilirsiniz. Tüm ayarlayıcıların **gerçek çıktı gönderilmeden önce çağrılması gerektiğini unutmayın.** `isSent()` yöntemi çıktının gönderilip gönderilmediğini söyler. Eğer `true` döndürürse, her başlık gönderme girişimi bir `Nette\InvalidStateException` istisnası fırlatır.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Bir durum [yanıt kodunu |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] değiştirir. Daha iyi kaynak kodu okunabilirliği için gerçek sayılar yerine [önceden tanımlanmış sabitlerin |api:Nette\Http\IResponse] kullanılması önerilir.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 `Content-Type` başlığını gönderir.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Bir çerez gönderir. Varsayılan parametre değerleri:
 
 | `$path` | `'/'` | (alt)etki alanı *(yapılandırılabilir)* üzerindeki tüm yolların kapsamı ile
@@ -138,8 +138,8 @@ $httpResponse->setCookie('lang', 'en', '100 days');
 `$sameSite` değeri için `Response::SameSiteLax`, `SameSiteStrict` ve `SameSiteNone` sabitlerini kullanabilirsiniz.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Bir çerezi siler. Parametrelerin varsayılan değerleri şunlardır:
 - `$path` tüm dizinleri kapsayacak şekilde (`'/'`)
 - `$domain` geçerli (alt) etki alanının kapsamı ile, ancak alt etki alanları ile değil
diff --git a/http/tr/sessions.texy b/http/tr/sessions.texy
index f7e7a1450c..959f4d842e 100644
--- a/http/tr/sessions.texy
+++ b/http/tr/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Oturumun sona ereceği hareketsizlik süresini ayarlar.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Çerezler için parametreleri ayarlar. Varsayılan parametre değerlerini [configuration#Session cookie |configuration#Session cookie] bölümünden değiştirebilirsiniz.
 
 
diff --git a/http/tr/urls.texy b/http/tr/urls.texy
index 2cf4fe5d8b..46a2cfb5c1 100644
--- a/http/tr/urls.texy
+++ b/http/tr/urls.texy
@@ -62,6 +62,8 @@ Tek tek URL bileşenlerini almak veya değiştirmek için aşağıdaki yöntemle
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | tam URL
 
+Uyarı: Bir [HTTP isteğinden |request] elde edilen bir URL ile çalışırken, tarayıcı bunu sunucuya göndermediği için parçayı içermeyeceğini unutmayın.
+
 Ayrıca tek tek sorgu parametreleri ile de işlem yapabiliriz:
 
 .[language-php]
diff --git a/http/uk/request.texy b/http/uk/request.texy
index f35c32a2fe..ccb3342e4b 100644
--- a/http/uk/request.texy
+++ b/http/uk/request.texy
@@ -32,11 +32,11 @@ echo $url; // https://nette.org/en/documentation?action=edit
 echo $url->getHost(); // nette.org
 ```
 
-Браузери не надсилають фрагмент на сервер, тому `$url->getFragment()` поверне порожній рядок.
+Попередження: Браузери не надсилають фрагмент на сервер, тому `$url->getFragment()` поверне порожній рядок.
 
 
-getQuery(string $key=null): string|array|null .[method]
--------------------------------------------------------
+getQuery(?string $key=null): string|array|null .[method]
+--------------------------------------------------------
 Повертає параметри GET-запиту:
 
 ```php
@@ -45,8 +45,8 @@ $id = $httpRequest->getQuery('id'); // повертає GET-параметр 'id
 ```
 
 
-getPost(string $key=null): string|array|null .[method]
-------------------------------------------------------
+getPost(?string $key=null): string|array|null .[method]
+-------------------------------------------------------
 Повертає параметри POST-запиту:
 
 ```php
@@ -141,11 +141,6 @@ echo $headers['Content-Type'];
 ```
 
 
-getReferer(): ?Nette\Http\UrlImmutable .[method]
-------------------------------------------------
-З якого URL прийшов користувач? Остерігайтеся, це зовсім не надійно.
-
-
 isSecured(): bool .[method]
 ---------------------------
 Чи зашифровано з'єднання (HTTPS)? Можливо, вам буде потрібно налаштувати [проксі-сервер |configuration#HTTP-Proxy] для правильної роботи.
@@ -357,6 +352,17 @@ getSanitizedName(): string .[method]
 ------------------------------------
 Повертає саніроване ім'я файлу. Воно містить тільки символи ASCII `[a-zA-Z0-9.-]`. Якщо ім'я не містить таких символів, повертається 'unknown'. Якщо файл є зображенням JPEG, PNG, GIF або WebP, повертається правильне розширення файлу.
 
+.[caution]
+Потрібне розширення PHP `fileinfo`.
+
+
+getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
+--------------------------------------------------------------
+Повертає відповідне розширення файлу (без крапки), що відповідає виявленому MIME-типу.
+
+.[caution]
+Вимагає розширення PHP `fileinfo`.
+
 
 getUntrustedFullPath(): string .[method]
 ----------------------------------------
diff --git a/http/uk/response.texy b/http/uk/response.texy
index b0bbc815ff..d99aa00be1 100644
--- a/http/uk/response.texy
+++ b/http/uk/response.texy
@@ -15,8 +15,8 @@ Nette\Http\Response .[#toc-nette-http-response]
 На відміну від [Nette\Http\Request |request], цей об'єкт є змінюваним, тому ви можете використовувати сеттери для зміни стану, тобто для надсилання заголовків. Пам'ятайте, що всі сеттери **повинні бути викликані до того, як буде надіслано фактичні дані.** Метод `isSent()` визначає, чи було надіслано дані. Якщо він повертає `true`, кожна спроба надіслати заголовок спричиняє виключення `Nette\InvalidStateException`.
 
 
-setCode(int $code, string $reason=null) .[method]
--------------------------------------------------
+setCode(int $code, ?string $reason=null) .[method]
+--------------------------------------------------
 Змінює [код відповіді |https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10] статусу. Для кращої читабельності вихідного коду рекомендується використовувати [зумовлені константи |api:Nette\Http\IResponse] замість реальних чисел.
 
 ```php
@@ -77,8 +77,8 @@ echo $headers['Pragma'];
 ```
 
 
-setContentType(string $type, string $charset=null) .[method]
-------------------------------------------------------------
+setContentType(string $type, ?string $charset=null) .[method]
+-------------------------------------------------------------
 Надсилає заголовок `Content-Type`.
 
 ```php
@@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf');
 ```
 
 
-setCookie(string $name, string $value, $time, string $path=null, string $domain=null, bool $secure=null, bool $httpOnly=null, string $sameSite=null) .[method]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
+setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method]
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Надсилає cookie. Значення параметрів за замовчуванням:
 
 | `$path` | `'/'` | з охопленням усіх шляхів на (під)домені *(налаштовується)*.
@@ -138,8 +138,8 @@ $httpResponse->setCookie('lang', 'en', '100 days');
 Для значення `$sameSite` можна використовувати константи `Response::SameSiteLax`, `SameSiteStrict` і `SameSiteNone`.
 
 
-deleteCookie(string $name, string $path=null, string $domain=null, bool $secure=null): void .[method]
------------------------------------------------------------------------------------------------------
+deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method]
+--------------------------------------------------------------------------------------------------------
 Видаляє файл cookie. За замовчуванням параметри мають такі значення:
 - `$path` з областю дії на всі каталоги (`'/'`)
 - `$domain` з областю дії на поточний (під)домен, але не на його піддомени.
diff --git a/http/uk/sessions.texy b/http/uk/sessions.texy
index e7419dbbec..9f789f951e 100644
--- a/http/uk/sessions.texy
+++ b/http/uk/sessions.texy
@@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method]
 Встановлює час бездіяльності, після якого сесія завершується.
 
 
-setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
-------------------------------------------------------------------------------------------------------------------
+setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method]
+---------------------------------------------------------------------------------------------------------------------
 Встановлює параметри для кукі. Значення параметрів за замовчуванням можна змінити в розділі [configuration |configuration#Session-Cookie].
 
 
diff --git a/http/uk/urls.texy b/http/uk/urls.texy
index c3d2f12605..0a2df8960a 100644
--- a/http/uk/urls.texy
+++ b/http/uk/urls.texy
@@ -62,6 +62,8 @@ $url = new Url(
 | | `getHostUrl(): string`| `'http://nette.org:8080'`
 | | `getAbsoluteUrl(): string` | повний URL
 
+Попередження: Працюючи з URL-адресою, отриманою з [HTTP-запиту |request], майте на увазі, що вона не міститиме фрагмент, оскільки браузер не надсилає його на сервер.
+
 Ми також можемо працювати з окремими параметрами запиту, використовуючи:
 
 .[language-php]
diff --git a/latte/bg/@left-menu.texy b/latte/bg/@left-menu.texy
index eaeb13b43f..c490a5efbb 100644
--- a/latte/bg/@left-menu.texy
+++ b/latte/bg/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Започване на работа |Guide]
 - [Защо да използвате шаблони? |why-use]
-- Концепции
+- Концепции ⚗️
 	- [Безопасността на първо място |Safety First]
 	- [Наследяване на шаблона |Template Inheritance]
 	- [Тип система |Type System]
 	- [Пясъчник |Sandbox]
 
-- За дизайнери
+- За дизайнери 🎨
 	- [Синтаксис |Syntax]
 	- [Етикети |Tags]
 	- [Филтри |Filters]
 	- [Функции |Functions]
 	- [Съвети и трикове |recipes]
 
-- За разработчици
+- За разработчици 🧮
 	- [Практически съвети за разработчици |develop]
 	- [Удължаване на Latte |Extending Latte]
 	- [Създаване на разширение |creating-extension]
 
-- [Готварска книга |cookbook/@home]
+- [Готварска книга 💡|cookbook/@home]
 	- [Миграция от Twig |cookbook/migration-from-twig]
 	- ... [повече |cookbook/@home]
 
diff --git a/latte/bg/cookbook/@home.texy b/latte/bg/cookbook/@home.texy
index 8d6307deee..47f1d68381 100644
--- a/latte/bg/cookbook/@home.texy
+++ b/latte/bg/cookbook/@home.texy
@@ -4,7 +4,9 @@
 .[perex]
 Примерни кодове и рецепти за изпълнение на често срещани задачи с Latte.
 
-- [Всичко, което винаги сте искали да знаете за {iterateWhile} |iteratewhile]
+- [Насоки за разработчици |/develop]
+- [Предаване на променливи между шаблони |passing-variables]
+- [Всичко, което винаги сте искали да знаете за групирането |grouping]
 - [Как се пишат SQL заявки в Latte |how-to-write-sql-queries-in-latte]?
 - [Миграция от PHP |migration-from-php]
 - [Миграция с Twig |migration-from-twig]
diff --git a/latte/bg/cookbook/grouping.texy b/latte/bg/cookbook/grouping.texy
new file mode 100644
index 0000000000..fac2fd662e
--- /dev/null
+++ b/latte/bg/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Всичко, което винаги сте искали да знаете за групирането
+********************************************************
+
+.[perex]
+Когато работите с данни в шаблони, често се сблъсквате с необходимостта да ги групирате или да ги показвате конкретно по определени критерии. За тази цел Latte предлага няколко мощни инструмента.
+
+Филтърът и функцията `|group` позволяват ефективно групиране на данните въз основа на определени критерии, докато филтърът `|batch` улеснява разделянето на данните на фиксирани партиди, а етикетът `{iterateWhile}` предоставя възможност за по-сложен контрол на циклите с условия.
+Всеки от тези тагове предлага специфични възможности за работа с данни, което ги прави незаменими инструменти за динамично и структурирано показване на информация в шаблоните Latte.
+
+
+Филтър и функция `group` .[#toc-filter-and-function-group]
+==========================================================
+
+Представете си таблица от базата данни `items` с елементи, разделени на категории:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Apple
+| 2 | 1 | Банан
+| 3 | 2 | PHP
+| 4 | 3 | Зелен
+| 5 | 3 | Червено
+| 6 | 3 | Синьо
+
+Един прост списък на всички елементи, използващ шаблон Latte, би изглеждал така:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Ако обаче искаме елементите да бъдат организирани в групи по категории, трябва да ги разделим така, че всяка категория да има собствен списък. Тогава резултатът би изглеждал така:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Задачата може да бъде решена лесно и елегантно с помощта на `|group`. Посочваме `categoryId` като параметър, което означава, че елементите ще бъдат разделени на по-малки масиви въз основа на стойността на `$item->categoryId` (ако `$item` беше масив, щяхме да използваме `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Филтърът може да се използва и като функция в Latte, което ни дава алтернативен синтаксис: `{foreach group($items, categoryId) ...}`.
+
+Ако искате да групирате елементи по по-сложни критерии, можете да използвате функция в параметъра на филтъра. Например, групирането на елементи по дължината на името им ще изглежда по следния начин:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Важно е да се отбележи, че `$categoryItems` не е обикновен масив, а обект, който се държи като итератор. За да получите достъп до първия елемент в групата, можете да използвате [`first()` |latte:functions#first] функция.
+
+Тази гъвкавост при групирането на данни прави `group` изключително полезен инструмент за представяне на данни в шаблони Latte.
+
+
+Вложени цикли .[#toc-nested-loops]
+----------------------------------
+
+Да кажем, че имаме таблица в базата данни с още една колона `subcategoryId`, която определя подкатегории за всеки елемент. Искаме да покажем всяка основна категория в отделна `<ul>` списък и всяка подкатегория в отделен вложен цикъл `<ol>` списък:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Връзка с базата данни Nette .[#toc-connection-with-nette-database]
+------------------------------------------------------------------
+
+Нека да покажем как ефективно да използваме групирането на данни в комбинация с Nette Database. Да предположим, че работим с таблицата `items` от първоначалния пример, която е свързана чрез колоната `categoryId` с тази таблица `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Fruits |
+| 2 | Езици |
+| 3 | Цветове |
+
+Зареждаме данни от таблицата `items`, като използваме командата на Nette Database Explorer `$items = $db->table('items')`. По време на итерацията над тези данни имаме възможност не само за достъп до атрибути като `$item->name` и `$item->categoryId`, но благодарение на връзката с таблицата `categories` и до свързания ред в нея чрез `$item->category`. Тази връзка може да демонстрира интересни приложения:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+В този случай използваме филтъра `|group`, за да групираме по свързания ред `$item->category`, а не само по колоната `categoryId`. Това ни дава `ActiveRow` на дадената категория в променливата ключ, което ни позволява директно да покажем нейното име с помощта на `{$category->name}`. Това е практически пример за това как групирането може да опрости шаблоните и да улесни обработката на данни.
+
+
+Филтър `|batch` .[#toc-filter-batch]
+====================================
+
+Филтърът ви позволява да разделите списък от елементи на групи с предварително определен брой елементи. Този филтър е идеален за ситуации, в които искате да представите данните в няколко по-малки групи, например за по-добра яснота или визуална организация на страницата.
+
+Представете си, че имаме списък с елементи и искаме да ги покажем в списъци, всеки от които съдържа максимум три елемента. Използването на филтъра `|batch` е много практично в такъв случай:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+В този пример списъкът `$items` е разделен на по-малки групи, като всяка група (`$batch`) съдържа до три елемента. След това всяка група се показва в отделен `<ul>` списък.
+
+Ако последната група не съдържа достатъчно елементи, за да се достигне желаният брой, вторият параметър на филтъра ви позволява да определите с какво ще бъде допълнена тази група. Това е идеално за естетическо подравняване на елементи, при които непълен ред може да изглежда безредно.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Етикет `{iterateWhile}` .[#toc-tag-iteratewhile]
+================================================
+
+Ще демонстрираме същите задачи, които разгледахме с филтъра `|group`, като използваме тага `{iterateWhile}`. Основната разлика между двата подхода е, че `group` първо обработва и групира всички входни данни, докато `{iterateWhile}` контролира хода на циклите с условия, така че итерацията се извършва последователно.
+
+Първо, съставяме таблица с категории, като използваме iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Докато тагът `{foreach}` маркира външната част на цикъла, т.е. изготвянето на списъци за всяка категория, тагът `{iterateWhile}` маркира вътрешната част, т.е. отделните елементи.
+Условието в тага end казва, че повторението ще продължи, докато текущият и следващият елемент принадлежат към една и съща категория (`$iterator->nextValue` е [следващият елемент |/tags#$iterator]).
+
+Ако условието беше винаги изпълнено, всички елементи щяха да бъдат изведени във вътрешния цикъл:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Резултатът ще изглежда така:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Каква е употребата на iterateWhile по този начин? Когато таблицата е празна и не съдържа никакви елементи, няма празни `<ul></ul>` се отпечатва.
+
+Ако укажем условието в отварящия таг `{iterateWhile}`, поведението се променя: условието (и преходът към следващия елемент) се изпълнява в началото на вътрешния цикъл, а не в края.
+По този начин, докато винаги въвеждате `{iterateWhile}` без условия, въвеждате `{iterateWhile $cond}` само когато е изпълнено условието `$cond`. И в същото време следващият елемент се записва в `$item`.
+
+Това е полезно например в ситуация, в която искаме да визуализираме първия елемент във всяка категория по различен начин, например по следния начин:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Модифицираме оригиналния код така, че първо да визуализираме първия елемент, а след това във вътрешния цикъл `{iterateWhile}` да визуализираме останалите елементи от същата категория:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+В рамките на един цикъл можем да създадем няколко вътрешни цикъла и дори да ги вложим. По този начин могат да се групират подкатегории, например.
+
+Да предположим, че таблицата има още една колона `subcategoryId`, и освен че всяка категория е в отделна `<ul>`, всяка подкатегория в отделна `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/bg/cookbook/iteratewhile.texy b/latte/bg/cookbook/iteratewhile.texy
deleted file mode 100644
index fb75a5acf3..0000000000
--- a/latte/bg/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Всичко, което винаги сте искали да знаете за {iterateWhile}
-***********************************************************
-
-.[perex]
-Тагът `{iterateWhile}` е подходящ за различни трикове в цикли foreach.
-
-Да предположим, че имаме следната таблица в базата данни, в която елементите са разделени на категории:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Разбира се, много е лесно да изведете елементите в цикъла foreach като списък:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Но какво да направите, ако искате да изведете всяка категория като отделен списък? С други думи, как се решава проблемът с групирането на елементи от линеен списък в цикъл foreach. Резултатът трябва да изглежда така:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Ще ви покажем как да решите този проблем лесно и елегантно с помощта на iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Докато `{foreach}` се отнася до външната част на цикъла, т.е. изготвянето на списъци за всяка категория, таговете `{iterateWhile}` се отнасят до вътрешната част, т.е. отделните елементи.
-Условието в крайния таг гласи, че повторението ще продължи, докато текущият и следващият елемент принадлежат към една и съща категория (`$iterator->nextValue` - [следващ елемент |/tags#iterator]).
-
-Ако условието е винаги изпълнено, всички елементи се изтеглят във вътрешния цикъл:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Резултатът ще изглежда по следния начин:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Как е полезно да се използва iterateWhile по този начин? По какво се различава от решението, което показахме в началото на това ръководство? Разликата е, че ако таблицата е празна и не съдържа елементи, тя няма да се изведе празна `<ul></ul>`.
-
-
-Решение без `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-------------------------------------------------------------------
-
-Ако трябва да решим същия проблем, като използваме напълно елементарни шаблони, например в Twig, Blade или чист PHP, решението би изглеждало по следния начин
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-Този код обаче е неразбираем и неинтуитивен. Връзката между началния и крайния HTML таг не е съвсем ясна. От пръв поглед не е ясно дали има грешка. А това изисква помощни променливи като `$prevCatId`.
-
-За разлика от това решението с `{iterateWhile}` е чисто, ясно, не изисква помощни променливи и е надеждно.
-
-
-Условие в затварящия таг .[#toc-condition-in-the-closing-tag]
--------------------------------------------------------------
-
-Ако посочите условие в отварящия таг `{iterateWhile}`, поведението се променя: условието (и преходът към следващия елемент) се изпълнява в началото на вътрешния цикъл, а не в края.
-Така, докато `{iterateWhile}` без условие се въвежда винаги, `{iterateWhile $cond}` се въвежда само когато е изпълнено условието `$cond`. В същото време следващият елемент се записва в `$item`.
-
-Това е полезно например в ситуация, в която първият елемент във всяка категория трябва да се показва по различен начин, напр:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Променете изходния код, като визуализираме първия елемент и след това допълнителни елементи от същата категория във вътрешния цикъл `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Вложени цикли .[#toc-nested-loops]
-----------------------------------
-
-Можем да създадем няколко вътрешни цикъла в един цикъл и дори да ги вложим един в друг. По този начин например подкатегориите могат да бъдат групирани заедно.
-
-Да предположим, че в таблицата има още една колона `subCatId` и освен че всяка категория е в отделна колона, всяка подкатегория ще бъде в отделна колона. `<ul>`, всяка подкатегория ще бъде в отделна колона. `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Филтриране | партида .[#toc-filter-batch]
------------------------------------------
-
-Групирането на елементите на реда се осигурява и от филтъра `batch`, в партида с фиксиран брой елементи:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Тя може да бъде заменена с iterateWhile, както следва:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/bg/cookbook/passing-variables.texy b/latte/bg/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..c328bf8e4e
--- /dev/null
+++ b/latte/bg/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Предаване на променливи между шаблони
+*************************************
+
+Това ръководство обяснява как се предават променливи между шаблони в Latte с помощта на различни тагове, като например `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` и други. Ще научите също как да работите с променливи в таговете `{block}` и `{define}`, както и за какво служи тагът `{parameters}`.
+
+
+Видове променливи .[#toc-types-of-variables]
+--------------------------------------------
+Променливите в Latte могат да бъдат разделени на три категории в зависимост от това как и къде са дефинирани:
+
+**Входни променливи** са тези, които се предават на шаблона отвън, например от PHP скрипт или с помощта на таг като `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Окръжаващи променливи** са променливи, съществуващи в местоположението на определен таг. Те включват всички входни променливи и други променливи, създадени с помощта на тагове като `{var}`, `{default}`, или в рамките на цикъл `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Експлицитни променливи** са тези, които са директно посочени в рамките на даден таг и са изпратени към целевия шаблон.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Тагът `{block}` се използва за дефиниране на блокове код за многократна употреба, които могат да бъдат персонализирани или разширени в наследени шаблони. Обкръжаващите променливи, дефинирани преди блока, са достъпни вътре в блока, но всички промени в променливите се отразяват само в рамките на този блок.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Тагът `{define}` се използва за създаване на блокове, които се визуализират само при извикване с помощта на `{include}`. Променливите, които са на разположение вътре в тези блокове, зависят от това дали в дефиницията са посочени параметри. Ако са посочени параметри, достъпни са само тези параметри. Ако това не е така, всички входни променливи на шаблона, в който са дефинирани блоковете, са достъпни.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Тагът `{parameters}` се използва за изрично деклариране на очакваните входни променливи в началото на шаблона. По този начин можете лесно да документирате очакваните променливи и техните типове данни. Възможно е също така да се дефинират стойности по подразбиране.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Тагът `{include file}` се използва за вмъкване на цял шаблон. На този шаблон се предават както входните променливи на шаблона, в който се използва тагът, така и изрично дефинирани променливи. Въпреки това целевият шаблон може да ограничи обхвата с помощта на `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+При вмъкване на блок, дефиниран в същия шаблон, всички заобикалящи го и изрично дефинирани променливи се предават към него:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+В този пример променливите `$name` и `$age` се предават на блока `blockName`. Същото поведение се прилага и за `{include parent}`.
+
+При вмъкване на блок от друг шаблон се предават само входни променливи и изрично дефинирани променливи. Обкръжаващите променливи не са достъпни автоматично.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` или `{extends}`
+--------------------------
+Тези тагове определят оформление, към което се предават входните променливи на подчинения шаблон и променливите, създадени в кода преди блоковете:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Шаблон `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Тагът `{embed}` е подобен на тага `{include}`, но позволява вграждане на блокове в шаблона. За разлика от `{include}`, се предават само изрично декларирани променливи:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+В този пример шаблонът `menu.latte` има достъп само до променливата `$items`.
+
+Обратно, блоковете вътре в `{embed}` имат достъп до всички околни променливи:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Тагът `{import}` се използва за зареждане на блокове от други шаблони. Към импортираните блокове се предават както входни, така и изрично декларирани променливи.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Тагът `{sandbox}` изолира шаблона за безопасна обработка. Променливите се предават изключително изрично.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/bg/creating-extension.texy b/latte/bg/creating-extension.texy
index f9cdb80533..3091394103 100644
--- a/latte/bg/creating-extension.texy
+++ b/latte/bg/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// функция за парсиране, която засега просто създава възел
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Ако създавате нов таг за Latte, препоръчително е да създадете за него специален клас възел, който ще го представя в дървото AST (вж. класа `ForeachNode` в примера по-горе). В някои случаи може да ви бъде полезен тривиалният помощен клас [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], който ви позволява да предадете тялото на метода `print()` и списъка на възлите, направени достъпни от метода `getIterator()`, като параметри на конструктора:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Компилаторът предава .[#toc-compiler-passes]
 ============================================
 
diff --git a/latte/bg/develop.texy b/latte/bg/develop.texy
index e947567ea5..1dd39d2d2f 100644
--- a/latte/bg/develop.texy
+++ b/latte/bg/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Местоположение .[#toc-locale]{data-version:3.0.18}
+==================================================
+
+Latte ви позволява да зададете локала, който влияе на форматирането на числата, датите и сортирането. Той се задава чрез метода `setLocale()`. Идентификаторът на локала следва стандарта за езикови маркери на IETF, който използва разширението на PHP `intl`. Той се състои от код на езика и евентуално от код на страната, например `en_US` за английски език в САЩ, `de_DE` за немски език в Германия и т.н.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Настройката на локала влияе на филтрите [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] и [bytes |filters#bytes].
+
+.[note]
+Изисква разширението PHP `intl`. Настройката в Latte не влияе на глобалната настройка на локала в PHP.
+
+
 Строг режим .[#toc-strict-mode]{data-version:3.0.8}
 ===================================================
 
@@ -274,16 +290,25 @@ vendor/bin/latte-lint <path>
 // въведете действителния път до файла autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// добавете отделни разширения тук
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// добавете индивидуалните си разширения тук
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Като алтернатива можете да предадете свой собствен обект `Latte\Engine` на Linter:
+
+```php
+$latte = new Latte\Engine;
+// тук конфигурираме обекта $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Зареждане на шаблони от низ .[#toc-loading-templates-from-a-string]
 ===================================================================
diff --git a/latte/bg/extending-latte.texy b/latte/bg/extending-latte.texy
index d156b9e5bb..12bbe4f051 100644
--- a/latte/bg/extending-latte.texy
+++ b/latte/bg/extending-latte.texy
@@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 
 Разбира се, функцията, представляваща филтъра, може да приема произволен брой параметри, като се поддържат и променливи параметри.
 
+Ако филтърът връща низ в HTML, можете да го маркирате така, че Latte да не го ескапира автоматично (и следователно двойно). По този начин се избягва необходимостта от задаване на `|noescape` в шаблона.
+Най-лесният начин е да обвиете низа в обект `Latte\Runtime\Html`, а другият начин е [Контекстни филтри |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+В този случай филтърът трябва да осигури правилно извеждане на данните.
+
 
 Филтри, които използват класа .[#toc-filters-using-the-class]
 -------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// променете типа на съдържанието на HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/bg/filters.texy b/latte/bg/filters.texy
index 6283bf3c42..4a5f91bdc4 100644
--- a/latte/bg/filters.texy
+++ b/latte/bg/filters.texy
@@ -11,14 +11,16 @@
 | `bytes` | [форматира размера в байтове |#bytes]
 | `clamp` | [ограничава стойността до определен диапазон |#clamp]
 | `dataStream` | [Конвертиране на протокола за данни URI |#dataStream]
-| `date` | [форматиране на датата |#date]
+| `date` | [форматиране на датата и часа |#date]
 | `explode` | [разделя низа с даден разделител |#explode]
-| `first` [връща първия елемент на масив или символен низ |#first]
+| `first` | [връща първия елемент на масив или символен низ |#first]
+| `group` | [групиране на данни по различни критерии |#group]
 | `implode` | [свързва масива с низ |#implode]
 | `indent` | [отстъпи на текста наляво с броя на табулаторите |#indent]
 | `join` | [обединяване на масив в низ |#implode]
 | `last` | [връща последния елемент на масив или символен низ |#last]
 | `length` | [връща дължината на низ или масив |#length]
+| `localDate` | [форматиране на датата и часа в съответствие с местността |#localDate]
 | `number` | [форматира число |#number]
 | `padLeft` | [допълва низа вляво |#padLeft]
 | `padRight` | [допълва низа до зададена дължина надясно |#padRight]
@@ -118,8 +120,8 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Филтър, който опростява изписването на линейни данни под формата на таблица. Връща масив от масиви със зададения брой елементи. Ако предоставите втори параметър, той се използва за попълване на липсващите елементи на последния ред.
 
 ```latte
@@ -152,6 +154,8 @@ batch(int length, mixed item): array .[filter]
 </table>
 ```
 
+Вижте също таговете [group |#group] и [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ breakLines .[filter]
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Форматира размера в байтове в удобна за четене от човека форма.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Форматира размера в байтове в удобна за четене от човека форма. Ако е зададена [локална среда |develop#locale], се използват съответните десетични и хилядни разделители.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ bytes(int precision = 2) .[filter]
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Закръгляне на число до зададена точност.
 
 ```latte
@@ -203,8 +207,8 @@ checkUrl .[filter]
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Отпечатва:
@@ -217,8 +221,8 @@ checkUrl .[filter]
 Вижте също [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Връща стойността, която е вкарана в обхват от min и max.
 
 ```latte
@@ -228,14 +232,14 @@ clamp(int|float min, int|float max) .[filter]
 Съществува и като [clamp |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Конвертира съдържанието в схема URI за данни. Може да се използва за вмъкване на изображения в HTML или CSS, без да е необходимо да се свързват външни файлове.
 
 Нека имаме изображение в променлива `$img = Image::fromFile('obrazek.gif')`, тогава
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Отпечатва например:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Изисква PHP разширение `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Връща дата в зададен формат, като използва опциите на функциите [php:strftime] или [php:date] на PHP. Филтърът получава датата като времеви печат на UNIX, низ или обект от тип `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Форматира датата и часа в съответствие с маската, използвана от функцията на PHP [php:date]. Филтърът приема датата във формат UNIX timestamp, като низ или като обект `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Вижте също [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ escapeUrl .[filter]
 Вижте също [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Разделя низ по зададения разделител и връща масив от низове. Псевдоним за `split`.
 
 ```latte
@@ -306,8 +311,8 @@ first .[filter]
 Вижте също [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Закръгляне на число до зададена точност.
 
 ```latte
@@ -330,8 +335,27 @@ firstUpper .[filter]
 Вижте също [capitalize |#capitalize], [lower |#lower], [upper |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Филтърът групира данните по различни критерии.
+
+В този пример редовете в таблицата са групирани по колоната `categoryId`. Изходът е масив от масиви, където ключът е стойността в колоната `categoryId`. Прочетете [подробните инструкции |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Вижте също [batch |#batch], функцията [group |functions#group] и маркера [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Връща низ, който е конкатенация на низовете в масива. Псевдоним за `join`.
 
 ```latte
@@ -346,8 +370,8 @@ implode(string glue = '') .[filter]
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Отстъпва текста отляво с даден брой табулации или други символи, които посочваме във втория незадължителен аргумент. Празните редове не се отдръпват.
 
 ```latte
@@ -396,6 +420,68 @@ length .[filter]
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Форматира датата и часа в зависимост от [локала, |develop#locale] като осигурява последователно и локализирано показване на данните за времето на различни езици и региони. Филтърът приема датата като времеви печат на UNIX, низ или обект `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Ако използвате филтъра без никакви параметри, той ще изведе датата на ниво дълъг формат, както е обяснено по-нататък.
+
+**а) Използване на формата**
+
+Параметърът `format` описва кои компоненти на времето трябва да се показват. Той използва буквени кодове, при които броят на повторенията влияе на ширината на изхода:
+
+| Година | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Месец | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `08` / `август`
+| Ден | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `нд` / `неделя`
+| Час | `j` / `H` / `h` | предпочитан / 24-часов / 12-часов
+| Минута | `m` / `mm` | `5` / `05` <small>(2 цифри, когато се комбинира със секунди)</small>
+| Секунда | `s` / `ss` | `8` / `08` <small>(2 цифри, когато се комбинират с минути)</small>
+
+Редът на кодовете във формата няма значение, тъй като редът на компонентите ще бъде показан в съответствие с конвенциите на локала. Следователно форматът е независим от локала. Например, форматът `yyyyMMMMd` в локала `en_US` извежда `April 15, 2024`, докато в локала `cs_CZ` извежда `15. dubna 2024`:
+
+| locale:  | bg-BG | en_US
+|---
+| `format: 'dMy'` | 10.08.2024 г. | 8/10/2024
+| `format: 'yM'` | 08.2024 г. | 8/2024
+| `format: 'yyyyMMMM'` | август 2024 г. | August 2024
+| `format: 'MMMM'` | август | August
+| `format: 'jm'` | 17:54 ч. | 5:54 PM
+| `format: 'Hm'` | 17:54 ч. | 17:54
+| `format: 'hm'` | 5:54 ч. сл.об. | 5:54 PM
+
+
+**б) Използване на предварително зададени стилове**
+
+Параметрите `date` и `time` определят нивото на детайлност за показване на датата и часа. Можете да избирате от няколко нива: `full`, `long`, `medium`, `short`. Можете да показвате само датата, само часа или и двете:
+
+| locale:  | bg-BG | en_US
+|---
+| `date: short` | 23.01.78 г. | 1/23/78
+| `date: medium` | 23.01.1978 г. | Jan 23, 1978
+| `date: long` | 23 януари 1978 г. | January 23, 1978
+| `date: full` | понеделник, 23 януари 1978 г. | Monday, January 23, 1978
+| `time: short` | 8:30 ч. | 8:30 AM
+| `time: medium` | 8:30:59 ч. | 8:30:59 AM
+| `time: long` | 8:30:59 ч. Гринуич+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.78 г., 8:30 ч. | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23.01.1978 г., 8:30 ч. | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 януари 1978 г. в 8:30 ч. | January 23, 1978 at 8:30 AM
+
+За датата можете да използвате и префикса `relative-` (например `relative-short`), който за дати, близки до настоящата, ще покаже `yesterday`, `today` или `tomorrow`; в противен случай ще се покаже по стандартния начин.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Вижте също [дата |#date].
+
+
 lower .[filter]
 ---------------
 Преобразува стойността в малки букви. Изисква PHP разширение `mbstring`.
@@ -416,8 +502,8 @@ nocheck .[filter]
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Отпечатъци:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 Злоупотребата с филтъра `noescape` може да доведе до уязвимост XSS! Никога не го използвайте, освен ако не сте **напълно сигурни** какво правите и че низът, който отпечатвате, идва от надежден източник.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Форматира число до зададен брой знаци след десетичната запетая. Можете също така да зададете символ на десетичната запетая и разделителя за хиляди.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Форматира число до определен брой знаци след десетичната запетая. Ако е зададена [локална среда |develop#locale], се използват съответните разделители за десетични знаци и хиляди.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[fil
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Параметърът `format` ви позволява да определите външния вид на числата точно според вашите нужди. Той изисква зададена [локализация |develop#locale]. Форматът се състои от няколко специални знака, чието пълно описание можете да намерите в документацията на "DecimalFormat"::https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns
+
+- <c id=6/> задължителна цифра, която винаги се показва, дори ако е нула
+- `#` незадължителна цифра, показва се само ако числото има цифра на това място
+- `@` значима цифра, помага за показване на числото с определен брой значими цифри
+- `.` маркира мястото, където трябва да се намира десетичният разделител (запетая или точка, в зависимост от локала)
+- `,` се използва за разделяне на групи от цифри, обикновено хиляди
+- `%` умножава числото по 100 и добавя знака за процент
+
+Нека разгледаме някои примери. В първия пример двата знака след десетичната запетая са задължителни; във втория те не са задължителни. Третият пример показва попълване с нули от двете страни, а четвъртият показва само съществуващите цифри:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Значимите цифри определят колко цифри, независимо от десетичната запетая, трябва да бъдат показани, като при необходимост числото се закръгля:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Лесен начин за показване на дадено число като процент. Числото се умножава по 100 и се добавя знакът `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Можем да дефинираме различен формат за положителни и отрицателни числа, разделени със знака `;`. По този начин например положителните числа могат да се показват със знака `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Не забравяйте, че действителният вид на числата може да се различава в зависимост от настройките на локала. Например в някои страни като десетичен разделител се използва запетая вместо точка. Този филтър автоматично отчита това, така че не е необходимо да се притеснявате за него.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Попълва низ с определена дължина с друг низ отляво.
 
@@ -472,7 +606,7 @@ padLeft(int length, string pad = ' ') .[filter]
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Подвежда низ до определена дължина с друг низ отдясно.
 
@@ -514,8 +648,8 @@ random .[filter]
 Вижте също [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Повтаря символния низ х пъти.
 
 ```latte
@@ -523,7 +657,7 @@ repeat(int count) .[filter]
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Заменя всички срещания на търсения низ със заместващия низ.
 
@@ -538,7 +672,7 @@ replace(string|array search, string replace = '') .[filter]
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Заменя всички срещания според регулярен израз.
 
@@ -559,8 +693,8 @@ reverse .[filter]
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Закръгляне на число до зададена точност.
 
 ```latte
@@ -573,7 +707,7 @@ round(int precision = 0) .[filter]
 Вижте също [таван, |#ceil] [етаж |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Извлича част от масив или низ.
 
@@ -591,9 +725,9 @@ slice(int start, int length = null, bool preserveKeys = false) .[filter]
 По подразбиране Filter ще пренареди и нулира ключовете на целочислените масиви. Това поведение може да бъде променено чрез задаване на стойност preserveKeys на true. Ключовете на низове винаги се запазват, независимо от този параметър.
 
 
-sort  .[filter]
----------------
-Филтър, който сортира масив и поддържа асоциация на индексите.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Филтърът сортира елементите на масив или итератор, като запазва асоциативните им ключове. Когато е зададен [локал |develop#locale], сортирането следва неговите правила, освен ако не е зададена потребителска функция за сравнение.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ sort  .[filter]
 {/foreach}
 ```
 
-Можете да подадете своя собствена функция за сравнение като параметър:
+Можете да зададете потребителска функция за сравнение за сортиране (примерът показва как да обърнете сортирането от най-голям към най-малък):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Филтърът `|sort` също така ви позволява да сортирате елементите по ключ:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Ако трябва да сортирате таблица по определена колона, можете да използвате параметъра `by`. Стойността `'name'` в примера указва, че сортирането ще се извършва по `$row->name` или `$row['name']`, в зависимост от това дали `$row` е масив или обект:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Можете също така да дефинирате функция за обратно извикване, която определя стойността, по която да се сортира:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Параметърът `byKey` може да се използва по същия начин.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ stripHtml .[filter]
 Полученият обикновен текст естествено може да съдържа символи, които представляват HTML тагове, например `'&lt;p&gt;'|stripHtml` се преобразува в `<p>`. Никога не извеждайте получения текст с `|noescape`, тъй като това може да доведе до уязвимост на сигурността.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Извлича част от низ. Този филтър е заменен с филтър за [парчета |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ substr(int offset, int length = null) .[filter]
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Той превежда изрази на други езици. За да направите филтъра достъпен, трябва да настроите [преводач |develop#TranslatorExtension]. Можете също така да използвате [таговете за превод |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ translate(string message, ...args) .[filter]
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Премахване на водещи и завършващи символи, по подразбиране бяло пространство.
 
 ```latte
@@ -675,7 +835,7 @@ trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Съкращава даден низ до максимално зададената дължина, но се опитва да запази цели думи. Ако низът е съкратен, той добавя елипса в края (това може да се промени с втория параметър).
 
diff --git a/latte/bg/functions.texy b/latte/bg/functions.texy
index 7a0a686c97..7062cb2beb 100644
--- a/latte/bg/functions.texy
+++ b/latte/bg/functions.texy
@@ -9,6 +9,8 @@
 | `divisibleBy`| [проверява дали дадена променлива се дели на дадено число |#divisibleBy]
 | `even` | [проверява дали дадено число е четно число|#even]
 | `first` | [връща първия елемент на масив или символен низ |#first]
+| `group` | [групиране на данни по различни критерии |#group]
+| `hasBlock` | [открива съществуването на блок |#hasBlock]
 | `last` | [връща последния елемент на масив или символен низ|#last]
 | `odd` | [проверява дали числото е нечетно |#odd]
 | `slice` | [извлича фрагмент от масив или низ |#slice]
@@ -73,8 +75,8 @@ even(int $value): bool .[method]
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Връща първия елемент на масив или символен низ:
 
 ```latte
@@ -85,6 +87,36 @@ first(string|array $value): mixed .[method]
 Вижте също [последно |#last], [първо филтриране |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Тази функция групира данните по различни критерии.
+
+В този пример редовете в таблицата са групирани по колоната `categoryId`. Изходът е масив от полета, където ключът е стойността в колоната `categoryId`. Прочетете [подробните инструкции |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Вижте също филтърна [група |filters#group].
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Проверява дали блокът със зададеното име съществува:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Вижте също [проверка на съществуването на блока |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Връща последния елемент на масив или символен низ:
@@ -106,8 +138,8 @@ odd(int $value): bool .[method]
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Извлича фрагмент от масив или низ.
 
 ```latte
diff --git a/latte/bg/recipes.texy b/latte/bg/recipes.texy
index e0f1445d8c..d3659fc171 100644
--- a/latte/bg/recipes.texy
+++ b/latte/bg/recipes.texy
@@ -9,7 +9,7 @@
 
 - NetBeans IDE има вградена поддръжка за
 - PhpStorm: инсталирайте [приставката Latte |https://plugins.jetbrains.com/plugin/7457-latte] в `Settings > Plugins > Marketplace`
-- VS Code: намерете плъгина "Nette Latte + Neon" в маркерплей
+- VS код: търсене на маркерплейс за плъгин за [шаблони |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] или [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Sublime Text 3: в Управление на пакетите намерете и инсталирайте пакета `Nette` и изберете Latte в `View > Syntax`
 - в по-стари редактори използвайте Smarty за подчертаване на .latte файлове
 
diff --git a/latte/bg/safety-first.texy b/latte/bg/safety-first.texy
index 2693ba01f9..b8dca3c913 100644
--- a/latte/bg/safety-first.texy
+++ b/latte/bg/safety-first.texy
@@ -351,7 +351,7 @@ Latte автоматично проверява дали променливат
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Пише:
diff --git a/latte/bg/syntax.texy b/latte/bg/syntax.texy
index fe5dce9df2..b7406ed381 100644
--- a/latte/bg/syntax.texy
+++ b/latte/bg/syntax.texy
@@ -98,7 +98,7 @@ n:атрибути .[#toc-n-attributes]
 Или с префикс `tag-` функционалността се прилага само за HTML тагове:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 В зависимост от стойността на променливата `$url` ще бъде изведено следното:
@@ -155,6 +155,20 @@ Latte ви позволява да извиквате филтри със зна
 ```
 
 
+Динамични HTML етикети .[#toc-dynamic-html-tags]
+================================================
+
+Latte поддържа динамични HTML тагове, които са полезни, когато се нуждаете от гъвкавост в имената на таговете:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Например, кодът по-горе може да генерира `<h1>Heading</h1>` или `<h2>Heading</h2>` в зависимост от стойността на променливата `$level`. Динамичните HTML тагове в Latte трябва винаги да бъдат сдвоени. Тяхната алтернатива е [n:tag |tags#n:tag].
+
+Тъй като Latte е сигурна система за шаблониране, тя проверява дали полученото име на тага е валидно и не съдържа нежелани или злонамерени стойности. Тя също така гарантира, че името на крайния таг винаги е същото като името на началния таг.
+
+
 Коментарите са изключени за .[#toc-comments]
 ============================================
 
diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy
index 99e8382a9a..465a714616 100644
--- a/latte/bg/tags.texy
+++ b/latte/bg/tags.texy
@@ -16,6 +16,7 @@
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [условие ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [проверка за промени |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [състояние на превключване |#switch-case-default]
+| `n:else` | [алтернативно съдържание за условията |#n:else]
 
 .[table-latte-tags language-latte]
 |## Цикли
@@ -97,8 +98,8 @@
 | `{link}` |00 | [отпечатва връзка |application:creating-links#In-the-Presenter-Template]
 | `{plink}` | [отпечатва връзката към главния модул |application:creating-links#In-the-Presenter-Template]
 | `{control}` | [отпечатва компонент |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [откъс от шаблон, който може да бъде изпратен чрез AJAX |application:ajax#Tag-snippet]
-| `{snippetArea}` | плик за фрагмент
+| `{snippet}`... `{/snippet}` | [откъс от шаблон, който може да бъде изпратен чрез AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [плик за фрагмент |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [кеширане на секцията с шаблони |caching:#Caching-in-Latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@
 | `{input}` | [отпечатва елемента за влизане във формата|forms:rendering#label-input]
 | `{inputError}` | [отпечатва съобщението за грешка за елемента за въвеждане на форма |forms:rendering#inputError]
 | `n:name` [активира входния елемент на HTML |forms:rendering#n:name]
-| `{formPrint}` [генерира чертеж на формата Latte |forms:rendering#formPrint]
-| `{formPrintClass}` [отпечатва PHP клас за данните от формата |forms:in-presenter#Mapping-to-Classes]
-| `{formContext}`... `{/formContext}` | [Частично визуализиране на формата |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [визуализиране на контейнера за формуляри |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Age: {date('Y') - $birth}<br>
 Страхотно.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Ако запишете условието `{if} ... {/if}` под формата на [n:атрибут |syntax#n:attributes], имате възможност да посочите алтернативен клон, като използвате `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Атрибутът `n:else` може да се използва и в комбинация с [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], и [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Age: {date('Y') - $birth}<br>
 Използвайте условието `{ifset $var}`, за да определите дали дадена променлива (или няколко променливи) съществува и има ненулева стойност. Всъщност това е същото като `if (isset($var))` в PHP. Както всеки сдвоен таг, и този може да бъде записан като [n:attribute |syntax#n-attributes], затова нека го покажем с пример:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Lata е умен и `$iterator->last` работи не само за масив
 `{iterateWhile}`
 ----------------
 
-Опростява групирането на линейни данни по време на итерация в цикъл foreach чрез итерация във вложен цикъл, докато условието е изпълнено. [Прочетете инструкциите в книгата с рецепти |cookbook/iteratewhile].
+Опростява групирането на линейни данни по време на итерация в цикъл foreach чрез итерация във вложен цикъл, докато не бъде изпълнено дадено условие. [Прочетете подробните инструкции |cookbook/grouping].
 
 Той може също така елегантно да замени `{first}` и `{last}` в примера по-горе:
 
@@ -489,6 +501,8 @@ Lata е умен и `$iterator->last` работи не само за масив
 {/foreach}
 ```
 
+Вижте също филтри за [партиди |filters#batch] и [групи |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ n:tag .[#toc-n-tag]
 <h3 class="main">...</h3>
 ```
 
+Тъй като Latte е сигурна система за шаблониране, тя проверява дали името на новия таг е валидно и не съдържа нежелани или злонамерени стойности.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/bg/template-inheritance.texy b/latte/bg/template-inheritance.texy
index 300e571bf1..16c179b22a 100644
--- a/latte/bg/template-inheritance.texy
+++ b/latte/bg/template-inheritance.texy
@@ -132,7 +132,7 @@
 
 - Ако използвате `{layout}` в шаблон, той трябва да бъде първият таг на шаблона в този шаблон.
 
-- Макетът може да се [търси автоматично |develop#automatic-layout-lookup] (както в [презентаторите |application:templates#search-for-templates]). В този случай, ако шаблонът не трябва да има оформление, той ще посочи това с тага `{layout none}`.
+- Макетът може да се [търси автоматично |develop#automatic-layout-lookup] (както в [презентаторите |application:templates#Template Lookup]). В този случай, ако шаблонът не трябва да има оформление, той ще посочи това с тага `{layout none}`.
 
 - Тагът `{layout}` има псевдоним `{extends}`.
 
@@ -396,6 +396,14 @@ Hi, I am Mary.
 {/ifset}
 ```
 
+Съществуването на блокове се връща и от функцията [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Съвети .[#toc-tips]
 -------------------
@@ -415,7 +423,7 @@ Hi, I am Mary.
 Хоризонтална повторна употреба `{import}` .{toc: Horizontal Reuse}
 ==================================================================
 
-Хоризонталната повторна употреба е третият механизъм за повторна употреба и наследяване в Latte. Той позволява зареждане на блокове от други шаблони. Това е подобно на създаването на PHP файл с помощни функции или черти.
+Хоризонталната повторна употреба е третият механизъм за повторна употреба и наследяване в Latte. Той позволява зареждане на блокове от други шаблони. Подобно е на създаването на файл с помощни функции в PHP и последващото му зареждане с помощта на `require`.
 
 Въпреки че наследяването на оформлението на шаблона е една от най-мощните функции на Latte, то е ограничено до просто наследяване - един шаблон може да разшири само един друг шаблон. Хоризонталното повторно използване е начин за постигане на многократно наследяване.
 
@@ -447,7 +455,7 @@ Hi, I am Mary.
 
 Можете да използвате толкова изрази `{import}`, колкото искате в даден шаблон. Ако два импортирани шаблона дефинират един и същ блок, печели първият. Най-голям приоритет обаче има основният шаблон, който може да презапише всеки импортиран блок.
 
-Всички надписани блокове могат да бъдат включени постепенно, като се вмъкнат като [родителски блок |#Parent-Block]:
+Съдържанието на презаписаните блокове може да бъде запазено чрез вмъкване на блока по същия начин, както при [родителския блок |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/cs/@left-menu.texy b/latte/cs/@left-menu.texy
index 545d015f3d..5c1fb287ea 100644
--- a/latte/cs/@left-menu.texy
+++ b/latte/cs/@left-menu.texy
@@ -1,26 +1,25 @@
 - [Začínáme s Latte |guide]
 - [Proč používat šablony? |why-use]
-- Koncepty
+- Koncepty ⚗️
 	- [Bezpečnost především |safety-first]
 	- [Dědičnost šablon |Template Inheritance]
 	- [Typový systém |type-system]
 	- [Sandbox]
 
-- Pro designéry
+- Pro designéry 🎨
 	- [Syntaxe |syntax]
 	- [Tagy |tags]
 	- [Filtry |filters]
 	- [Funkce |functions]
 	- [Tipy a triky |recipes]
 
-- Pro vývojáře
+- Pro vývojáře 🧮
 	- [Vývojářské postupy |develop]
 	- [Rozšiřujeme Latte |extending-latte]
 	- [Vytváříme Extension |creating-extension]
 
-- [Návody a postupy |cookbook/@home]
+- [Návody a postupy 💡|cookbook/@home]
 	- [Migrace z Twigu |cookbook/migration-from-twig]
-	- [Migrace z Latte 2 |cookbook/migration-from-latte2]
 	- [… další |cookbook/@home]
 
 - "Hřiště .[link-external]":https://fiddle.nette.org/latte/ .{padding-top:1em}
diff --git a/latte/cs/cookbook/@home.texy b/latte/cs/cookbook/@home.texy
index 1cdf0a908b..60b8f0fba1 100644
--- a/latte/cs/cookbook/@home.texy
+++ b/latte/cs/cookbook/@home.texy
@@ -4,7 +4,9 @@ Návody a postupy
 .[perex]
 Příklady kódů a receptů pro provádění běžných úkolů pomocí Latte.
 
-- [Všechno, co jste kdy chtěli vědět o {iterateWhile} |iteratewhile]
+- [Postupy pro vývojáře |/develop]
+- [Předávání proměnných napříč šablonami |passing-variables]
+- [Všechno, co jste kdy chtěli vědět o seskupování |grouping]
 - [Jak psát SQL queries v Latte? |how-to-write-sql-queries-in-latte]
 - [Migrace z Latte 2 |migration-from-latte2]
 - [Migrace z PHP |migration-from-php]
diff --git a/latte/cs/cookbook/grouping.texy b/latte/cs/cookbook/grouping.texy
new file mode 100644
index 0000000000..91f6c65e33
--- /dev/null
+++ b/latte/cs/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Všechno, co jste kdy chtěli vědět o seskupování
+***********************************************
+
+.[perex]
+Při práci s daty ve šablonách můžete často narazit na potřebu jejich seskupování nebo specifického zobrazení podle určitých kritérií. Latte pro tento účel nabízí hned několik silných nástrojů.
+
+Filtr a funkce `|group` umožňují efektivní seskupení dat podle zadaného kritéria, filtr `|batch` zase usnadňuje rozdělení dat do pevně daných dávek a značka `{iterateWhile}` poskytuje možnost složitějšího řízení průběhu cyklů s podmínkami.
+Každá z těchto značek nabízí specifické možnosti pro práci s daty, čímž se stávají nepostradatelnými nástroji pro dynamické a strukturované zobrazení informací v Latte šablonách.
+
+
+Filtr a funkce `group` .{data-version:3.0.16}
+=============================================
+
+Představte si databázovou tabulku `items` s položkami rozdělenou do kategorií:
+
+| id  | categoryId | name
+|------------------
+| 1   |      1  | Apple
+| 2   |      1  | Banana
+| 3   |      2  | PHP
+| 4   |      3  | Green
+| 5   |      3  | Red
+| 6   |      3  | Blue
+
+Jednoduchý seznam všech položek pomocí Latte šablony by vypadal takto:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Pokud bychom ale chtěli, aby položky byly uspořádány do skupin podle kategorie, potřebujeme je rozdělit tak, že každá kategorie bude mít svůj vlastní seznam. Výsledek by pak měl vypadat následovně:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Úkol se dá snadno a elegantně vyřešit pomocí `|group`. Jako parametr uvedeme `categoryId`, což znamená, že se položky rozdělí do menších polí podle hodnoty `$item->categoryId` (pokud by `$item` bylo pole, použije se `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Filtr lze v Latte použít i jako funkci, což nám dává alternativní syntaxi: `{foreach group($items, categoryId) ...}`.
+
+Chcete-li seskupovat položky podle složitějších kritérií, můžete v parametru filtru použít funkci. Například, seskupení položek podle délky názvu by vypadalo takto:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Je důležité si uvědomit, že `$categoryItems` není běžné pole, ale objekt, který se chová jako iterátor. Pro přístup k první položce skupiny můžete použít funkci [`first()`|latte:functions#first].
+
+Tato flexibilita v seskupování dat činí `group` výjimečně užitečným nástrojem pro prezentaci dat v šablonách Latte.
+
+
+Vnořené smyčky
+--------------
+
+Představme si, že máme databázovou tabulku s dalším sloupcem `subcategoryId`, který definuje podkategorie jednotlivých položek. Chceme zobrazit každou hlavní kategorii v samostatném seznamu `<ul>` a každou podkategorii v samostatném vnořeném seznamu `<ol>`:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Spojení s Nette Database
+------------------------
+
+Pojďme si ukázat, jak efektivně využít seskupování dat v kombinaci s Nette Database. Předpokládejme, že pracujeme s tabulkou `items` z úvodního příkladu, která je prostřednictvím sloupce `categoryId` spojená s touto tabulkou `categories`:
+
+| categoryId | name       |
+|------------|------------|
+| 1          | Fruits     |
+| 2          | Languages  |
+| 3          | Colors     |
+
+Data z tabulky `items` načteme pomocí Nette Database Explorer příkazem `$items = $db->table('items')`. Během iterace nad těmito daty máme možnost přistupovat nejen k atributům jako `$item->name` a `$item->categoryId`, ale díky propojení s tabulkou `categories` také k souvisejícímu řádku v ní přes `$item->category`. Na tomto propojení lze demonstrovat zajímavé využití:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+V tomto případě používáme filtr `|group` k seskupení podle propojeného řádku `$item->category`, nikoliv jen dle sloupce `categoryId`. Díky tomu v proměnné klíči přímo `ActiveRow` dané kategorie, což nám umožňuje přímo vypisovat její název pomocí `{$category->name}`. Toto je praktický příklad, jak může seskupování zpřehlednit šablony a usnadnit práci s daty.
+
+
+Filtr `|batch`
+==============
+
+Filtr umožňuje rozdělit seznam prvků do skupin s předem určeným počtem prvků. Tento filtr je ideální pro situace, kdy chcete data prezentovat ve více menších skupinách, například pro lepší přehlednost nebo vizuální uspořádání na stránce.
+
+Představme si, že máme seznam položek a chceme je zobrazit v seznamech, kde každý obsahuje maximálně tři položky. Použití filtru `|batch` je v takovém případě velmi praktické:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+V tomto příkladu je seznam `$items` rozdělen do menších skupin, přičemž každá skupina (`$batch`) obsahuje až tři položky. Každá skupina je poté zobrazena v samostatném `<ul>` seznamu.
+
+Pokud poslední skupina neobsahuje dostatek prvků k dosažení požadovaného počtu, druhý parametr filtru umožňuje definovat, čím bude tato skupina doplněna. To je ideální pro estetické zarovnání prvků tam, kde by neúplná řada mohla působit neuspořádaně.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Značka `{iterateWhile}`
+=======================
+
+Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `group` nejprve zpracuje a seskupí všechna vstupní data, zatímco `{iterateWhile}` řídí průběhu cyklů s podmínkami, takže iterace probíhá postupně.
+
+Nejprve vykreslíme tabulku s kategoriemi pomocí iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Zatímco `{foreach}` označuje vnější část cyklu, tedy vykreslování seznamů pro každou kategorii, tak značka `{iterateWhile}` označuje vnitřní část, tedy jednotlivé položky.
+Podmínka v koncové značce říká, že opakování bude probíhat do té doby, dokud aktuální i následující prvek patří do stejné kategorie (`$iterator->nextValue` je [následující položka|/tags#$iterator]).
+
+Kdyby podmínka byla splněná vždy, tak se ve vnitřním cyklu vykreslí všechny prvky:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Výsledek bude vypadat takto:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+K čemu je takové použití iterateWhile dobré? Když bude tabulka prázdná a nebude obsahovat žádné prvky, nevypíše se prázdné `<ul></ul>`.
+
+Pokud uvedeme podmínku v otevírací značce `{iterateWhile}`, tak se chování změní: podmínka (a přechod na další prvek) se vykoná už na začátku vnitřního cyklu, nikoliv na konci.
+Tedy zatímco do `{iterateWhile}` bez podmínky se vstoupí vždy, do `{iterateWhile $cond}` jen při splnění podmínky `$cond`. A zároveň se s tím do `$item` zapíše následující prvek.
+
+Což se hodí například v situaci, kdy budeme chtít první prvek v každé kategorii vykreslit jiným způsobem, například takto:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Původní kód upravíme tak, že nejprve vykreslíme první položku a poté ve vnitřním cyklu `{iterateWhile}` vykreslíme další položky ze stejné kategorie:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Takto by se daly seskupovat třeba podkategorie atd.
+
+Dejme tomu, že v tabulce bude ještě další sloupec `subcategoryId` a kromě toho, že každá kategorie bude v samostatném `<ul>`, každá každý podkategorie samostatném `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy b/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy
index bdfc0feedc..07fb5dec84 100644
--- a/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy
+++ b/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy
@@ -2,9 +2,9 @@ Jak psát SQL queries v Latte?
 *****************************
 
 .[perex]
-Latte se může hodit i pro generování opravdu složitých SQL dotazů.
+Latte může být užitečným nástrojem i pro generování komplexních SQL dotazů, což zvyšuje jejich čitelnost a udržovatelnost.
 
-Pokud vytvoření SQL dotazu obsahuje řadu podmínek a proměnných, může být opravdu přehlednější ho napsat v Latte. Velmi jednoduchý příklad:
+Když SQL dotaz obsahuje mnoho podmínek a proměnných, může být jeho zápis v Latte přehlednější a flexibilnější. Zde je jednoduchý příklad demonstrující tuto výhodu:
 
 ```latte
 SELECT users.* FROM users
@@ -14,8 +14,13 @@ SELECT users.* FROM users
 WHERE groups.name = 'Admins' {ifset $country} AND country.name = {$country} {/ifset}
 ```
 
-Pomocí `$latte->setContentType()` řekneme Latte, aby k obsahu přistupovalo jako k prostému textu (nikoliv jako k HTML) a dále
-připravíme escapovací funkci, která bude řetězce escapovat přímo databázovým driverem:
+Pro správné fungování je třeba provést několik kroků:
+
+1. Nastavení typu obsahu: pomocí `$latte->setContentType()` informujeme Latte, že obsah má být zpracován jako prostý text, nikoliv jako HTML.
+
+2. Definice escapovací funkce: vytvoříme vlastní escapovací funkci, která bude řetězce escapovat přímo pomocí databázového driveru. Tím zajistíme bezpečnost proti SQL injection.
+
+Zde je ukázka implementace těchto kroků:
 
 ```php
 $db = new PDO(/* ... */);
@@ -31,13 +36,28 @@ $latte->addFilter('escape', fn($val) => match (true) {
 });
 ```
 
-Použití by vypadalo takto:
+Tato escapovací funkce zajišťuje správné ošetření různých datových typů:
+- Řetězce jsou escapovány pomocí metody `quote()` databázového driveru.
+- Čísla (celá i s plovoucí desetinnou čárkou) jsou převedena na řetězce.
+- Booleovské hodnoty jsou převedeny na '1' nebo '0'.
+- Null hodnoty jsou převedeny na 'NULL'.
+- Pro nepodporované typy je vyhozena výjimka.
+
+Použití v praxi by pak vypadalo takto:
 
 ```php
 $sql = $latte->renderToString('query.sql.latte', ['country' => $country]);
 $result = $db->query($sql);
 ```
 
-*Uvedený příklad vyžaduje Latte v3.0.5 nebo vyšší.*
+Tento přístup umožňuje:
+1. Dynamické sestavování SQL dotazů s využitím logiky Latte.
+2. Bezpečné vkládání proměnných do dotazu díky vlastní escapovací funkci.
+3. Lepší čitelnost a udržovatelnost komplexních SQL dotazů.
+
+.[note]
+Tento příklad vyžaduje Latte ve verzi 3.0.5 nebo novější.
+
+Využití Latte pro generování SQL dotazů může výrazně zjednodušit práci s komplexními dotazy, zejména v situacích, kdy se dotaz dynamicky mění na základě různých podmínek. Zároveň tento přístup pomáhá udržet kód čistý a snadno upravitelný.
 
 {{leftbar: /@left-menu}}
diff --git a/latte/cs/cookbook/iteratewhile.texy b/latte/cs/cookbook/iteratewhile.texy
deleted file mode 100644
index d224273408..0000000000
--- a/latte/cs/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Všechno, co jste kdy chtěli vědět o {iterateWhile}
-**************************************************
-
-.[perex]
-Značka `{iterateWhile}` se hodí na nejrůznější kejkle ve foreach cyklech.
-
-Dejme tomu, že máme následující databázovou tabulku, kde jsou položky rozdělené do kategorií:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Vykreslit položky ve foreach cyklu jako seznam je samozřejmě snadné:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Ale co kdybychom chtěli, aby každá kategorie byla v samostatném seznamu? Jinými slovy, řešíme úkol, jak seskupit položky v lineárním seznamu ve foreach cyklu do skupin. Výstup by měl vypadat takto:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Rovnou si ukážeme, jak snadno a elegantně se dá úkol vyřešit pomocí iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Zatímco `{foreach}` označuje vnější část cyklu, tedy vykreslování seznamů pro každou kategorii, tak značka `{iterateWhile}` označuje vnitřní část, tedy jednotlivé položky.
-Podmínka v koncové značce říká, že opakování bude probíhat do té doby, dokud aktuální i následující prvek patří do stejné kategorie (`$iterator->nextValue` je [následující položka|/tags#$iterator]).
-
-Kdyby podmínka byla splněná vždy, tak se ve vnitřním cyklu vykreslí všechny prvky:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Výsledek bude vypadat takto:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-K čemu je takové použití iterateWhile dobré? Jak se liší od řešení, které jsme si ukázali úplně na začátku tohoto návodu? Rozdíl je v tom, že když bude tabulka prázdná a nebude obsahovat žádné prvky, nevypíše se prázdné `<ul></ul>`.
-
-
-Řešení bez `{iterateWhile}`
----------------------------
-
-Pokud bychom stejný úkol řešili zcela základními prostředky šablonovacích systému, například v Twig, Blade, nebo čistém PHP, vypadalo by řešení cca takto:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* změnila se kategorie *}
-
-		{* uzavřeme předchozí <ul>, pokud nejde o první položku *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* otevřeme nový seznam *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* uzavřeme poslední seznam *}
-	</ul>
-{/if}
-```
-
-Tento kód je však nesrozumitelný a neintuitivní. Není vůbec jasná vazba mezi otevíracími a zavíracími HTML značkami. Není na první pohled vidět, jestli tam není nějaká chyba. A vyžaduje pomocné proměnné jako `$prevCatId`.
-
-Oproti tomu řešení s `{iterateWhile}` je čisté, přehledné, nepotřebujeme pomocné proměnné a je blbuvzdorné.
-
-
-Podmínka v otevírací značce
----------------------------
-
-Pokud uvedeme podmínku v otevírací značce `{iterateWhile}`, tak se chování změní: podmínka (a přechod na další prvek) se vykoná už na začátku vnitřního cyklu, nikoliv na konci.
-Tedy zatímco do `{iterateWhile}` bez podmínky se vstoupí vždy, do `{iterateWhile $cond}` jen při splnění podmínky `$cond`. A zároveň se s tím do `$item` zapíše následující prvek.
-
-Což se hodí například v situaci, kdy budeme chtít první prvek v každé kategorii vykreslit jiným způsobem, například takto:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Původní kód upravíme tak, že nejprve vykreslíme první položku a poté ve vnitřním cyklu `{iterateWhile}` vykreslíme další položky ze stejné kategorie:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Vnořené smyčky
---------------
-
-V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Takto by se daly seskupovat třeba podkategorie atd.
-
-Dejme tomu, že v tabulce bude ještě další sloupec `subCatId` a kromě toho, že každá kategorie bude v samostatném `<ul>`, každá každý podkategorie samostatném `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtr |batch
-------------
-
-Seskupování lineárních položek obstarává také filtr `batch`, a to do dávek s pevným počtem prvků:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Lze jej nahradit za iterateWhile tímto způsobem:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/cs/cookbook/migration-from-latte2.texy b/latte/cs/cookbook/migration-from-latte2.texy
index f14c9f90e7..4718cb2d74 100644
--- a/latte/cs/cookbook/migration-from-latte2.texy
+++ b/latte/cs/cookbook/migration-from-latte2.texy
@@ -128,6 +128,26 @@ $latte->addExtension(new Nette\Bridges\CacheLatte\CacheExtension($cacheStorage))
 ```
 
 
+Tracy
+-----
+
+Panel pro Tracy se nyní aktivuje také jako rozšíření.
+
+Starý kód pro Latte 2:
+
+```php
+$latte = new Latte\Engine;
+Latte\Bridges\Tracy\LattePanel::initialize($latte);
+```
+
+Nový kód pro Latte 3:
+
+```php
+$latte = new Latte\Engine;
+$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
+```
+
+
 Překlady
 --------
 
@@ -157,7 +177,7 @@ V Latte 2 bylo možné registrovat nové tagy pomocí [konfiguračního souboru
 latte:
 	extensions:
 		- App\Templating\LatteExtension
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 
diff --git a/latte/cs/cookbook/migration-from-php.texy b/latte/cs/cookbook/migration-from-php.texy
index f17181af91..2bec5df959 100644
--- a/latte/cs/cookbook/migration-from-php.texy
+++ b/latte/cs/cookbook/migration-from-php.texy
@@ -2,27 +2,30 @@ Migrace z PHP do Latte
 **********************
 
 .[perex]
-Převádíte starý projekt napsaný v čistém PHP do Latte? Máme pro vás nástroj, které vám migraci usnadní. [Vyzkoušejte jej online |https://php2latte.nette.org].
+Převádíte starší projekt napsaný v čistém PHP na Latte? Máme pro vás nástroj, který tento proces výrazně zjednoduší. [Vyzkoušejte jej online |https://php2latte.nette.org].
 
-Nástroj si můžete stáhnout z [GitHubu|https://github.com/nette/latte-tools] nebo nainstalovat pomocí Composeru:
+Tento užitečný nástroj můžete získat dvěma způsoby:
+
+1. Stáhnout z [GitHubu|https://github.com/nette/latte-tools]
+2. Nainstalovat pomocí Composeru:
 
 ```shell
 composer create-project latte/tools
 ```
 
-Převodník nepoužívá jednoduché záměny pomocí regulárních výrazů, naopak využívá přímo PHP parser, takže si poradí s jakkoliv složitou syntaxí.
+Na rozdíl od jednoduchých nástrojů využívajících regulární výrazy, tento převodník používá sofistikovaný PHP parser. Díky tomu si poradí i s komplexní PHP syntaxí.
 
-K převodu z PHP do Latte slouží skript `php-to-latte.php`:
+Pro převod z PHP do Latte použijte skript `php-to-latte.php`:
 
 ```shell
 php-to-latte.php input.php [output.latte]
 ```
 
 
-Příklad
--------
+Příklad použití
+---------------
 
-Vstupní soubor může vypadat třeba takto (jde o část kódu fóra PunBB):
+Podívejme se na konkrétní příklad. Níže je ukázka vstupního PHP souboru (část kódu fóra PunBB):
 
 ```php
 <h1><span><?= $lang_common['User list'] ?></span></h1>
@@ -48,7 +51,7 @@ foreach ($result as $cur_group) {
 </div>
 ```
 
-Vygeneruje tuto šablonu:
+Po zpracování nástrojem získáme následující Latte šablonu:
 
 ```latte
 <h1><span>{$lang_common['User list']}</span></h1>
@@ -69,4 +72,13 @@ Vygeneruje tuto šablonu:
 </div>
 ```
 
+Hlavní výhody tohoto převodu:
+
+1. **Čistší syntaxe**: Latte šablona je čitelnější a snáze udržovatelná.
+2. **Automatické escapování**: Latte automaticky escapuje výstup, čímž zvyšuje bezpečnost (např. `htmlspecialchars()` již není potřeba).
+3. **Lepší struktura**: Latte tagy (`{foreach}`, `{if}`) jasně oddělují logiku od prezentace.
+4. **Zjednodušení**: Odstraňuje nutnost explicitního výpisu pomocí `echo`.
+
+Tento nástroj významně urychluje a zjednodušuje proces migrace z PHP na Latte, což vám umožní rychleji modernizovat vaše projekty a využít všech výhod, které Latte nabízí.
+
 {{leftbar: /@left-menu}}
diff --git a/latte/cs/cookbook/migration-from-twig.texy b/latte/cs/cookbook/migration-from-twig.texy
index 4ded46f341..8a7fb5bd9c 100644
--- a/latte/cs/cookbook/migration-from-twig.texy
+++ b/latte/cs/cookbook/migration-from-twig.texy
@@ -2,37 +2,40 @@ Migrace z Twigu do Latte
 ************************
 
 .[perex]
-Převádíte projekt napsaný v Twigu do modernějšího Latte? Máme pro vás nástroj, které vám migraci usnadní. [Vyzkoušejte jej online |https://twig2latte.nette.org].
+Převádíte projekt z Twigu na modernější a mnohem bezpečnější Latte? Máme pro vás nástroj, který tento proces výrazně zjednoduší. [Vyzkoušejte jej online |https://twig2latte.nette.org].
 
-Nástroj si můžete stáhnout z [GitHubu|https://github.com/nette/latte-tools] nebo nainstalovat pomocí Composeru:
+Tento užitečný nástroj je dostupný dvěma způsoby:
+
+1. Stažením z [GitHubu|https://github.com/nette/latte-tools]
+2. Instalací pomocí Composeru:
 
 ```shell
 composer create-project latte/tools
 ```
 
-Převodník nepoužívá jednoduché záměny pomocí regulárních výrazů, naopak využívá přímo Twig parser, takže si poradí s jakkoliv složitou syntaxí.
+Na rozdíl od jednoduchých nástrojů využívajících regulární výrazy, tento převodník používá sofistikovaný Twig parser. Díky tomu si poradí i s komplexní Twig syntaxí.
 
-K převodu z Twigu do Latte slouží skript `twig-to-latte.php`:
+Pro převod z Twigu do Latte použijte skript `twig-to-latte.php`:
 
 ```shell
 twig-to-latte.php input.twig.html [output.latte]
 ```
 
 
-Konverze
---------
+Konverze a její specifika
+-------------------------
 
-Převod předpokládá ruční úpravu výsledku, protože konverzi nelze provést jednoznačně. Twig používá tečkovou syntax, kde `{{ a.b }}` může znamenat `$a->b`, `$a['b']` nebo  `$a->getB()`, což nelze rozlišit při kompilaci. Převaděč proto vše převádí na `$a->b`.
+Je důležité poznamenat, že převod může vyžadovat ruční úpravy výsledku. Důvodem je, že některé konstrukce v Twigu nelze jednoznačně převést do Latte. Například, Twig používá tečkovou syntax, kde `{{ a.b }}` může znamenat `$a->b`, `$a['b']` nebo `$a->getB()`. Tento rozdíl nelze rozlišit při kompilaci, proto převaděč vše převádí na `$a->b`.
 
-Některé funkce, filtry nebo tagy nemají obdobu v Latte, nebo se mohou chovat mírně jinak.
+Některé funkce, filtry nebo tagy v Twigu nemají přímou obdobu v Latte, nebo se mohou chovat mírně odlišně. To je další důvod, proč může být potřeba ruční úprava po automatickém převodu.
 
 
-Příklad
--------
+Příklad použití
+---------------
 
-Vstupní soubor může vypadat třeba takto:
+Podívejme se na konkrétní příklad. Níže je ukázka vstupního Twig souboru:
 
-```latte
+```twig
 {% use "blocks.twig" %}
 <!DOCTYPE html>
 <html>
@@ -54,7 +57,7 @@ Vstupní soubor může vypadat třeba takto:
 </html>
 ```
 
-Po konverzi do Latte získáme tuto šablonu:
+Po konverzi do Latte získáme následující šablonu:
 
 ```latte
 {import 'blocks.latte'}
@@ -78,4 +81,15 @@ Po konverzi do Latte získáme tuto šablonu:
 </html>
 ```
 
+Hlavní rozdíly a výhody po převodu:
+
+1. **Změna syntaxe**: Twig používá `{% ... %}` pro logiku a `{{ ... }}` pro výpis, zatímco Latte používá jednotnou `{ ... }` syntaxi
+2. **Bloky**: `{% block ... %}` se mění na `{block ...}`
+3. **Cykly**: `{% for ... %}` se převádí na `{foreach ...}`
+4. **Podmínky**: `{% if ... %}` zůstává podobné, ale používá se `{if ...}`.
+5. **Přístup k proměnným**: Tečková notace `item.caption` se mění na objektovou notaci `$item->caption`
+6. **Import**: `{% use ... %}` se mění na `{import ...}`
+
+Tento nástroj významně urychluje a zjednodušuje proces migrace z Twigu na Latte. Umožňuje vám rychle modernizovat vaše projekty a využít všech výhod, které Latte nabízí, včetně jeho výkonu a flexibilnity. Nezapomeňte však po automatickém převodu zkontrolovat a případně upravit výsledný kód, aby plně odpovídal vašim potřebám a specifikům vašeho projektu.
+
 {{leftbar: /@left-menu}}
diff --git a/latte/cs/cookbook/passing-variables.texy b/latte/cs/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..7bb477af7a
--- /dev/null
+++ b/latte/cs/cookbook/passing-variables.texy
@@ -0,0 +1,163 @@
+Předávání proměnných napříč šablonami
+*************************************
+
+Tento průvodce objasňuje, jak se v Latte předávají proměnné mezi šablonami pomocí různých tagů jako `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` a dalších. Dozvíte se také, jak pracovat s proměnnými v tagu `{block}` a `{define}`, a k čemu slouží značka `{parameters}`.
+
+
+Typy proměnných
+---------------
+V Latte rozlišujeme tři kategorie proměnných podle jejich definice a dostupnosti:
+
+**Vstupní proměnné** jsou předávány do šablony zvenčí, typicky z PHP skriptu nebo pomocí tagů jako `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Okolní proměnné** jsou proměnné existující v místě určité značky. Zahrnují všechny vstupní proměnné a další proměnné vytvořené pomocí tagů jako `{var}`, `{default}` nebo v rámci smyčky `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Explicitní proměnné** jsou ty, které jsou přímo specifikovány uvnitř tagu a jsou odeslány do cílové šablony.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Tag `{block}` se používá k definování opakovaně použitelných bloků kódu, které lze v dědičných šablonách přizpůsobit nebo rozšířit. Okolní proměnné definované před blokem jsou dostupné uvnitř bloku, ale jakékoli změny proměnných se projeví jen v rámci toho bloku.
+
+```latte
+{var $foo = 'původní'}
+{block example}
+	{var $foo = 'změněný'}
+{/block}
+
+{$foo}    // vypíše: původní
+```
+
+
+`{define}`
+----------
+Tag `{define}` vytváří bloky, které se renderují až po jejich explicitním zavolání pomocí `{include}`. Dostupnost proměnných uvnitř těchto bloků závisí na přítomnosti parametrů v definici. S parametry mají bloky přístup pouze k těmto parametrům. Bez parametrů mají přístup ke všem vstupním proměnným šablony, ve které jsou definovány.
+
+```latte
+{define hello}
+	{* má přístup ke všem vstupním proměnným šablony *}
+{/define}
+
+{define hello $name}
+	{* má přístup jen k parametru $name *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Tag `{parameters}` slouží k explicitní deklaraci očekávaných vstupních proměnných na začátku šablony. Tímto způsobem lze efektivně dokumentovat očekávané proměnné a jejich datové typy. Umožňuje také definovat výchozí hodnoty.
+
+```latte
+{parameters int $age, string $name = 'neznámé'}
+<p>Věk: {$age}, Jméno: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Tag `{include file}` vkládá celou šablonu. Do vkládané šablony se předávají vstupní proměnné šablony, ve které je značka použita, spolu s explicitně definovanými proměnnými. Cílová šablona může omezit rozsah přijímaných proměnných pomocí `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Při vkládání bloku definovaného ve stejné šabloně se do něj předávají všechny okolní a explicitně definované proměnné:
+
+```latte
+{define blockName}
+	<p>Jméno: {$name}, Věk: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+V tomto příkladu jsou proměnné `$name` a `$age` předány do bloku `blockName`. Stejně se chová i `{include parent}`.
+
+Při vkládání bloku z jiné šablony se předávají pouze vstupní proměnné a explicitně definované proměnné. Okolní proměnné nejsou automaticky dostupné.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` nebo `{extends}`
+---------------------------
+Tyto tagy definují layout, do kterého se předávají vstupní proměnné podřízené šablony a proměnné vytvořené v kódu před bloky:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Šablona `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Tag `{embed}` je podobný tagu `{include}`, ale umožňuje vkládání bloků do šablony. Na rozdíl od `{include}` se předávají pouze explicitně deklarované proměnné:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+V tomto příkladu má šablona `menu.latte` přístup pouze k proměnné `$items`.
+
+Naopak v blocích uvnitř `{embed}` je přístup ke všem okolním proměnným:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Tag `{import}` se používá pro načítání bloků z jiných šablon. Do importovaných bloků se předávají jak vstupní, tak explicitně deklarované proměnné.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Tag `{sandbox}` izoluje šablonu pro bezpečné zpracování. Proměnné jsou předávány výhradně explicitně, což zvyšuje kontrolu nad daty vstupujícími do izolovaného prostředí.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+Tento mechanismus umožňuje přesnou kontrolu nad tím, jaká data jsou dostupná v izolované šabloně, což je užitečné pro zpracování potenciálně nebezpečného obsahu.
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/cs/creating-extension.texy b/latte/cs/creating-extension.texy
index 26b2b0b3bb..7608d85ebc 100644
--- a/latte/cs/creating-extension.texy
+++ b/latte/cs/creating-extension.texy
@@ -2,25 +2,24 @@ Vytváříme Extension
 *******************
 
 .[perex]
-Tzv. rozšíření je opakovatelně použitelná třída, která může definovat vlastní značky, filtry, funkce, providery, atd.
+Rozšíření (extension) je znovupoužitelná třída, která může definovat vlastní značky, filtry, funkce, providery a další prvky pro Latte. Vytváříme je, když chceme své úpravy Latte použít v různých projektech nebo je sdílet s komunitou.
 
-Rozšíření vytváříme tehdy, pokud chceme své úpravy Latte znovu použít v různých projektech nebo je sdílet s ostatními.
-Je užitečné vytvářet rozšíření i pro každý webový projekt, které bude obsahovat všechny specifické značky a filtry, které chcete v šablonách projektu využívat.
+Rozšíření je užitečné vytvořit i pro každý webový projekt. Může obsahovat všechny specifické značky a filtry, které chcete v šablonách projektu využívat.
 
 
 Třída rozšíření
 ===============
 
-Rozšíření je třída dědící od [api:Latte\Extension]. Do Latte se registruje pomocí `addExtension()` (případně [konfiguračním souborem |application:configuration#Šablony Latte]):
+Rozšíření je třída dědící od [api:Latte\Extension]. Do Latte se registruje pomocí `addExtension()` nebo [konfiguračním souborem |application:configuration#Šablony Latte]:
 
 ```php
 $latte = new Latte\Engine;
 $latte->addExtension(new MyLatteExtension);
 ```
 
-Pokud zaregistrujete vícero rozšíření a ty definují stejně pojmenované tagy, filtry nebo funkce, vyhrává poslední přidané rozšíření. Z toho také plyne, že vaše rozšíření mohou přepisovat nativní značky/filtry/funkce.
+Pokud zaregistrujete více rozšíření definujících stejně pojmenované tagy, filtry nebo funkce, platí poslední přidané. To znamená, že vaše rozšíření může přepisovat nativní značky/filtry/funkce.
 
-Kdykoliv v třídě provedete změnu a není vypnutý auto-refresh, Latte automaticky překompiluje vaše šablony.
+Kdykoliv provedete změnu ve třídě rozšíření a není vypnutý auto-refresh, Latte automaticky překompiluje vaše šablony.
 
 Třída může implementovat kteroukoliv z následujících metod:
 
@@ -76,11 +75,13 @@ abstract class Extension
 
 Pro představu, jak rozšíření vypadá, se podívejte na vestavěné "CoreExtension":https://github.com/nette/latte/blob/master/src/Latte/Essential/CoreExtension.php.
 
+Nyní si podrobněji rozebereme jednotlivé metody:
+
 
 beforeCompile(Latte\Engine $engine): void .[method]
 ---------------------------------------------------
 
-Volá se před kompilací šablony. Metodu lze využít např. pro inicializace související s kompilací.
+Tato metoda se volá před kompilací šablony. Můžete ji využít například pro inicializace související s kompilací.
 
 
 getTags(): array .[method]
@@ -102,18 +103,18 @@ public function getTags(): array
 
 Značka `n:baz` představuje ryzí n:atribut, tj. jde o značku, kterou lze zapisovat pouze jako atribut.
 
-V případě značek `foo` a `bar` Latte samo rozezná, zda jsou párové, a pokud ano, bude je možné automaticky zapisovat i pomocí n:atributů, včetně variant s prefixy `n:inner-foo` a `n:tag-foo`.
+Latte automaticky rozpozná, zda jsou značky `foo` a `bar` párové. Pokud ano, bude je možné zapisovat i pomocí n:atributů, včetně variant s prefixy `n:inner-foo` a `n:tag-foo`.
 
-Pořadí provádění takovýchto n:atributů je dáno jejich pořadím v poli vráceném `getTags()`. Tedy `n:foo` se provede vždy před `n:bar`, i kdyby byly atributy v HTML značce uvedeny v opačném pořadí jako `<div n:bar="..." n:foo="...">`.
+Pořadí provádění n:atributů je dáno jejich pořadím v poli vráceném `getTags()`. Tedy `n:foo` se provede vždy před `n:bar`, i kdyby byly atributy v HTML značce uvedeny v opačném pořadí.
 
-Pokud potřebujete stanovit pořadí n:atributů napříč více rozšířeními, použijte pomocnou metodu `order()`, kde parametr `before` a nebo `after` určuje, před nebo za kterými značkami se daná značka zařadí.
+Pro stanovení pořadí n:atributů napříč více rozšířeními použijte pomocnou metodu `order()`. Parametry `before` a `after` určují, před nebo za kterými značkami se daná značka zařadí:
 
 ```php
 public function getTags(): array
 {
 	return [
-		'foo' => self::order([FooNode::class, 'create'], before: 'bar')]
-		'bar' => self::order([BarNode::class, 'create'], after: ['block', 'snippet'])]
+		'foo' => self::order([FooNode::class, 'create'], before: 'bar'),
+		'bar' => self::order([BarNode::class, 'create'], after: ['block', 'snippet']),
 	];
 }
 ```
@@ -122,7 +123,7 @@ public function getTags(): array
 getPasses(): array .[method]
 ----------------------------
 
-Volá se při kompilaci šablony. Vrací asociativní pole *název pass => callable*, což jsou funkce představující tzv. [#průchody kompilátoru], které procházejí a modifikujou AST.
+Volá se při kompilaci šablony. Vrací asociativní pole *název pass => callable*, což jsou funkce představující tzv. [#průchody kompilátoru], které procházejí a modifikují AST.
 
 Opět je možné využít pomocnou metodu `order()`. Hodnotou parametrů `before` nebo `after` může být `'*'` s významem před/za všemi.
 
@@ -141,7 +142,7 @@ public function getPasses(): array
 beforeRender(Latte\Engine $engine): void .[method]
 --------------------------------------------------
 
-Volá se před každým vykreslením šablony. Metodu lze využít např. pro inicializaci proměnných používaných při vykreslování.
+Volá se před každým vykreslením šablony. Metodu lze využít například pro inicializaci proměnných používaných při vykreslování.
 
 
 getFilters(): array .[method]
@@ -181,7 +182,7 @@ public function getFunctions(): array
 getProviders(): array .[method]
 -------------------------------
 
-Volá se před vykreslením šablony. Vrací pole tzv. providers, což jsou zpravidla objekty, které za běhu využívají tagy. Přistupují k nim přes `$this->global->...`.
+Volá se před vykreslením šablony. Vrací pole tzv. providerů, což jsou zpravidla objekty, které za běhu využívají tagy. Přistupují k nim přes `$this->global->...`.
 
 ```php
 public function getProviders(): array
@@ -198,7 +199,7 @@ public function getProviders(): array
 getCacheKey(Latte\Engine $engine): mixed .[method]
 --------------------------------------------------
 
-Volá se před vykreslením šablony. Vrácená hodnota se stane součástí klíče, jehož hash je obsažen v názvu souboru se zkompilovanou šablonou. Tedy pro různé vrácené hodnoty Latte vygeneruje různé soubory v cache.
+Volá se před vykreslením šablony. Vrácená hodnota se stane součástí klíče, jehož hash je obsažen v názvu souboru se zkompilovanou šablonou. Pro různé vrácené hodnoty tedy Latte vygeneruje různé soubory v cache.
 
 
 Jak Latte funguje?
@@ -208,20 +209,19 @@ Pro pochopení toho, jak definovat vlastní tagy nebo compiler passes, je nezbyt
 
 Kompilace šablon v Latte probíhá zjednodušeně takto:
 
-- Nejprve **lexer** tokenizuje zdrojový kód šablony na malé části (tokeny) pro snadnější zpracování.
-- Poté **parser** převede proud tokenů na smysluplný strom uzlů (abstraktní syntaktický strom, AST).
-- Nakonec překladač **vygeneruje** z AST třídu PHP, která vykresluje šablonu, a uloží ji do cache.
+1. **Lexer** tokenizuje zdrojový kód šablony na menší části (tokeny) pro snadnější zpracování.
+2. **Parser** převede proud tokenů na smysluplný strom uzlů (abstraktní syntaktický strom, AST).
+3. **Překladač** vygeneruje z AST třídu PHP, která vykresluje šablonu, a uloží ji do cache.
 
 Ve skutečnosti je kompilace o něco složitější. Latte **má dva** lexery a parsery: jeden pro HTML šablonu a druhý pro PHP-like kód uvnitř tagů. A také parsování neprobíhá až po tokenizaci, ale lexer i parser běží paralelně ve dvou "vláknech" a koordinují se. Je to raketová věda :-)
 
-Dále své parsovací rutiny mají i všechny tagy. Když parser narazí na tag, zavolá jeho parsovací funkci (vrací je [Extension::getTags()|#getTags]).
-Jejich úkolem je naparsovat argumenty značky a v případě párových značek i vnitřní obsah. Vrací *uzel*, který se stane součástí AST. Podrobně v části [#Parsovací funkce tagu].
+Každý tag má svou parsovací rutinu. Když parser narazí na tag, zavolá jeho parsovací funkci (vrací je [Extension::getTags()|#getTags]). Jejich úkolem je naparsovat argumenty značky a v případě párových značek i vnitřní obsah. Vrací *uzel*, který se stane součástí AST. Podrobně v části [#Parsovací funkce tagu].
 
-Když parser dokončí práci, máme kompletní AST reprezentující šablonu. Kořenovým uzlem je `Latte\Compiler\Nodes\TemplateNode`. Jednotlivé uzly uvnitř stromu pak reprezentují nejen tagy, ale i HTML elementy, jejich atributy, všechny výrazy použité uvnitř značek atd.
+Po dokončení parsování máme kompletní AST reprezentující šablonu. Kořenovým uzlem je `Latte\Compiler\Nodes\TemplateNode`. Jednotlivé uzly uvnitř stromu reprezentují nejen tagy, ale i HTML elementy, jejich atributy, všechny výrazy použité uvnitř značek atd.
 
 Poté přicházejí na řadu tzv. [#Průchody kompilátoru], což jsou funkce (vrací je [Extension::getPasses()|#getPasses]), které modifikují AST.
 
-Celý proces od načtení obsahu šablony přes parsování až po vygenerování výsledného souboru se dá sekvenčně vykonat tímto kódem, se kterým můžete experimentovat a dumpovat si jednotlivé mezikroky:
+Celý proces od načtení obsahu šablony přes parsování až po vygenerování výsledného souboru můžete sekvenčně vykonat tímto kódem:
 
 ```php
 $latte = new Latte\Engine;
@@ -285,19 +285,21 @@ Vlastní tagy
 
 K definování nové značky jsou zapotřebí tři kroky:
 
-- definování [#parsovací funkce tagu] (zodpovědná za parsování tagu do uzlu)
-- vytvoření třídy uzlu (zodpovědné za [#generování PHP kódu] a [#procházení AST])
-- registrace tagu pomocí [Extension::getTags()|#getTags]
+1. Definování [#parsovací funkce tagu] (zodpovědná za parsování tagu do uzlu)
+2. Vytvoření třídy uzlu (zodpovědné za [#generování PHP kódu] a [#procházení AST])
+3. Registrace tagu pomocí [Extension::getTags()|#getTags]
 
 
 Parsovací funkce tagu
 ---------------------
 
-Parsování tagů ma na starosti jeho parsovací funkce (ta, kterou vrací [Extension::getTags()|#getTags]). Jejím úkolem je naparsovat a zkontrolovat případné argumenty uvnitř značky (k tomu využívá TagParser).
-A dále, pokud je značka párová, požádá TemplateParser o naparsování a vrácení vnitřního obsahu.
-Funkce vytvoří a vrátí uzel, který je zpravidla potomkem `Latte\Compiler\Nodes\StatementNode`, a ten se stane součástí AST.
+Parsování tagů má na starosti jeho parsovací funkce (ta, kterou vrací [Extension::getTags()|#getTags]). Jejím úkolem je:
+
+1. Naparsovat a zkontrolovat případné argumenty uvnitř značky (k tomu využívá TagParser).
+2. Pokud je značka párová, požádat TemplateParser o naparsování a vrácení vnitřního obsahu.
+3. Vytvořit a vrátit uzel, který je zpravidla potomkem `Latte\Compiler\Nodes\StatementNode`, a který se stane součástí AST.
 
-Pro každý uzel si vytváříme třídu, což uděláme teď hned a parsovací funkci do ní elegantně umístíme jako statickou továrnu. Jako příklad si zkusíme vytvořit známý tag `{foreach}`:
+Pro každý uzel vytváříme třídu a parsovací funkci do ní umístíme jako statickou továrnu. Jako příklad si vytvoříme známý tag `{foreach}`:
 
 ```php
 use Latte\Compiler\Nodes\StatementNode;
@@ -307,7 +309,7 @@ class ForeachNode extends StatementNode
 	// parsovací funkce, která zatím pouze vytváří uzel
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -338,7 +340,7 @@ a dále nízkoúrovňový [api:Latte\Compiler\TokenStream] operující přímo s
 - `$tag->parser->stream->consume(...): Token`
 - `$tag->parser->stream->tryConsume(...): ?Token`
 
-Latte drobnými způsoby rozšiřuje syntaxi PHP, například o modifikátory, zkrácené ternání operátory, nebo umožňuje jednoduché alfanumerické řetězce psát bez uvozovek. Proto používáme termím *PHP-like* místo PHP. Tudíž metoda `parseExpression()` naparsuje např. `foo` jako `'foo'`.
+Latte mírně rozšiřuje syntaxi PHP, například o modifikátory, zkrácené ternání operátory, nebo umožňuje jednoduché alfanumerické řetězce psát bez uvozovek. Proto používáme termín *PHP-like* místo PHP. Metoda `parseExpression()` tedy naparsuje např. `foo` jako `'foo'`.
 Vedle toho *unquoted-řetězec* je speciálním případem řetězce, který také nemusí být v uvozovkách, ale zároveň nemusí být ani alfanumerický. Jde třeba o cestu k souboru ve značce `{include ../file.latte}`. K jeho naparsování slouží metoda `parseUnquotedStringOrExpression()`.
 
 .[note]
@@ -359,7 +361,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -406,7 +408,7 @@ public static function create(Latte\Compiler\Tag $tag): \Generator
 }
 ```
 
-Vrácením uzlu je parsování tagu dokončeno.
+Vrácením uzlu `$node` je parsování tagu dokončeno.
 
 
 Generování PHP kódu
@@ -416,7 +418,7 @@ Každý uzel musí implementovat metodu `print()`. Vrací PHP kód vykreslujíc
 
 Metoda `format(string $mask, ...$args)` akceptuje v masce tyto placeholdery:
 - `%node` vypisuje Node
-- `%dump` vyexporuje hodnotu do PHP
+- `%dump` vyexportuje hodnotu do PHP
 - `%raw` vloží přímo text bez jakékoliv transformace
 - `%args` vypíše ArrayNode jako argumenty volání funkce
 - `%line` vypíše komentář s číslem řádku
@@ -474,7 +476,7 @@ Všimněte si, že `getIterator()` vrací reference. Právě díky tomu mohou *n
 .[warning]
 Pokud má uzel poduzly, je nezbytné tuto metodu implementovat a všechny poduzly zpřístupnit. Jinak by mohla vzniknout bezpečnostní díra. Například režim sandboxu by nebyl schopen kontrolovat poduzly a zajistit, aby v nich nebyly volány nepovolené konstrukce.
 
-Protože klíčové slovo `yield` musí být přítomno v těle metody i pokud nemá žádné podřízené uzly, zapište ji takto:
+Pokud uzel nemá žádné poduzly, implementujte metodu takto:
 
 ```php
 public function &getIterator(): \Generator
@@ -486,6 +488,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Pokud vytváříte nový tag pro Latte, je žádoucí, abyste pro něj vytvořili vlastní třídu uzlu, která jej bude reprezentovat v AST stromu (viz třída `ForeachNode` v příkladu výše). V některých případech se vám může hodit pomocná triviální třída uzlu [AuxiliaryNode|api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], které tělo metody `print()` a seznam uzlů, které zpřístupňuje metoda `getIterator()`, předáme jako parametry konstruktoru:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// tělo metody print():
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// uzly zpřístupněné přes getIterator() a také předané do metody print():
+	[$argNode],
+);
+```
+
+
 Průchody kompilátoru
 ====================
 
@@ -526,9 +546,9 @@ $ast = (new NodeTraverser)->traverse(
 );
 ```
 
-Modul AST může snadno obsahovat tisíce uzlů a procházení všech uzlů může být pomalé. V některých případech je možné se úplnému procházení vyhnout.
+AST může snadno obsahovat tisíce uzlů a procházení všech uzlů může být časově náročné. V některých případech je možné se úplnému procházení vyhnout.
 
-Pokud ve stromu hledáte všechny uzly `Html\ElementNode`, pak víte, že jakmile jednou uvidíte uzel `Php\ExpressionNode`, nemá smysl kontrolovat také všechny jeho podřízené uzly, protože HTML nemůže být uvnitř ve výrazech. V takovém případě můžete traverseru přikázat, aby do uzlu třídy neprováděl rekurzi:
+Pokud ve stromu hledáte všechny uzly `Html\ElementNode`, pak víte, že jakmile jednou uvidíte uzel `Php\ExpressionNode`, nemá smysl kontrolovat také všechny jeho podřízené uzly, protože HTML nemůže být uvnitř výrazů. V takovém případě můžete traverseru přikázat, aby do uzlu třídy neprováděl rekurzi:
 
 ```php
 $ast = (new NodeTraverser)->traverse(
@@ -560,7 +580,7 @@ $ast = (new NodeTraverser)->traverse(
 Pomocníci pro uzly
 ------------------
 
-Třída [api:Latte\Compiler\NodeHelpers] poskytuje některé metody, které mohou najít uzly AST, které buď splňují určitou podmínku atd. Několik příkladů:
+Třída [api:Latte\Compiler\NodeHelpers] poskytuje některé metody, které mohou najít uzly AST, které splňují určitou podmínku atd. Několik příkladů:
 
 ```php
 use Latte\Compiler\NodeHelpers;
@@ -577,3 +597,5 @@ $value = NodeHelpers::toValue($node);
 // převede statický textový uzel na řetězec
 $text = NodeHelpers::toText($node);
 ```
+
+Tímto způsobem můžete efektivně procházet a manipulovat s AST stromem ve vašich rozšířeních pro Latte.
diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy
index 32e43894a7..db494d990c 100644
--- a/latte/cs/develop.texy
+++ b/latte/cs/develop.texy
@@ -5,7 +5,7 @@ Vývojářské postupy
 Instalace
 =========
 
-Nejlepší způsob, jak nainstalovat Latte, je pomocí Composeru:
+Nejlepší způsob instalace Latte je pomocí Composeru:
 
 ```shell
 composer require latte/latte
@@ -18,22 +18,22 @@ Podporované verze PHP (platí pro poslední setinkové verze Latte):
 | Latte 3.0       | PHP 8.0 – 8.2
 
 
-Jak vykreslit šablonu
-=====================
+Vykreslení šablony
+==================
 
 Jak vykreslit šablonu? Stačí k tomu tento jednoduchý kód:
 
 ```php
 $latte = new Latte\Engine;
-// adresář pro cache
+// nastavení adresáře pro cache
 $latte->setTempDirectory('/path/to/tempdir');
 
 $params = [ /* proměnné šablony */ ];
-// or $params = new TemplateParameters(/* ... */);
+// nebo $params = new TemplateParameters(/* ... */);
 
-// kresli na výstup
+// vykreslení na výstup
 $latte->render('template.latte', $params);
-// kresli do proměnné
+// vykreslení do proměnné
 $output = $latte->renderToString('template.latte', $params);
 ```
 
@@ -46,23 +46,21 @@ Ukázky použití najdete také v repozitáři [Latte examples |https://github.c
 Výkon a cache
 =============
 
-Šablony v Latte jsou nesmírně rychlé, Latte je totiž kompiluje přímo do PHP kódu a ukládá do cache na disk. Nemají tedy žádnou režii navíc oproti šablonám psaným v čistém PHP.
+Šablony v Latte jsou extrémně rychlé, protože se kompilují přímo do PHP kódu a ukládají do cache na disk. Nemají tedy žádnou režii navíc oproti šablonám psaným v čistém PHP.
 
-Cache se automaticky regeneruje pokaždé, když změníte zdrojový soubor. Během vývoje si tedy pohodlně editujete šablony v Latte a změny okamžitě vidíte v prohlížeči. Tuto funkci můžete v produkčním prostředí vypnout a ušetřit tím malinko výkonu:
+Cache se automaticky regeneruje při změně zdrojového souboru. Během vývoje tedy pohodlně editujete šablony v Latte a změny okamžitě vidíte v prohlížeči. Pro mírné zvýšení výkonu v produkčním prostředí můžete automatickou regeneraci vypnout:
 
 ```php
 $latte->setAutoRefresh(false);
 ```
 
-Při nasazení na produkčním serveru může prvotní vygenerování cache, zejména u rozsáhlejších aplikací, pochopitelně chviličku trvat. Latte má vestavěnou prevenci před "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-Jde o situaci, kdy se sejde větší počet souběžných požadavků, které spustí Latte, a protože cache ještě neexistuje, začaly by ji všechny generovat současně. Což by neúměrně zatížilo server.
-Latte je chytré a při více souběžných požadavcích generuje cache pouze první vlákno, ostatní čekají a následně ji využíjí.
+Při nasazení na produkční server může prvotní vygenerování cache, zejména u rozsáhlých aplikací, chvíli trvat. Latte má vestavěnou prevenci proti "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede, což je situace, kdy velký počet souběžných požadavků spustí generování cache současně, což by mohlo přetížit server. Latte tento problém řeší chytře - při více souběžných požadavcích generuje cache pouze první vlákno, zatímco ostatní čekají a následně využijí vytvořenou cache.
 
 
 Parametry jako třída
 ====================
 
-Lepší než předávat proměnné do šablony jako pole je vytvořit si třídu. Získáte tak [typově bezpečný zápis|type-system], [příjemné napovídání v IDE|recipes#Editory a IDE] a cestu pro [registraci filtrů|extending-latte#Filtry pomocí třídy] a [funkcí|extending-latte#Funkce pomocí třídy].
+Místo předávání proměnných do šablony jako pole je lepší vytvořit si třídu. Získáte tak [typově bezpečný zápis|type-system], [příjemné napovídání v IDE|recipes#Editory a IDE] a možnost [registrace filtrů|extending-latte#Filtry pomocí třídy] a [funkcí|extending-latte#Funkce pomocí třídy].
 
 ```php
 class MailTemplateParameters
@@ -89,9 +87,9 @@ $latte->render('mail.latte', new MailTemplateParameters(
 Vypnutí auto-escapování proměnné
 ================================
 
-Pokud proměnná obsahuje řetězec v HTML, můžete ji označit tak, aby ji Latte automaticky (a tedy dvojitě) neescapovalo. Vyhnete se tak potřebě uvádět v šabloně `|noescape`.
+Pokud proměnná obsahuje HTML řetězec, můžete ji označit tak, aby ji Latte automaticky (a tedy dvojitě) neescapovalo. Tím se vyhnete potřebě uvádět v šabloně `|noescape`.
 
-Nejjednodušší cestou je řetězec zabalit do objektu `Latte\Runtime\Html`:
+Nejjednodušší způsob je zabalit řetězec do objektu `Latte\Runtime\Html`:
 
 ```php
 $params = [
@@ -99,10 +97,10 @@ $params = [
 ];
 ```
 
-Latte dále neescapuje všechny objekty, které implementují rozhraní `Latte\HtmlStringable`. Můžete si tak vytvořit vlastní třídu, jejíž metoda `__toString()` bude vracet HTML kód, který se nebude automaticky escapovat:
+Latte také neescapuje objekty implementující rozhraní `Latte\HtmlStringable`. Můžete si vytvořit vlastní třídu, jejíž metoda `__toString()` bude vracet HTML kód, který se nebude automaticky escapovat:
 
 ```php
-class Emphasis extends Latte\HtmlStringable
+class Emphasis implements Latte\HtmlStringable
 {
 	public function __construct(
 		private string $str,
@@ -127,16 +125,14 @@ Metoda `__toString` musí vracet korektní HTML a zajistit escapování parametr
 Jak rozšířit Latte o filtry, značky atd.
 ========================================
 
-Jak do Latte přidat vlastní filtr, funkci, značku atd? O tom pojednává kapitola [rozšiřujeme Latte |extending-latte].
+Informace o přidávání vlastních filtrů, funkcí, značek atd. najdete v kapitole [rozšiřujeme Latte |extending-latte].
 Pokud chcete své úpravy znovu použít v různých projektech nebo je sdílet s ostatními, měli byste [vytvořit rozšíření |creating-extension].
 
 
-Libovolný kód v šabloně `{php ...}` .{toc: RawPhpExtension}
-===========================================================
+Libovolný PHP kód v šabloně `{php ...}` .{toc: RawPhpExtension}
+===============================================================
 
-Uvnitř značky [`{do}`|tags#do] lze zapisovat pouze PHP výrazy, nemůžete tak třeba vložit konstrukce jako `if ... else` nebo statementy ukončené středníkem.
-
-Můžete si však zaregistrovat rozšíření `RawPhpExtension`, které přidává značku `{php ...}`. Pomocí té lze vkládat jakýkoliv PHP kód. Nevztahují se na něj žádná pravidla sandbox režimu, použití je tedy na zodpovědnost autora šablony.
+Zatímco uvnitř značky [`{do}`|tags#do] lze zapisovat pouze PHP výrazy, rozšíření `RawPhpExtension` přidává značku `{php ...}`, která umožňuje vkládat jakýkoliv PHP kód. Použití je na zodpovědnost autora šablony, protože se na ni nevztahují pravidla sandbox režimu.
 
 ```php
 $latte->addExtension(new Latte\Essential\RawPhpExtension);
@@ -146,12 +142,10 @@ $latte->addExtension(new Latte\Essential\RawPhpExtension);
 Kontrola vygenerovaného kódu .{data-version:3.0.7}
 ==================================================
 
-Latte kompiluje šablony do PHP kódu. Samozřejmě dbá na to, aby vygenerovaný kód byl syntakticky validní. Nicméně při použítí rozšíření třetích stran nebo `RawPhpExtension` nemůže Latte zaručit správnost vygenerovaného souboru.
-Také lze v PHP zapsat kód, který je sice syntakticky správný, ale je zakázaný (například přiřazení hodnoty do proměnné `$this`) a způsobí PHP Compile Error.
+Latte kompiluje šablony do PHP kódu a dbá na jeho syntaktickou správnost. Nicméně při použití rozšíření třetích stran nebo `RawPhpExtension` nemůže Latte zaručit korektnost vygenerovaného souboru. V PHP lze také zapsat kód, který je syntakticky správný, ale zakázaný (například přiřazení hodnoty do `$this`) a způsobí PHP Compile Error.
 Pokud takovou operaci zapíšete v šabloně, dostane se i do vygenerovaného PHP kódu. Jelikož v PHP existují na dvě stovky různých zakázaných operací, nemá Latte ambici je odhalovat. Upozorní na ně až samotné PHP při vykreslení, což obvykle ničemu nevadí.
 
-Jsou ale situace, kdy chcete vědět už v době kompilace šablony, že žádný PHP Compile Error neobsahuje. Zejména tehdy, pokud šablony mohou editovat uživatelé, nebo používáte [Sandbox]. V takovém případě si nechte šablony kontrolovat už v době kompilace.
-Tuto funkčnost zapnete metodou `Engine::enablePhpLint()`. Jelikož ke kontrole potřebuje volat binárku PHP, cestu k ní předejte jako parametr:
+Pokud chcete odhalit tyto problémy už v době kompilace šablony, zejména pokud šablony mohou editovat uživatelé nebo používáte [Sandbox], můžete zapnout kontrolu pomocí `Engine::enablePhpLint()`. Ke kontrole je potřeba volat binárku PHP, jejíž cestu předáte jako parametr:
 
 ```php
 $latte = new Latte\Engine;
@@ -166,10 +160,26 @@ try {
 ```
 
 
+Národní prostředí .{data-version:3.0.18}{toc: Locale}
+=====================================================
+
+Latte umožňuje nastavit národní prostředí, které ovlivňuje formátování čísel, datumů a řazení. Nastavuje se pomocí metody `setLocale()`. Identifikátor prostředí se řídí standardem IETF language tag, který používá rozšíření PHP `intl`. Skládá se z kódu jazyka a případně kódu země, např. `en_US` pro angličtinu ve Spojených státech, `de_DE` pro němčinu v Německu atd.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Nastavení prostředí ovlivňuje filtry [localDate|filters#localDate], [sort|filters#sort], [number|filters#number] a [bytes|filters#bytes].
+
+.[note]
+Vyžaduje PHP rozšíření `intl`. Nastavení v Latte neovlivňuje globální nastavení locale v PHP.
+
+
 Striktní režim .{data-version:3.0.8}
 ====================================
 
-Ve striktním režimu parsování Latte kontroluje, zda nechybí uzavírací HTML značky a také zakazuje používání proměnné `$this`. Zapnete jej takto:
+Ve striktním režimu parsování Latte kontroluje, zda nechybí uzavírací HTML značky a zakazuje používání proměnné `$this`. Zapnete jej takto:
 
 ```php
 $latte = new Latte\Engine;
@@ -187,7 +197,7 @@ $latte->setStrictTypes();
 Překládání v šablonách .{toc: TranslatorExtension}
 ==================================================
 
-Pomocí rozšíření `TranslatorExtension` přidáte do šablony značky [`{_...}`|tags#_], [`{translate}`|tags#translate] a filtr [`translate`|filters#translate]. Slouží k překládání hodnot nebo částí šablony do jiných jazyků. Jako parametr uvedeme metodu (PHP callable) provádějící překlad:
+Rozšíření `TranslatorExtension` přidává do šablony značky [`{_...}`|tags#_], [`{translate}`|tags#translate] a filtr [`translate`|filters#translate] pro překládání hodnot nebo částí šablony do jiných jazyků. Jako parametr uvedeme metodu provádějící překlad:
 
 ```php
 class MyTranslator
@@ -233,7 +243,7 @@ public function translate(string $original, ...$params): string
 Debuggování a Tracy
 ===================
 
-Latte se vám snaží vývoj co nejvíce zpříjemnit. Přímo pro účely debugování existuje trojice značek [`{dump}`|tags#dump], [`{debugbreak}`|tags#debugbreak] a [`{trace}`|tags#trace].
+Latte se vám snaží vývoj co nejvíce zpříjemnit. Nabízí několik nástrojů pro debugování, včetně značek [`{dump}`|tags#dump], [`{debugbreak}`|tags#debugbreak] a [`{trace}`|tags#trace].
 
 Největší komfort získáte, když ještě si nainstalujete skvělý [ladicí nástroj Tracy|tracy:] a aktivujete doplněk pro Latte:
 
@@ -251,13 +261,13 @@ Zároveň v pravém dolním rohu v tzv. Tracy Baru se objeví záložka pro Latt
 
 [* latte-debugging.webp *]
 
-Jelikož Latte kompiluje šablony do přehledného PHP kódu, můžete je pohodlně ve svém IDE krokovat.
+Jelikož Latte kompiluje šablony do přehledného PHP kódu, můžete je pohodlně krokovat ve svém IDE.
 
 
 Linter: validace syntaxe šablon .{toc: Linter}
 ==============================================
 
-Projít všechny šablony a zkontrolovat, zda neobsahují syntaktické chyby, vám pomůže nástroj Linter. Spouští se z konzole:
+Pro kontrolu syntaxe všech šablon můžete použít nástroj Linter, který se spouští z konzole:
 
 ```shell
 vendor/bin/latte-lint <cesta>
@@ -265,30 +275,38 @@ vendor/bin/latte-lint <cesta>
 
 Parametrem `--strict` aktivujete [striktní režim|#striktní režim].
 
-Pokud používáte vlastní značky, vytvořte si také vlastní verzi Linteru, např. `custom-latte-lint`:
+Pokud používáte vlastní značky, vytvořte si vlastní verzi Linteru, např. `custom-latte-lint`:
 
 ```php
 #!/usr/bin/env php
 <?php
 
-// zadejte skutečnou cestu k soubor autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// tady přidejte jednotlivá rozšíření
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// zde přidejte svá rozšíření
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternativně můžete předat vlastní objekt `Latte\Engine` do Linteru:
+
+```php
+$latte = new Latte\Engine;
+// zde nakonfigurujeme objekt $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Načítání šablon z řetězce
 =========================
 
-Potřebujete načítat šablony z řetězců místo souborů, třeba pro účely testování? Pomůže vám [StringLoader|extending-latte#stringloader]:
+Pro načítání šablon z řetězců, například pro účely testování, můžete použít [StringLoader|extending-latte#stringloader]:
 
 ```php
 $latte->setLoader(new Latte\Loaders\StringLoader([
@@ -334,4 +352,4 @@ $latte = new Latte\Engine;
 $latte->addProvider('coreParentFinder', $finder);
 ```
 
-Pokud šablona nemá mít layout, oznámí to značkou `{layout none}`.
+Pokud šablona nemá mít layout, použije se značka `{layout none}`.
diff --git a/latte/cs/extending-latte.texy b/latte/cs/extending-latte.texy
index ad40b23768..3a4089c0aa 100644
--- a/latte/cs/extending-latte.texy
+++ b/latte/cs/extending-latte.texy
@@ -2,89 +2,101 @@ Rozšiřujeme Latte
 *****************
 
 .[perex]
-Latte je velmi flexibilní a lze jej rozšířit mnoha způsoby: můžete přidat vlastní filtry, funkce, značky, loadery atd. Ukážeme si jak na to.
+Latte je mimořádně flexibilní šablonovací systém, který můžete přizpůsobit svým potřebám mnoha způsoby. Ať už potřebujete přidat vlastní filtry, funkce, značky nebo změnit způsob načítání šablon, Latte vám to umožní. Pojďme se podívat, jak na to.
 
-Tato kapitola popisuje jednotlivé cesty rozšiřování Latte. Pokud chcete své úpravy znovu použít v různých projektech nebo je sdílet s ostatními, měli byste [vytvořit tzv. rozšíření |creating-extension].
+Tato kapitola vás provede různými metodami rozšíření Latte. Pokud plánujete své rozšíření použít ve více projektech nebo ho sdílet s komunitou, doporučujeme vytvořit [samostatné rozšíření |creating-extension].
 
 
 Kolik cest vede do Říma?
 ========================
 
-Protože některé způsoby rozšíření Latte mohou splývat, zkusíme si nejprve vysvětlit rozdíly mezi nimi. Jako příklad se pokusíme implementovat generátor *Lorem ipsum*, kterému předáme počet slov, jenž má vygenerovat.
+Jelikož některé způsoby rozšíření Latte mohou být podobné, pojďme si nejprve objasnit rozdíly mezi nimi. Jako příklad implementujeme generátor textu *Lorem ipsum*, kterému předáme požadovaný počet slov.
 
-Hlavní konstrukcí jazyka Latte je značka (tag). Generátor můžeme implementovat rozšířením jazyka Latte o nový tag:
+Základním stavebním kamenem jazyka Latte je značka (tag). Generátor bychom mohli implementovat jako novou značku:
 
 ```latte
 {lipsum 40}
 ```
+Tato značka by fungovala dobře, ale nemusí být dostatečně flexibilní, protože ji nelze použít ve výrazech. Mimochodem, v praxi je potřeba vytvářet nové značky jen zřídka, což je dobrá zpráva, protože jde o složitější způsob rozšíření.
 
-Tag bude skvěle fungovat. Nicméně generátor v podobě tagu nemusí být dostatečně flexibilní, protože jej nelze použít ve výrazu. Mimochodem v praxi potřebujete tagy vytvářet jen zřídka; a to je dobrá zpráva, protože tagy jsou složitějším způsobem rozšíření.
-
-Dobrá, zkusme místo tagu vytvořit filtr:
+Zkusme místo značky vytvořit filtr:
 
 ```latte
 {=40|lipsum}
 ```
 
-Opět validní možnost. Ale filtr by měl předanou hodnotu transformovat na něco jiného. Zde hodnotu `40`, která udává počet vygenerovaných slov, používáme jako argument filtru, nikoli jako hodnotu, kterou chceme transformovat.
+To je také platná možnost. Avšak filtr by měl typicky transformovat předanou hodnotu. V tomto případě hodnotu `40`, která určuje počet generovaných slov, používáme jako argument filtru, nikoli jako hodnotu k transformaci.
 
-Tak zkusíme použít funkci:
+Pojďme tedy zkusit funkci:
 
 ```latte
 {lipsum(40)}
 ```
 
-To je ono! Pro tento konkrétní příklad je vytvoření funkce ideálním způsobem rozšíření. Můžete ji volat kdekoli, kde je akceptován výraz, například:
+To je ono! Pro tento konkrétní případ je vytvoření funkce ideálním způsobem rozšíření. Můžete ji volat kdekoli, kde je povolen výraz, například:
 
 ```latte
 {var $text = lipsum(40)}
 ```
 
+Tento příklad ukazuje, že výběr správného způsobu rozšíření závisí na konkrétním použití. Nyní se pojďme podívat na jednotlivé metody podrobněji.
+
 
 Filtry
 ======
 
-Filtr vytvoříme zaregistrováním jeho názvu a libovolného PHP callable, třeba funkce:
+Filtry jsou mocné nástroje pro transformaci dat přímo v šabloně. Vytvořit vlastní filtr je jednoduché:
 
 ```php
 $latte = new Latte\Engine;
-$latte->addFilter('shortify', fn(string $s) => mb_substr($s, 0, 10)); // zkrátí text na 10 písmen
+$latte->addFilter('shortify', fn(string $s) => mb_substr($s, 0, 10)); // zkrátí text na 10 znaků
 ```
 
-V tomto případě by bylo šikovnější, kdyby filtr přijímal další parametr:
+V tomto případě by bylo užitečné, kdyby filtr přijímal další parametr:
 
 ```php
 $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len));
 ```
 
-V šabloně se potom volá takto:
+V šabloně se pak volá takto:
 
 ```latte
 <p>{$text|shortify}</p>
 <p>{$text|shortify:100}</p>
 ```
 
-Jak vidíte, funkce obdrží levou stranu filtru před pipe `|` jako první argument a argumenty předané filtru za `:` jako další argumenty.
+Všimněte si, že:
+- První argument filtru je vždy hodnota nalevo od `|`
+- Další argumenty se předávají za dvojtečkou
+- Filtry mohou mít libovolný počet argumentů, včetně volitelných
+
+Pokud filtr vrací řetězec v HTML, můžete jej označit tak, aby jej Latte automaticky (a tedy dvojitě) neescapovalo. Tím se vyhnete nutnosti používat v šabloně `|noescape`.
+Nejjednodušší způsob je obalit řetězec do objektu `Latte\Runtime\Html`, alternativou jsou [Kontextové filtry|#Kontextové filtry].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount Kč</i>"));
+```
 
-Funkce představující filtr může samozřejmě přijímat libovolný počet parametrů, podporovány jsou i variadic parametry.
+.[note]
+Filtr musí v takovém případě zajistit správné escapování dat.
 
 
 Filtry pomocí třídy
 -------------------
 
-Druhým způsobem definice filtru je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFilter`:
+Alternativním způsobem definice filtru je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFilter`:
 
 ```php
 class TemplateParameters
 {
 	public function __construct(
-		// parameters
+		// parametry
 	) {}
 
 	#[Latte\Attributes\TemplateFilter]
 	public function shortify(string $s, int $len = 10): string
 	{
-		return mb_substr($s, 0, $len);
+		return mb_substr($s, 0, $len) . (mb_strlen($s) > $len ? '...' : '');
 	}
 }
 
@@ -92,11 +104,13 @@ $params = new TemplateParameters(/* ... */);
 $latte->render('template.latte', $params);
 ```
 
+Tento přístup je zvláště užitečný, když máte více filtrů nebo když filtry potřebují přístup ke sdíleným zdrojům.
+
 
 Zavaděč filtrů
 --------------
 
-Místo registrace jednotlivých filtrů lze vytvořit tzv. zavaděč, což je funkce, které se zavolá s názvem filtru jako argumentem a vrátí jeho PHP callable, nebo null.
+Místo registrace jednotlivých filtrů lze vytvořit tzv. zavaděč. Jde o funkci, která se volá s názvem filtru jako argumentem a vrací jeho PHP callable, nebo null.
 
 ```php
 $latte->addFilterLoader([new Filters, 'load']);
@@ -121,11 +135,13 @@ class Filters
 }
 ```
 
+Tento přístup umožňuje dynamicky načítat filtry podle potřeby, což může být užitečné v rozsáhlých aplikacích.
+
 
 Kontextové filtry
 -----------------
 
-Kontextový filtr je takový, který v prvním parametru přijímá objekt [api:Latte\Runtime\FilterInfo] a teprve po něm následují další parametry jako u klasických filtrů. Registruje se stejný způsobem, Latte samo rozpozná, že filtr je kontextový:
+Kontextové filtry jsou speciální typ filtrů, které mají přístup k dodatečným informacím o kontextu, ve kterém jsou použity:
 
 ```php
 use Latte\Runtime\FilterInfo;
@@ -137,20 +153,20 @@ $latte->addFilter('foo', function (FilterInfo $info, string $str): string {
 
 Kontextové filtry mohou zjišťovat a měnit content-type, který obdrží v proměnné `$info->contentType`. Pokud se filtr volá klasicky nad proměnnou (např. `{$var|foo}`), bude `$info->contentType` obsahovat null.
 
-Filtr by měl nejprve ověřit, zda content-type vstupního řetězce podporuje. A může ho také změnit. Příklad filtru, který přijímá text (nebo null) a vrací HTML:
+Filtr by měl nejprve ověřit, zda podporuje content-type vstupního řetězce. Může ho také změnit. Příklad filtru, který přijímá text (nebo null) a vrací HTML:
 
 ```php
 use Latte\Runtime\FilterInfo;
 
 $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
-	// nejprve oveříme, zda je vstupem content-type text
+	// nejprve ověříme, zda je vstupem content-type text
 	if (!in_array($info->contentType, [null, ContentType::Text])) {
 		throw new Exception("Filter |money used in incompatible content type $info->contentType.");
 	}
 
 	// změníme content-type na HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount Kč</i>";
 });
 ```
 
@@ -163,9 +179,9 @@ Všechny filtry, které se používají nad [bloky|tags#block] (např. jako `{bl
 Funkce
 ======
 
-V Latte lze standardně používat všechny nativní funkce z PHP, pokud to nezakáže sandbox. Ale zároveň si můžete definovat funkce vlastní. Mohou přepsat funkce nativní.
+V Latte lze standardně používat všechny nativní funkce PHP, pokud to nezakáže sandbox. Zároveň si můžete definovat vlastní funkce, které mohou přepsat i nativní funkce.
 
-Funkci vytvoříme zaregistrováním jejího názvu a libovolného PHP callable:
+Funkci vytvoříme registrací jejího názvu a libovolného PHP callable:
 
 ```php
 $latte = new Latte\Engine;
@@ -174,7 +190,7 @@ $latte->addFunction('random', function (...$args) {
 });
 ```
 
-Použití je pak stejné, jako když voláte PHP funkci:
+Použití je pak stejné jako při volání PHP funkce:
 
 ```latte
 {random(jablko, pomeranč, citron)} // vypíše například: jablko
@@ -184,13 +200,13 @@ Použití je pak stejné, jako když voláte PHP funkci:
 Funkce pomocí třídy
 -------------------
 
-Druhým způsobem definice funkce je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFunction`:
+Alternativním způsobem definice funkce je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFunction`:
 
 ```php
 class TemplateParameters
 {
 	public function __construct(
-		// parameters
+		// parametry
 	) {}
 
 	#[Latte\Attributes\TemplateFunction]
@@ -204,17 +220,19 @@ $params = new TemplateParameters(/* ... */);
 $latte->render('template.latte', $params);
 ```
 
+Tento přístup je užitečný pro organizaci souvisejících funkcí a sdílení zdrojů mezi nimi.
+
 
 Loadery
 =======
 
-Loadery jsou zodpovědné za načítání šablon ze zdroje, například ze souborového systému. Nastaví se metodou `setLoader()`:
+Loadery jsou zodpovědné za načítání šablon ze zdroje, například ze souborového systému. Nastavují se metodou `setLoader()`:
 
 ```php
 $latte->setLoader(new MyLoader);
 ```
 
-Vestavěné loadery jsou tyto:
+Latte nabízí tyto vestavěné loadery:
 
 
 FileLoader
@@ -222,7 +240,7 @@ FileLoader
 
 Výchozí loader. Načítá šablony ze souborového systému.
 
-Přístup k souborům je možné omezit nastavením základního adresáře:
+Přístup k souborům lze omezit nastavením základního adresáře:
 
 ```php
 $latte->setLoader(new Latte\Loaders\FileLoader($templateDir));
@@ -233,7 +251,7 @@ $latte->render('test.latte');
 StringLoader
 ------------
 
-Načítá šablony z řetězců. Tento loader je velmi užitečný pro testování. Lze jej také použít pro malé projekty, kde může mít smysl ukládat všechny šablony do jediného souboru PHP.
+Načítá šablony z řetězců. Tento loader je velmi užitečný pro testování. Lze jej také použít pro menší projekty, kde může být výhodné ukládat všechny šablony do jediného PHP souboru.
 
 ```php
 $latte->setLoader(new Latte\Loaders\StringLoader([
@@ -262,20 +280,20 @@ Loader je třída, která implementuje rozhraní [api:Latte\Loader].
 Tagy (makra)
 ============
 
-Jednou z nejzajímavějších funkcí šablonovacího jádra je možnost definovat nové jazykové konstrukce pomocí značek. Je to také složitější funkčnost a je třeba pochopit, jak Latte interně funguje.
+Jednou z nejzajímavějších funkcí šablonovacího jádra je možnost definovat nové jazykové konstrukce pomocí značek. Je to také složitější funkcionalita a vyžaduje pochopení vnitřního fungování Latte.
 
-Většinou však značka není potřeba:
-- pokud by měla generovat nějaký výstup, použijte místo ní [funkci|#funkce]
-- pokud měla upravovat nějaký vstup a vracet ho, použijte místo toho [filtr|#filtry]
-- pokud měla upravovat oblast textu, obalte jej značkou [`{block}`|tags#block] a použijte [filtr|#Kontextové filtry]
-- pokud neměla nic vypisovat, ale pouze volat funkci, zavolejte ji pomocí [`{do}`|tags#do]
+Ve většině případů však značka není potřeba:
+- pokud má generovat nějaký výstup, použijte místo ní [funkci|#funkce]
+- pokud má upravovat nějaký vstup a vracet ho, použijte [filtr|#filtry]
+- pokud má upravovat oblast textu, obalte jej značkou [`{block}`|tags#block] a použijte [filtr|#Kontextové filtry]
+- pokud nemá nic vypisovat, ale pouze volat funkci, použijte [`{do}`|tags#do]
 
-Pokud přesto chcete vytvořit tag, skvěle! Vše podstatné najdete v kapitole [Vytváříme Extension|creating-extension].
+Pokud se přesto rozhodnete vytvořit tag, skvělé! Vše potřebné najdete v kapitole [Vytváříme Extension|creating-extension].
 
 
 Průchody kompilátoru
 ====================
 
-Průchody kompilátoru jsou funkce, které modifikují AST nebo sbírají v nich informace. V Latte je takto implementován například sandbox: projde všechny uzly AST, najde volání funkcí a metod a nahradí je za jím kontrolované volání.
+Průchody kompilátoru jsou funkce, které modifikují AST (abstraktní syntaktický strom) nebo z něj sbírají informace. V Latte je takto implementován například sandbox: projde všechny uzly AST, najde volání funkcí a metod a nahradí je za kontrolovaná volání.
 
-Stejně jako v případě značek se jedná o složitější funkcionalitu a je potřeba pochopit, jak funguje Latte pod kapotou. Vše podstatné najdete v kapitole [Vytváříme Extension|creating-extension].
+Stejně jako v případě značek se jedná o složitější funkcionalitu, která vyžaduje pochopení vnitřního fungování Latte. Vše potřebné najdete v kapitole [Vytváříme Extension|creating-extension].
diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy
index b7a86927f4..108da2e117 100644
--- a/latte/cs/filters.texy
+++ b/latte/cs/filters.texy
@@ -2,111 +2,111 @@ Latte filtry
 ************
 
 .[perex]
-V šablonách můžeme používat funkce, které pomáhají upravit nebo přeformátovat data do výsledné podoby. Říkáme jim *filtry*.
+Filtry v šablonách Latte pomáhají upravit nebo přeformátovat data do požadované podoby
 
 .[table-latte-filters]
 |## Transformace
-| `batch`      | [výpis lineárních dat do tabulky |#batch]
-| `breakLines` | [Před konce řádku přidá HTML odřádkování |#breakLines]
+| `batch`      | [rozdělí lineární data do bloků |#batch]
+| `breakLines` | [přidá HTML odřádkování za konce řádků |#breakLines]
 | `bytes`      | [formátuje velikost v bajtech |#bytes]
-| `clamp`      | [ohraničí hodnotu do daného rozsahu |#clamp]
-| `dataStream` | [konverze pro Data URI protokol |#datastream]
-| `date`       | [formátuje datum |#date]
+| `clamp`      | [omezí hodnotu do daného rozsahu |#clamp]
+| `dataStream` | [převede data do formátu Data URI |#datastream]
+| `date`       | [formátuje datum a čas |#date]
 | `explode`    | [rozdělí řetězec na pole podle oddělovače |#explode]
-| `first`      | [vrací první prvek pole nebo znak řetězce |#first]
+| `first`      | [vrátí první prvek pole nebo znak řetězce |#first]
+| `group`      | [seskupí data podle zadaných kritérií |#group]
 | `implode`    | [spojí pole do řetězce |#implode]
-| `indent`     | [odsadí text zleva o daný počet tabulátorů |#indent]
+| `indent`     | [odsadí text zleva |#indent]
 | `join`       | [spojí pole do řetězce |#implode]
-| `last`       | [vrací poslední prvek pole nebo znak řetězce |#last]
-| `length`     | [vrací délku řetězce ve znacích nebo pole |#length]
+| `last`       | [vrátí poslední prvek pole nebo znak řetězce |#last]
+| `length`     | [vrátí délku řetězce nebo počet prvků pole |#length]
+| `localDate`  | [formátuje datum a čas podle národního prostředí |#localDate]
 | `number`     | [formátuje číslo |#number]
 | `padLeft`    | [doplní řetězec zleva na požadovanou délku |#padLeft]
 | `padRight`   | [doplní řetězec zprava na požadovanou délku |#padRight]
-| `random`     | [vrací náhodný prvek pole nebo znak řetězce |#random]
-| `repeat`     | [opakování řetězce |#repeat]
-| `replace`    | [zamění výskyty hledaného řetězce |#replace]
-| `replaceRE`  | [zamění výskyty dle regulárního výrazu |#replaceRE]
-| `reverse`    | [obrátí UTF‑8 řetězec nebo pole |#reverse]
+| `random`     | [vrátí náhodný prvek pole nebo znak řetězce |#random]
+| `repeat`     | [opakuje řetězec |#repeat]
+| `replace`    | [nahradí výskyty hledaného řetězce |#replace]
+| `replaceRE`  | [nahradí výskyty podle regulárního výrazu |#replaceRE]
+| `reverse`    | [obrátí pořadí znaků v řetězci nebo prvků v poli |#reverse]
 | `slice`      | [extrahuje část pole nebo řetězce |#slice]
 | `sort`       | [seřadí pole |#sort]
-| `spaceless`  | [odstraní bílé místo |#spaceless], podobně jako značka [spaceless |tags] tag
+| `spaceless`  | [odstraní nadbytečné bílé znaky |#spaceless]
 | `split`      | [rozdělí řetězec na pole podle oddělovače |#explode]
-| `strip`      | [odstraní bílé místo |#spaceless]
-| `stripHtml`  | [odstraní HTML značky a HTML entity převede na znaky |#stripHtml]
+| `strip`      | [odstraní nadbytečné bílé znaky |#spaceless]
+| `stripHtml`  | [odstraní HTML značky a převede entity na znaky |#stripHtml]
 | `substr`     | [vrátí část řetězce |#substr]
-| `trim`       | [odstraní počáteční a koncové mezery či jiné znaky |#trim]
-| `translate`  | [překlad do jiných jazyků |#translate]
-| `truncate`   | [zkrátí délku se zachováním slov |#truncate]
-| `webalize`   | [upraví UTF‑8 řetězec do tvaru používaného v URL |#webalize]
+| `trim`       | [odstraní bílé znaky na začátku a konci řetězce |#trim]
+| `translate`  | [přeloží text do jiného jazyka |#translate]
+| `truncate`   | [zkrátí text na danou délku se zachováním slov |#truncate]
+| `webalize`   | [upraví řetězec pro použití v URL |#webalize]
 
 .[table-latte-filters]
 |## Velikost písmen
-| `capitalize` | [malá písmena, první písmeno ve slovech velké |#capitalize]
+| `capitalize` | [převede první písmeno každého slova na velké |#capitalize]
 | `firstUpper` | [převede první písmeno na velké |#firstUpper]
-| `lower`      | [převede na malá písmena |#lower]
-| `upper`      | [převede na velká písmena |#upper]
+| `lower`      | [převede text na malá písmena |#lower]
+| `upper`      | [převede text na velká písmena |#upper]
 
 .[table-latte-filters]
 |## Zaokrouhlování
-| `ceil`       | [zaokrouhlí číslo nahoru na danou přesnost |#ceil]
-| `floor`      | [zaokrouhlí číslo dolů na danou přesnost |#floor]
-| `round`      | [zaokrouhlí číslo na danou přesnost |#round]
+| `ceil`       | [zaokrouhlí číslo nahoru |#ceil]
+| `floor`      | [zaokrouhlí číslo dolů |#floor]
+| `round`      | [zaokrouhlí číslo |#round]
 
 .[table-latte-filters]
 |## Escapování
 | `escapeUrl`  | [escapuje parametr v URL |#escapeUrl]
-| `noescape`   | [vypíše proměnnou bez escapování |#noescape]
+| `noescape`   | [vypne automatické escapování |#noescape]
 | `query`      | [generuje query string v URL |#query]
 
-Dále existují escapovací filtry pro HTML (`escapeHtml` a `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) a iCalendar (`escapeICal`), které Latte používá samo díky [kontextově sensitivnímu escapování|safety-first#Kontextově sensitivní escapování] a nemusíte je zapisovat.
+Latte automaticky používá escapovací filtry pro HTML (`escapeHtml` a `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) a iCalendar (`escapeICal`) díky [kontextově sensitivnímu escapování|safety-first#Kontextově sensitivní escapování]. Tyto filtry není třeba explicitně zapisovat.
 
 .[table-latte-filters]
 |## Bezpečnost
-| `checkUrl`   | [ošetří URL adresu od nebezpečných vstupů |#checkUrl]
-| `nocheck`    | [předejde automatickému ošetření URL adresy |#nocheck]
-
-Latte atributy `src` a `href` [kontroluje automaticky |safety-first#Kontrola odkazů], takže filtr `checkUrl` téměř nemusíte používat.
+| `checkUrl`   | [zkontroluje a případně upraví URL adresu |#checkUrl]
+| `nocheck`    | [vypne automatickou kontrolu URL adresy |#nocheck]
 
 
 .[note]
-Všechny výchozí filtry jsou určeny pro řetězce v kódování UTF‑8.
+Všechny výchozí filtry jsou navrženy pro práci s řetězci v kódování UTF-8.
 
 
 Použití
 =======
 
-Filtry se zapisují za svislítko (může být před ním mezera):
+Filtry se aplikují pomocí svislítka za proměnnou nebo výrazem:
 
 ```latte
 <h1>{$heading|upper}</h1>
 ```
 
-Filtry (ve starších verzích helpery) lze zřetězit a poté se aplikují v pořadí od levého k pravému:
+Filtry lze řetězit, v takovém případě se aplikují zleva doprava:
 
 ```latte
 <h1>{$heading|lower|capitalize}</h1>
 ```
 
-Parametry se zadávají za jménem filtru oddělené dvojtečkami nebo čárkami:
+Parametry filtrů se zadávají za dvojtečkou:
 
 ```latte
 <h1>{$heading|truncate:20,''}</h1>
 ```
 
-Filtry lze aplikovat i na výraz:
+Filtry lze použít i na výrazy:
 
 ```latte
-{var $name = ($title|upper) . ($subtitle|lower)}</h1>
+{var $name = ($title|upper) . ($subtitle|lower)}
 ```
 
-[Vlastní filtry|extending-latte#filtry] lze registrovat tímto způsobem:
+[Vlastní filtry|extending-latte#filtry] se registrují následovně:
 
 ```php
 $latte = new Latte\Engine;
 $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len));
 ```
 
-V šabloně se potom volá takto:
+V šabloně se pak volají stejně jako vestavěné filtry:
 
 ```latte
 <p>{$text|shortify}</p>
@@ -118,9 +118,9 @@ Filtry
 ======
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
-Filtr, který zjednodušuje výpis lineárních dat do podoby tabulky. Vrací pole polí se zadaným počtem položek. Pokud zadáte druhý parametr, použije se k doplnění chybějících položek na posledním řádku.
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
+Filtr `batch` usnadňuje výpis lineárních dat do tabulkové struktury. Vrací pole polí s požadovaným počtem položek. Pokud zadáte druhý parametr, použije se k doplnění chybějících položek v posledním řádku.
 
 ```latte
 {var $items = ['a', 'b', 'c', 'd', 'e']}
@@ -135,7 +135,7 @@ Filtr, který zjednodušuje výpis lineárních dat do podoby tabulky. Vrací po
 </table>
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
 <table>
@@ -152,10 +152,12 @@ Vypíše:
 </table>
 ```
 
+Viz také [#group] a značka [iterateWhile|tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
-Přidává před každý znak nového řádku HTML značku `<br>`
+Filtr `breakLines` vkládá HTML značku `<br>` před každý znak nového řádku.
 
 ```latte
 {var $s = "Text & with \n newline"}
@@ -163,19 +165,21 @@ Přidává před každý znak nového řádku HTML značku `<br>`
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formátuje velikost v bajtech do lidsky čitelné podoby.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Filtr `bytes` formátuje velikost v bajtech do lidsky čitelné podoby. Pokud je nastaveno [národní prostředí |develop#locale], použijí se odpovídající oddělovače desetinných míst a tisíců.
 
 ```latte
-{$size|bytes}     0 B, 10 B, …
-{$size|bytes:2}   1.25 GB, …
+{$size|bytes}     0 B, 1.25 GB, …
+{$size|bytes:0}   10 B, 1 GB, …
 ```
 
+Viz také [#number].
 
-ceil(int precision = 0) .[filter]
----------------------------------
-Zaokrouhlí číslo nahoru na danou přesnost.
+
+ceil(int $precision=0) .[filter]
+--------------------------------
+Filtr `ceil` zaokrouhlí číslo nahoru na danou přesnost.
 
 ```latte
 {=3.4|ceil}         {* vypíše 4      *}
@@ -188,7 +192,7 @@ Viz také [#floor], [#round].
 
 capitalize .[filter]
 --------------------
-Slova budou začínat velkými písmeny, všechny zbývající znaky budou malá. Vyžaduje PHP rozšíření `mbstring`.
+Filtr `capitalize` upraví text tak, že první písmeno každého slova bude velké a zbývající malá. Vyžaduje PHP rozšíření `mbstring`.
 
 ```latte
 {='i like LATTE'|capitalize}  {* vypíše 'I Like Latte' *}
@@ -199,46 +203,48 @@ Viz také [#firstUpper], [#lower], [#upper].
 
 checkUrl .[filter]
 ------------------
-Vynutí ošetření URL adresy. Kontroluje, zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a předchází vypsání odkazů, které mohou představovat bezpečnostní riziko.
+Filtr `checkUrl` zajistí kontrolu a případné ošetření URL adresy. Ověří, zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a zabrání vypsání odkazů, které by mohly představovat bezpečnostní riziko.
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">kontrolované</a>
-<a data-href="{$link}">nekontrolované</a>
+<a data-href={$link|checkUrl}>kontrolované</a>
+<a data-href={$link}>nekontrolované</a>
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
 <a data-href="">kontrolované</a>
 <a data-href="javascript:window.close()">nekontrolované</a>
 ```
 
+Latte automaticky [kontroluje atributy |safety-first#Kontrola odkazů] `src` a `href`, takže filtr `checkUrl` většinou není nutné explicitně uvádět.
+
 Viz také [#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
-Ohraničí hodnotu do daného inkluzivního rozsahu min a max.
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
+Filtr `clamp` omezí hodnotu do zadaného inkluzivního rozsahu min a max.
 
 ```latte
 {$level|clamp: 0, 255}
 ```
 
-Existuje také jako [funkce|functions#clamp].
+K dispozici je také jako [funkce|functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
-Konvertuje obsah do data URI scheme. Pomocí něj lze do HTML nebo CSS vkládat obrázky bez nutnosti linkovat externí soubory.
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
+Filtr `dataStream` konvertuje obsah do schématu data URI. To umožňuje vkládat obrázky přímo do HTML nebo CSS bez nutnosti odkazovat na externí soubory.
 
-Mějme v proměnné obrázek `$img = Image::fromFile('obrazek.gif')`, poté
+Pokud máme v proměnné obrázek `$img = Image::fromFile('obrazek.gif')`, potom
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
-Vypíše například:
+vypíše například:
 
 ```latte
 <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
@@ -250,19 +256,20 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Vyžaduje PHP rozšíření `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Formátuje datum podle masky buď ve tvaru používaném PHP funkcí [php:strftime] nebo [php:date]. Filtr přijímá datum buď ve formátu UNIX timestamp, v podobě řetězce nebo jako objekt `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Filtr `date` formátuje datum a čas podle zadané masky, kterou používá PHP funkce [php:date]. Filtr akceptuje datum ve formátu UNIX timestamp, jako řetězec nebo objekt typu `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Viz také [#localDate].
+
 
 escapeUrl .[filter]
 -------------------
-Escapuje proměnnou pro použití jakožto parametru v URL.
+Filtr `escapeUrl` escapuje proměnnou pro bezpečné použití jako parametr v URL.
 
 ```latte
 <a href="http://example.com/{$name|escapeUrl}">{$name}</a>
@@ -271,15 +278,15 @@ Escapuje proměnnou pro použití jakožto parametru v URL.
 Viz také [#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
-Rozdělí řetězec na pole podle oddělovače. Alias pro `split`.
+explode(string $separator='') .[filter]
+---------------------------------------
+Filtr `explode` rozdělí řetězec na pole podle zadaného oddělovače. Je to alias pro `split`.
 
 ```latte
 {='one,two,three'|explode:','}    {* vrací ['one', 'two', 'three'] *}
 ```
 
-Pokud je oddělovač prázdný řetězec (výchozí hodnota), bude vstup rozdělen na jednotlivé znaky:
+Pokud je oddělovač prázdný řetězec (výchozí hodnota), vstup se rozdělí na jednotlivé znaky:
 
 ```latte
 {='123'|explode}                  {* vrací ['1', '2', '3'] *}
@@ -296,7 +303,7 @@ Viz také [#implode].
 
 first .[filter]
 ---------------
-Vrací první prvek pole nebo znak řetězce:
+Filtr `first` vrací první prvek pole nebo první znak řetězce:
 
 ```latte
 {=[1, 2, 3, 4]|first}    {* vypíše 1 *}
@@ -306,9 +313,9 @@ Vrací první prvek pole nebo znak řetězce:
 Viz také [#last], [#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
-Zaokrouhlí číslo dolů na danou přesnost.
+floor(int $precision=0) .[filter]
+---------------------------------
+Filtr `floor` zaokrouhlí číslo dolů na danou přesnost.
 
 ```latte
 {=3.5|floor}        {* vypíše 3      *}
@@ -321,7 +328,7 @@ Viz také [#ceil], [#round].
 
 firstUpper .[filter]
 --------------------
-Převede první písmeno na velká. Vyžaduje PHP rozšíření `mbstring`.
+Filtr `firstUpper` převede první písmeno na velké. Vyžaduje PHP rozšíření `mbstring`.
 
 ```latte
 {='the latte'|firstUpper}  {* vypíše 'The latte' *}
@@ -330,9 +337,28 @@ Převede první písmeno na velká. Vyžaduje PHP rozšíření `mbstring`.
 Viz také [#capitalize], [#lower], [#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
-Vrátí řetězec, který je zřetězením položek sekvence. Alias pro `join`.
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Filtr `group` umožňuje seskupit data podle různých kritérií.
+
+V tomto příkladu se řádky v tabulce seskupují podle sloupce `categoryId`. Výstupem je pole polí, kde klíčem je hodnota ve sloupci `categoryId`. [Přečtěte si podrobný návod|cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Viz také [#batch], funkce [group|functions#group] a značka [iterateWhile|tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
+Filtr `implode` spojí prvky pole do řetězce. Je to alias pro `join`.
 
 ```latte
 {=[1, 2, 3]|implode}      {* vypíše '123' *}
@@ -346,9 +372,9 @@ Můžete také použít alias `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
-Odsadí text zleva o daný počet tabulátorů nebo jiných znaků, které můžeme uvést ve druhém argumentu. Prázdné řádky nejsou odsazeny.
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
+Filtr `indent` odsadí text zleva o zadaný počet tabulátorů nebo jiných znaků. Prázdné řádky nejsou odsazeny.
 
 ```latte
 <div>
@@ -358,7 +384,7 @@ Odsadí text zleva o daný počet tabulátorů nebo jiných znaků, které můž
 </div>
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
 <div>
@@ -369,7 +395,7 @@ Vypíše:
 
 last .[filter]
 --------------
-Vrací poslední prvek pole nebo znak řetězce:
+Filtr `last` vrací poslední prvek pole nebo poslední znak řetězce:
 
 ```latte
 {=[1, 2, 3, 4]|last}    {* vypíše 4 *}
@@ -381,13 +407,12 @@ Viz také [#first], [#random].
 
 length .[filter]
 ----------------
-Vrátí délku řetězce nebo pole.
-
-- pro řetězce vrátí délku v UTF‑8 znacích
-- pro pole vrátí počet položek
-- pro objekty, které implementují rozhraní Countable, použije návratovou hodnotu metody count()
-- pro objekty, které implementují rozhraní IteratorAggregate, použije návratovou hodnotu funkce iterator_count()
+Filtr `length` vrátí délku řetězce nebo počet prvků v poli.
 
+- pro řetězce vrátí počet unicode znaků
+- pro pole vrátí počet prvků
+- pro objekty implementující rozhraní Countable použije návratovou hodnotu metody count()
+- pro objekty implementující rozhraní IteratorAggregate použije návratovou hodnotu funkce iterator_count()
 
 ```latte
 {if ($users|length) > 10}
@@ -396,9 +421,71 @@ Vrátí délku řetězce nebo pole.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Filtr `localDate` formátuje datum a čas podle [národního prostředí |develop#locale]. To zajišťuje konzistentní a lokalizované zobrazení časových údajů napříč různými jazyky a regiony. Filtr přijímá datum jako UNIX timestamp, řetězec nebo objekt typu `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Bez parametrů se datum vypíše v úrovni `long` (viz dále).
+
+**a) použití formátu**
+
+Parametr `format` definuje, které časové složky se mají zobrazit. Používá písmena jako kódy, jejichž počet opakování ovlivňuje šířku výstupu:
+
+| rok | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| měsíc | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `srp` / `srpen`
+| den | `d` / `dd` / `E` / `EEEE` |  `1` / `01` / `ne` / `neděle`
+| hodina | `j` /  `H` / `h` | preferovaná / 24hodinová / 12hodinová
+| minuta | `m` / `mm` | `5` / `05` <small>(2 číslice v kombinaci se sekundami)</small>
+| sekunda | `s` / `ss` | `8` / `08` <small>(2 číslice v kombinaci s minutami)</small>
+
+Pořadí kódů ve formátu nemá vliv na pořadí složek ve výstupu, protože to se řídí zvyklostmi národního prostředí. Formát je tedy na něm nezávislý. Například formát `yyyyMMMMd` v prostředí `en_US` vypíše `April 15, 2024`, zatímco v prostředí `cs_CZ` vypíše `15. dubna 2024`:
+
+| locale: | cs_CZ | en_US
+|---
+| `format: 'dMy'` | 10. 8. 2024 | 8/10/2024
+| `format: 'yM'` | 8/2024 | 8/2024
+| `format: 'yyyyMMMM'` | srpen 2024 | August 2024
+| `format: 'MMMM'` | srpen | August
+| `format: 'jm'` | 17:22 | 5:22 PM
+| `format: 'Hm'` | 17:22 | 17:22
+| `format: 'hm'` | 5:22 odp. | 5:22 PM
+
+
+**b) použití přednastavených stylů**
+
+Parametry `date` a `time` určují úroveň podrobnosti pro výpis data a času. K dispozici jsou úrovně: `full`, `long`, `medium`, `short`. Můžete nechat vypsat jen datum, jen čas, nebo obojí:
+
+| locale: | cs_CZ | en_US
+|---
+| `date: short` | 23.01.78 | 1/23/78
+| `date: medium` | 23. 1. 1978 | Jan 23, 1978
+| `date: long` | 23. ledna 1978 | January 23, 1978
+| `date: full` | pondělí 23. ledna 1978 | Monday, January 23, 1978
+| `time: short` | 8:30 | 8:30 AM
+| `time: medium` | 8:30:59 | 8:30:59 AM
+| `time: long` | 8:30:59 SEČ | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.78 8:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23. 1. 1978 8:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23. ledna 1978 v 8:30 | January 23, 1978 at 8:30 AM
+
+Pro datum lze použít prefix `relative-` (např. `relative-short`), který pro data blízká současnosti zobrazí `včera`, `dnes` nebo `zítra`, jinak se vypíše standardním způsobem.
+
+```latte
+{$date|localDate: date: relative-short}    {* včera *}
+```
+
+Viz také [#date].
+
+
 lower .[filter]
 ---------------
-Převede řetězec na malá písmena. Vyžaduje PHP rozšíření `mbstring`.
+Filtr `lower` převede řetězec na malá písmena. Vyžaduje PHP rozšíření `mbstring`.
 
 ```latte
 {='LATTE'|lower}   {* vypíše 'latte' *}
@@ -409,18 +496,18 @@ Viz také [#capitalize], [#firstUpper], [#upper].
 
 nocheck .[filter]
 -----------------
-Předejde automatickému ošetření URL adresy. Latte [automaticky kontroluje|safety-first#Kontrola odkazů], zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a předchází vypsání odkazů, které mohou představovat bezpečnostní riziko.
+Filtr `nocheck` vypne automatickou kontrolu URL adresy. Latte standardně [kontroluje |safety-first#Kontrola odkazů], zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a brání vypsání potenciálně nebezpečných odkazů.
 
-Pokud odkaz používá jiné schéma, např. `javascript:` nebo `data:`, a jste si jistí jeho obsahem, můžete kontrolu vypnout pomoci `|nocheck`.
+Pokud odkaz používá jiné schéma, např. `javascript:` nebo `data:`, a jste si jisti jeho obsahem, můžete kontrolu vypnout pomocí `|nocheck`.
 
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">kontrolované</a>
-<a href="{$link|nocheck}">nekontrolované</a>
+<a href={$link}>kontrolované</a>
+<a href={$link|nocheck}>nekontrolované</a>
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
 <a href="">kontrolované</a>
@@ -432,7 +519,7 @@ Viz také [#checkUrl].
 
 noescape .[filter]
 ------------------
-Zakáže automatické escapování.
+Filtr `noescape` vypne automatické escapování.
 
 ```latte
 {var $trustedHtmlString = '<b>hello</b>'}
@@ -440,7 +527,7 @@ Escapovaný: {$trustedHtmlString}
 Neescapovaný: {$trustedHtmlString|noescape}
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
 Escapovaný: &lt;b&gt;hello&lt;/b&gt;
@@ -448,33 +535,81 @@ Neescapovaný: <b>hello</b>
 ```
 
 .[warning]
-Špatné použití filtru `noescape` může vést ke vzniku zranitelnosti XSS! Nikdy jej nepoužívejte, pokud si nejste **zcela jisti** co děláte, a že vypisovaný řetězec pochází z důvěryhodného zdroje.
+Nesprávné použití filtru `noescape` může vést ke zranitelnosti XSS! Používejte jej pouze tehdy, když si jste **naprosto jisti**, že vypisovaný řetězec pochází z důvěryhodného zdroje.
+
+
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Filtr `number` formátuje číslo na zadaný počet desetinných míst. Pokud je nastaveno [národní prostředí |develop#locale], použijí se odpovídající oddělovače desetinných míst a tisíců.
+
+```latte
+{1234.20|number}              1,234
+{1234.20|number:1}            1,234.2
+{1234.20|number:2}            1,234.20
+{1234.20|number:2, ',', ' '}  1 234,20
+```
+
+
+number(string $format) .[filter]
+--------------------------------
+Parametr `format` umožňuje přesně definovat vzhled čísel podle vašich potřeb. K tomu je nutné mít nastavené [národní prostředí |develop#locale]. Formát se skládá z několika speciálních znaků, jejichž kompletní popis najdete v dokumentaci "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
 
+- `0` povinná číslice, vždy se zobrazí, i kdyby to byla nula
+- `#` volitelná číslice, zobrazí se jen tehdy, pokud na tomto místě číslo skutečně je
+- `@` významná číslice, pomáhá zobrazit číslo s určitým počtem platných číslic
+- `.` označuje pozici desetinné čárky (nebo tečky, podle země)
+- `,` slouží k oddělení skupin číslic, nejčastěji tisíců
+- `%` číslo vynásobí 100× a přidá znak procenta
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formátuje číslo na určitý počet desetinných míst. Lze určit znak pro desetinnou čárku a oddělovač tisíců.
+Podívejme se na příklady. V prvním příkladu jsou dvě desetinná místa povinná, ve druhém volitelná. Třetí příklad ukazuje doplnění nulami zleva i zprava, čtvrtý zobrazuje jen existující číslice:
 
 ```latte
-{1234.20 |number}              1,234
-{1234.20 |number:1}            1,234.2
-{1234.20 |number:2}            1,234.20
-{1234.20 |number:2, ',', ' '}  1 234,20
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
 ```
 
+Významné číslice určují, kolik číslic bez ohledu na desetinnou čárku má být zobrazeno, přičemž dochází k zaokrouhlování:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
 
-padLeft(int length, string pad = ' ') .[filter]
+Snadný způsob, jak zobrazit číslo jako procenta. Číslo se vynásobí 100× a přidá se znak `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Můžeme definovat odlišný formát pro kladná a záporná čísla, oddělené znakem `;`. Tímto způsobem lze například nastavit, že kladná čísla se mají zobrazovat se znaménkem `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Nezapomeňte, že skutečný vzhled čísel se může lišit podle nastavení země. Například v některých zemích se používá čárka místo tečky jako oddělovač desetinných míst. Tento filtr to automaticky zohlední, takže se o to nemusíte starat.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
-Doplní řetězec do určité délky jiným řetězcem zleva.
+Filtr `padLeft` doplní řetězec zleva na požadovanou délku jiným řetězcem.
 
 ```latte
 {='hello'|padLeft: 10, '123'}  {* vypíše '12312hello' *}
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
-Doplní řetězec do určité délky jiným řetězcem zprava.
+Filtr `padRight` doplní řetězec zprava na požadovanou délku jiným řetězcem.
 
 ```latte
 {='hello'|padRight: 10, '123'}  {* vypíše 'hello12312' *}
@@ -483,18 +618,18 @@ Doplní řetězec do určité délky jiným řetězcem zprava.
 
 query .[filter]
 ---------------
-Dynamicky generuje query string v URL:
+Filtr `query` dynamicky generuje query string v URL:
 
 ```latte
-<a href="http://example.com/?{[name: 'John Doe', age: 43]|query}">click</a>
-<a href="http://example.com/?search={$search|query}">search</a>
+<a href="http://example.com/?{[name: 'John Doe', age: 43]|query}">klikněte</a>
+<a href="http://example.com/?search={$search|query}">hledat</a>
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
-<a href="http://example.com/?name=John+Doe&amp;age=43">click</a>
-<a href="http://example.com/?search=Foo+Bar">search</a>
+<a href="http://example.com/?name=John+Doe&amp;age=43">klikněte</a>
+<a href="http://example.com/?search=Foo+Bar">hledat</a>
 ```
 
 Klíče s hodnotou `null` se vynechají.
@@ -504,7 +639,7 @@ Viz také [#escapeUrl].
 
 random .[filter]
 ----------------
-Vrací náhodný prvek pole nebo znak řetězce:
+Filtr `random` vrací náhodný prvek pole nebo náhodný znak řetězce:
 
 ```latte
 {=[1, 2, 3, 4]|random}    {* vypíše např.: 3 *}
@@ -514,18 +649,18 @@ Vrací náhodný prvek pole nebo znak řetězce:
 Viz také [#first], [#last].
 
 
-repeat(int count) .[filter]
----------------------------
-Opakuje řetězec x-krát.
+repeat(int $count) .[filter]
+----------------------------
+Filtr `repeat` opakuje řetězec zadaný počet krát.
 
 ```latte
 {='hello'|repeat: 3}  {* vypíše 'hellohellohello' *}
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
-Nahradí všechny výskyty vyhledávacího řetězce náhradním řetězcem.
+Filtr `replace` nahradí všechny výskyty hledaného řetězce náhradním řetězcem.
 
 ```latte
 {='hello world'|replace: 'world', 'friend'}  {* vypíše 'hello friend' *}
@@ -538,9 +673,9 @@ Lze provést i více záměn najednou:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
-Provede vyhledávání regulárních výrazů s nahrazením.
+Filtr `replaceRE` provádí nahrazování podle regulárních výrazů.
 
 ```latte
 {='hello world'|replaceRE: '/l.*/', 'l'}  {* vypíše 'hel' *}
@@ -549,19 +684,19 @@ Provede vyhledávání regulárních výrazů s nahrazením.
 
 reverse .[filter]
 -----------------
-Obrátí daný řetězec nebo pole.
+Filtr `reverse` obrátí pořadí znaků v řetězci nebo prvků v poli.
 
 ```latte
 {var $s = 'Nette'}
 {$s|reverse}    {* vypíše 'etteN' *}
 {var $a = ['N', 'e', 't', 't', 'e']}
-{$a|reverse}    {* returns ['e', 't', 't', 'e', 'N'] *}
+{$a|reverse}    {* vrátí ['e', 't', 't', 'e', 'N'] *}
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
-Zaokrouhlí číslo na danou přesnost.
+round(int $precision=0) .[filter]
+---------------------------------
+Filtr `round` zaokrouhlí číslo na zadanou přesnost.
 
 ```latte
 {=3.4|round}        {* vypíše 3      *}
@@ -573,27 +708,27 @@ Zaokrouhlí číslo na danou přesnost.
 Viz také [#ceil], [#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
-Extrahuje část pole nebo řetězce.
+Filtr `slice` extrahuje část pole nebo řetězce.
 
 ```latte
 {='hello'|slice: 1, 2}           {* vypíše 'el' *}
 {=['a', 'b', 'c']|slice: 1, 2}   {* vypíše ['b', 'c'] *}
 ```
 
-Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF‑8.
+Tento filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF-8.
 
-Pokud je start kladný, posloupnost začné posunutá o tento počet od začátku pole/řetezce. Pokud je záporný posloupnost začné posunutá o tolik od konce.
+Pokud je `start` kladný, posloupnost začíná posunutá o tento počet od začátku pole/řetězce. Pokud je záporný, posloupnost začíná posunutá o tolik od konce.
 
-Pokud je zadaný parametr length a je kladný, posloupnost bude obsahovat tolik prvků. Pokud je do této funkce předán záporný parametr length, posloupnost bude obsahovat všechny prvky původního pole, začínající na pozici start a končicí na pozici menší na length prvků od konce pole. Pokud tento parametr nezadáte, posloupnost bude obsahovat všechny prvky původního pole, začínající pozici start.
+Pokud je zadán parametr `length` a je kladný, posloupnost bude obsahovat tolik prvků. Pokud je do této funkce předán záporný parametr `length`, posloupnost bude obsahovat všechny prvky původního pole, začínající na pozici `start` a končící na pozici menší o `length` prvků od konce pole. Pokud tento parametr nezadáte, posloupnost bude obsahovat všechny prvky původního pole, začínající pozicí `start`.
 
-Ve výchozím nastavení filtr změní pořadí a resetuje celočíselného klíče pole. Toto chování lze změnit nastavením preserveKeys na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr.
+Ve výchozím nastavení filtr změní pořadí a resetuje celočíselné klíče pole. Toto chování lze změnit nastavením `preserveKeys` na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr.
 
 
-sort .[filter]
---------------
-Filtr, který seřadí pole. Zachovává asociaci s klíčí.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Filtr `sort` seřadí prvky pole nebo iterátoru a zachová jejich asociační klíče. Při nastaveném [národním prostředí |develop#locale] se řazení řídí jeho pravidly, pokud není specifikována vlastní porovnávací funkce.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -601,7 +736,7 @@ Filtr, který seřadí pole. Zachovává asociaci s klíčí.
 {/foreach}
 ```
 
-Řazené pole v opačném pořadí:
+Pro řazení pole v opačném pořadí:
 
 ```latte
 {foreach ($names|sort|reverse) as $name}
@@ -609,16 +744,42 @@ Filtr, který seřadí pole. Zachovává asociaci s klíčí.
 {/foreach}
 ```
 
-Jako parametr lze předat vlastní porovnávací funkci:
+Můžete specifikovat vlastní porovnávací funkci pro řazení (příklad ukazuje, jak obrátit řazení od největší po nejmenší):
+
+```latte
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
+```
+
+Filtr `|sort` také umožňuje řadit prvky podle klíčů:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Pokud potřebujete seřadit tabulku podle konkrétního sloupce, můžete použít parametr `by`. Hodnota `'name'` v ukázce určuje, že se bude řadit podle `$item->name` nebo `$item['name']`, v závislosti na tom, zda je `$item` objekt nebo pole:
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
 ```
 
+Můžete také definovat callback funkci, která určí hodnotu, podle které se má řadit:
+
+```latte
+{foreach ($items|sort: by: fn($item) => $item->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Stejným způsobem lze využít i parametr `byKey`.
+
 
 spaceless .[filter]
 -------------------
-Odstraní zbytečné bílé místo (mezery) z výstupu. Můžete také použít alias `strip`.
+Filtr `spaceless` odstraní nadbytečné bílé znaky z výstupu. Můžete také použít alias `strip`.
 
 ```latte
 {block |spaceless}
@@ -628,7 +789,7 @@ Odstraní zbytečné bílé místo (mezery) z výstupu. Můžete také použít
 {/block}
 ```
 
-Vypíše:
+Výstup:
 
 ```latte
 <ul> <li>Hello</li> </ul>
@@ -637,7 +798,7 @@ Vypíše:
 
 stripHtml .[filter]
 -------------------
-Převádí HTML na čistý text. Tedy odstraní z něj HTML značky a HTML entity převede na text.
+Filtr `stripHtml` převádí HTML na čistý text. Odstraní HTML značky a převede HTML entity na jejich textovou reprezentaci.
 
 ```latte
 {='<p>one &lt; two</p>'|stripHtml}  {* vypíše 'one < two' *}
@@ -646,18 +807,18 @@ Převádí HTML na čistý text. Tedy odstraní z něj HTML značky a HTML entit
 Výsledný čistý text může přirozeně obsahovat znaky, které představují HTML značky, například `'&lt;p&gt;'|stripHtml` se převede na `<p>`. V žádném případě nevypisujte takto vzniklý text s `|noescape`, protože to může vést ke vzniku bezpečnostní díry.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
-Extrahuje část řetězce. Tento filtr byl nahrazen filtrem [#slice].
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
+Filtr `substr` extrahuje část řetězce. Tento filtr byl nahrazen filtrem [#slice].
 
 ```latte
 {$string|substr: 1, 2}
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
-Překládá výrazy do jiných jazyků. Aby byl filtr k dispozici, je potřeba [nastavit překladač|develop#TranslatorExtension]. Můžete také použít [tagy pro překlad|tags#Překlady].
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
+Filtr `translate` překládá výrazy do jiných jazyků. Aby byl filtr k dispozici, je potřeba [nastavit překladač|develop#TranslatorExtension]. Můžete také použít [tagy pro překlad|tags#Překlady].
 
 ```latte
 <a href="basket">{='Košík'|translate}</a>
@@ -665,9 +826,9 @@ Překládá výrazy do jiných jazyků. Aby byl filtr k dispozici, je potřeba [
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
-Odstraní prázdné znaky (nebo jiné znaky) od začátku a konce řetězce.
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
+Filtr `trim` odstraní bílé znaky (nebo jiné zadané znaky) od začátku a konce řetězce.
 
 ```latte
 {='  I like Latte.  '|trim}    {* vypíše 'I like Latte.' *}
@@ -675,9 +836,9 @@ Odstraní prázdné znaky (nebo jiné znaky) od začátku a konce řetězce.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
-Ořízne řetězec na uvedenou maximální délku, přičemž se snaží zachovávat celá slova. Pokud dojde ke zkrácení řetězce, přidá nakonec trojtečku (lze změnit druhým parametrem).
+Filtr `truncate` zkrátí řetězec na uvedenou maximální délku, přičemž se snaží zachovávat celá slova. Pokud dojde ke zkrácení řetězce, přidá nakonec trojtečku (lze změnit druhým parametrem).
 
 ```latte
 {var $title = 'Hello, how are you?'}
@@ -689,7 +850,7 @@ Ořízne řetězec na uvedenou maximální délku, přičemž se snaží zachov
 
 upper .[filter]
 ---------------
-Převede řetězec na velká písmena. Vyžaduje PHP rozšíření `mbstring`.
+Filtr `upper` převede řetězec na velká písmena. Vyžaduje PHP rozšíření `mbstring`.
 
 ```latte
 {='latte'|upper}  {* vypíše 'LATTE' *}
@@ -700,9 +861,9 @@ Viz také [#capitalize], [#firstUpper], [#lower].
 
 webalize .[filter]
 ------------------
-Upraví UTF‑8 řetězec do tvaru používaného v URL.
+Filtr `webalize` upraví UTF-8 řetězec do tvaru používaného v URL.
 
-Převádí se na ASCII. Převede mezery na pomlčky. Odstraní znaky, které nejsou alfanumerické, podtržítka ani pomlčky. Převede na malá písmena. Také odstraní přední a koncové mezery.
+Převádí znaky na ASCII ekvivalenty. Převádí mezery na pomlčky. Odstraní znaky, které nejsou alfanumerické, podtržítka ani pomlčky. Převádí text na malá písmena. Také odstraní úvodní a koncové bílé znaky.
 
 ```latte
 {var $s = 'Náš 10. produkt'}
diff --git a/latte/cs/functions.texy b/latte/cs/functions.texy
index 1235964104..c4aeeab033 100644
--- a/latte/cs/functions.texy
+++ b/latte/cs/functions.texy
@@ -2,22 +2,24 @@ Latte funkce
 ************
 
 .[perex]
-V šablonách můžeme kromě běžných PHP funkcí používat i tyto další.
+V šablonách Latte můžeme kromě běžných PHP funkcí využívat i další speciální funkce, které rozšiřují možnosti při práci s daty a šablonami.
 
 .[table-latte-filters]
-| `clamp`      | [ohraničí hodnotu do daného rozsahu |#clamp]
-| `divisibleBy`| [zkontroluje, zda je proměnná dělitelná číslem |#divisibleBy]
-| `even`       | [zkontroluje, zda je dané číslo sudé |#even]
-| `first`      | [vrací první prvek pole nebo znak řetězce |#first]
-| `last`       | [vrací poslední prvek pole nebo znak řetězce |#last]
-| `odd`        | [zkontroluje, zda je dané číslo liché |#odd]
+| `clamp`      | [omezí hodnotu do zadaného rozsahu |#clamp]
+| `divisibleBy`| [ověří dělitelnost čísla |#divisibleBy]
+| `even`       | [zkontroluje, zda je číslo sudé |#even]
+| `first`      | [získá první prvek pole nebo znak řetězce |#first]
+| `group`      | [seskupí data podle zadaných kritérií |#group]
+| `hasBlock`   | [ověří existenci bloku |#hasBlock]
+| `last`       | [získá poslední prvek pole nebo znak řetězce |#last]
+| `odd`        | [zkontroluje, zda je číslo liché |#odd]
 | `slice`      | [extrahuje část pole nebo řetězce |#slice]
 
 
 Použití
 =======
 
-Funkce se používají strejně jaké běžné PHP funkce a lze je použít ve všechn výrazech:
+Funkce v Latte se používají stejně jako běžné PHP funkce a lze je využít ve všech výrazech:
 
 ```latte
 <p>{clamp($num, 1, 100)}</p>
@@ -25,14 +27,14 @@ Funkce se používají strejně jaké běžné PHP funkce a lze je použít ve v
 {if odd($num)} ... {/if}
 ```
 
-[Vlastní funkce|extending-latte#funkce] lze registrovat tímto způsobem:
+[Vlastní funkce|extending-latte#funkce] můžete do Latte přidat takto:
 
 ```php
 $latte = new Latte\Engine;
 $latte->addFunction('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len));
 ```
 
-V šabloně se potom volá takto:
+V šabloně pak tuto funkci můžete volat následovně:
 
 ```latte
 <p>{shortify($text)}</p>
@@ -46,7 +48,7 @@ Funkce
 
 clamp(int|float $value, int|float $min, int|float $max): int|float .[method]
 ----------------------------------------------------------------------------
-Ohraničí hodnotu do daného inkluzivního rozsahu min a max.
+Funkce `clamp` omezí hodnotu do zadaného inkluzivního rozsahu mezi `$min` a `$max`.
 
 ```latte
 {=clamp($level, 0, 255)}
@@ -57,7 +59,7 @@ Viz také [filtr clamp|filters#clamp].
 
 divisibleBy(int $value, int $by): bool .[method]
 ------------------------------------------------
-Zkontroluje, zda je proměnná dělitelná číslem.
+Funkce `divisibleBy` ověří, zda je číslo `$value` dělitelné číslem `$by`.
 
 ```latte
 {if divisibleBy($num, 5)} ... {/if}
@@ -66,16 +68,16 @@ Zkontroluje, zda je proměnná dělitelná číslem.
 
 even(int $value): bool .[method]
 --------------------------------
-Zkontroluje, zda je dané číslo sudé.
+Funkce `even` zkontroluje, zda je dané číslo sudé.
 
 ```latte
 {if even($num)} ... {/if}
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
-Vrací první prvek pole nebo znak řetězce:
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
+Funkce `first` vrací první prvek pole nebo první znak řetězce:
 
 ```latte
 {=first([1, 2, 3, 4])}    {* vypíše 1 *}
@@ -85,9 +87,39 @@ Vrací první prvek pole nebo znak řetězce:
 Viz také [#last], [filtr first|filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Funkce `group` seskupí data podle zadaných kritérií.
+
+V tomto příkladu se řádky v tabulce seskupují podle sloupce `categoryId`. Výsledkem je pole polí, kde klíčem je hodnota ve sloupci `categoryId`. [Podrobný návod najdete zde|cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Viz také filtr [group|filters#group].
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Funkce `hasBlock` ověří, zda existuje blok s uvedeným názvem:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Viz také [kontrola existence bloků|template-inheritance#Kontrola existence bloků].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
-Vrací poslední prvek pole nebo znak řetězce:
+Funkce `last` vrací poslední prvek pole nebo poslední znak řetězce:
 
 ```latte
 {=last([1, 2, 3, 4])}    {* vypíše 4 *}
@@ -99,26 +131,26 @@ Viz také [#first], [filtr last|filters#last].
 
 odd(int $value): bool .[method]
 -------------------------------
-Zkontroluje, zda je dané číslo liché.
+Funkce `odd` zkontroluje, zda je dané číslo liché.
 
 ```latte
 {if odd($num)} ... {/if}
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
-Extrahuje část pole nebo řetězce.
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
+Funkce `slice` extrahuje část pole nebo řetězce.
 
 ```latte
 {=slice('hello', 1, 2)}           {* vypíše 'el' *}
 {=slice(['a', 'b', 'c'], 1, 2)}   {* vypíše ['b', 'c'] *}
 ```
 
-Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF‑8.
+Tato funkce funguje podobně jako PHP funkce `array_slice` pro pole nebo `mb_substr` pro řetězce (s fallbackem na `iconv_substr` v režimu UTF-8).
 
-Pokud je start kladný, posloupnost začné posunutá o tento počet od začátku pole/řetezce. Pokud je záporný posloupnost začné posunutá o tolik od konce.
+- Pokud je `$start` kladný, výsledek začíná od tohoto indexu od začátku pole/řetězce. Pokud je záporný, začíná se od konce.
 
-Pokud je zadaný parametr length a je kladný, posloupnost bude obsahovat tolik prvků. Pokud je do této funkce předán záporný parametr length, posloupnost bude obsahovat všechny prvky původního pole, začínající na pozici start a končicí na pozici menší na length prvků od konce pole. Pokud tento parametr nezadáte, posloupnost bude obsahovat všechny prvky původního pole, začínající pozici start.
+- Pokud je `$length` kladný, výsledek bude obsahovat tolik prvků. Pokud je záporný, výsledek bude obsahovat všechny prvky kromě posledních `$length` prvků. Pokud není zadán, výsledek bude obsahovat všechny prvky od `$start` do konce.
 
-Ve výchozím nastavení filtr změní pořadí a resetuje celočíselného klíče pole. Toto chování lze změnit nastavením preserveKeys na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr.
+- Parametr `$preserveKeys` určuje, zda zachovat původní klíče pole. Ve výchozím nastavení (false) jsou číselné klíče resetovány. Řetězcové klíče jsou vždy zachovány bez ohledu na toto nastavení.
diff --git a/latte/cs/recipes.texy b/latte/cs/recipes.texy
index b071f62371..11389d60c2 100644
--- a/latte/cs/recipes.texy
+++ b/latte/cs/recipes.texy
@@ -5,19 +5,19 @@ Tipy a triky
 Editory a IDE
 =============
 
-Pište šablony v editoru nebo IDE, který má podporu pro Latte. Bude to mnohem příjemnější.
+Efektivní práce s Latte šablonami začíná u správně nastaveného vývojového prostředí. Vhodný editor nebo IDE s podporou Latte vám významně usnadní práci a zvýší produktivitu.
 
-- NetBeans IDE má podporu vestavěnou
-- PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte]
-- VS Code: hledejte v markerplace "Nette Latte + Neon" plugin
-- Sublime Text 3: v Package Control najděte a nainstalujte balíček `Nette` a zvolte Latte ve `View > Syntax`
-- ve starých editorech použijte pro soubory .latte zvýrazňování Smarty
+- PhpStorm: v `Settings > Plugins > Marketplace` nainstalujte [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte]
+- VS Code: vyhledejte a nainstalujte [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] nebo [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
+- NetBeans IDE: nativní podpora Latte je součástí instalace
+- Sublime Text 3: přes Package Control nainstalujte balíček `Nette` a v `View > Syntax` zvolte Latte
+- Pro starší editory: použijte zvýrazňování syntaxe pro Smarty u souborů s příponou .latte
 
-Plugin pro PhpStorm je velmi pokročilý a umí výborně napovídat PHP kód. Aby fungoval optimálně, používejte [typované šablony|type-system].
+Plugin pro PhpStorm vyniká pokročilými funkcemi a nabízí vynikající napovídání PHP kódu. Pro jeho optimální funkčnost doporučujeme používat [typované šablony|type-system].
 
 [* latte-phpstorm-plugin.webp *]
 
-Podporu pro Latte najdete také ve webovém zvýrazňovači kódu [Prism.js|https://prismjs.com/#supported-languages] a editoru [Ace|https://ace.c9.io].
+Podporu Latte najdete také v online zvýrazňovači kódu [Prism.js|https://prismjs.com/#supported-languages] a webovém editoru [Ace|https://ace.c9.io].
 
 
 Latte uvnitř JavaScriptu nebo CSS
@@ -37,9 +37,11 @@ Latte lze velmi pohodlně používat i uvnitř JavaScriptu nebo CSS. Jak se vša
 </script>
 ```
 
-**Varianta 1**
+Existuje několik řešení:
 
-Vyhněte se situaci, kdy následuje písmeno hned za `{`, třeba tím, že před něj vložíte mezeru, odřádkování nebo uvozovku:
+**Řešení 1: Oddělení závorek**
+
+Vložte mezeru, odřádkování nebo uvozovku mezi `{` a následující písmeno:
 
 ```latte
 <style>
@@ -53,9 +55,9 @@ Vyhněte se situaci, kdy následuje písmeno hned za `{`, třeba tím, že před
 </script>
 ```
 
-**Varianta 2**
+**Řešení 2: Vypnutí zpracování Latte**
 
-Zcela vypněte zpracování Latte značek uvnitř elementu pomocí [n:syntax |tags#syntax]:
+Použijte atribut [n:syntax |tags#syntax] pro úplné vypnutí zpracování Latte značek v daném elementu:
 
 ```latte
 <script n:syntax="off">
@@ -63,9 +65,9 @@ Zcela vypněte zpracování Latte značek uvnitř elementu pomocí [n:syntax |ta
 </script>
 ```
 
-**Varianta 3**
+**Řešení 3: Změna syntaxe Latte**
 
-Přepněte uvnitř elementu syntax Latte značek na zdvojené složené závorky:
+Přepněte na syntaxi s dvojitými složenými závorkami uvnitř elementu:
 
 ```latte
 <script n:syntax="double">
@@ -75,13 +77,13 @@ Přepněte uvnitř elementu syntax Latte značek na zdvojené složené závorky
 </script>
 ```
 
-V JavaScriptu [se nepíší uvozovky kolem proměnné |tags#Vypsání v JavaScriptu].
+Pamatujte, že v JavaScriptu [se nepoužívají uvozovky kolem proměnných |tags#Vypsání v JavaScriptu].
 
 
-Náhrada `use` klausule v Latte
-==============================
+Náhrada `use` v Latte
+=====================
 
-Jak v Latte nahradit klauzule `use`, které se používají v PHP, abyste nemuseli psát namespace při přistupování k třídě? Příklad v PHP:
+V PHP používáme `use` pro zkrácení zápisu názvů tříd. Jak lze dosáhnout podobného efektu v Latte? Příklad v PHP:
 
 ```php
 use Pets\Model\Dog;
@@ -91,9 +93,9 @@ if ($dog->status === Dog::StatusHungry) {
 }
 ```
 
-**Varianta 1**
+V Latte máme dvě hlavní možnosti:
 
-Místo klausule `use` si uložíme název třídy do proměnné a následně místo `Dog` používáme `$Dog`:
+**Možnost 1: Uložení názvu třídy do proměnné**
 
 ```latte
 {var $Dog = Pets\Model\Dog::class}
@@ -105,9 +107,17 @@ Místo klausule `use` si uložíme název třídy do proměnné a následně mí
 </div>
 ```
 
-**Varianta 2**
+**Možnost 2: Využití instance objektu**
+
+Pokud je `$dog` instancí `Pets\Model\Dog`, můžeme použít:
 
-Pokud je objekt `$dog` instancí `Pets\Model\Dog`, pak lze použít `{if $dog->status === $dog::StatusHungry}`.
+```latte
+<div>
+	{if $dog->status === $dog::StatusHungry}
+		...
+	{/if}
+</div>
+```
 
 
 Generování XML v Latte
@@ -121,12 +131,12 @@ Latte může generovat jakýkoli textový formát (HTML, XML, CSV, iCal atd.), n
 ...
 ```
 
-Poté můžeme například vygenerovat sitemapu podobným způsobem:
+Příklad generování sitemapy:
 
 ```latte
 {contentType application/xml}
 <?xml version="1.0" encoding="UTF-8"?>
-<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" >
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
 	<url n:foreach="$urls as $url">
 		<loc>{$url->loc}</loc>
 		<lastmod>{$url->lastmod->format('Y-m-d')}</lastmod>
@@ -137,11 +147,10 @@ Poté můžeme například vygenerovat sitemapu podobným způsobem:
 ```
 
 
-Předání dat z includované šablony
-=================================
+Předávání dat z vložené šablony
+===============================
 
-Proměnné, které vytvoříme pomocí `{var}` či `{default}` v inkludované šabloně, existují jen v ní a nejsou v inkludující šabloně k dispozici.
-Pokud bychom si chtěli z inkludované šablony předat zpátky do inkludující nějaká data, jednou z možností je předat do šablony objekt a do něj data vložit.
+Proměnné vytvořené pomocí `{var}` nebo `{default}` ve vložené šabloně jsou lokální a nejsou dostupné v šabloně, která je vkládá. Pokud potřebujete předat data zpět do vkládající šablony, můžete využít objektu jako prostředníka.
 
 Hlavní šablona:
 
@@ -155,9 +164,11 @@ Hlavní šablona:
 {$vars->foo}
 ```
 
-Inkludovaná šablona `included.latte`:
+Vložená šablona `included.latte`:
 
 ```latte
 {* zapíšeme data do property foo *}
 {var $vars->foo = 123}
 ```
+
+Tento přístup umožňuje efektivní sdílení dat mezi šablonami při zachování čistého a přehledného kódu.
diff --git a/latte/cs/safety-first.texy b/latte/cs/safety-first.texy
index 44bd9f4edf..ff82aebe68 100644
--- a/latte/cs/safety-first.texy
+++ b/latte/cs/safety-first.texy
@@ -1,13 +1,13 @@
 Latte je synonymum bezpečnosti
 ******************************
 
-<div class=perex>
+<div class="perex">
 
-Latte je jediný šablonovací systém pro PHP s efektivní ochranou proti kritické zranitelnosti Cross-site Scripting (XSS). A to díky tzv. kontextově sensitivnímu escapování. Povíme si,
+Latte je jediný šablonovací systém pro PHP, který poskytuje účinnou ochranu proti kritické zranitelnosti Cross-site Scripting (XSS). Tuto ochranu zajišťuje pomocí tzv. kontextově sensitivního escapování. V tomto článku se dozvíte:
 
-- jaký je princip zranitelnosti XSS a proč je tak nebezpečná
-- čím to, že je Latte v obraně před XSS tak efektivní
-- jak lze v šablonách Twig, Blade a spol. snadno udělat bezpečnostní díru
+- Princip zranitelnosti XSS a proč je tak nebezpečná
+- Proč je Latte v obraně před XSS tak efektivní
+- Jak lze v šablonách jiných systémů jako Twig či Blade snadno vytvořit bezpečnostní mezeru
 
 </div>
 
@@ -15,90 +15,89 @@ Latte je jediný šablonovací systém pro PHP s efektivní ochranou proti kriti
 Cross-site Scripting (XSS)
 ==========================
 
-Cross-site Scripting (zkráceně XSS) je jednou z nejčastějších zranitelností webových stránek a přitom velmi nebezpečnou. Umožní útočníkovi vložit do cizí stránky škodlivý skript (tzv. malware), který se spustí v prohlížeči nic netušícího uživatele.
+Cross-site Scripting, zkráceně XSS, patří mezi nejčastější a zároveň velmi nebezpečné zranitelnosti webových stránek. Umožňuje útočníkovi vložit do cizí webové stránky škodlivý skript (malware), který se následně spustí v prohlížeči nic netušícího uživatele.
 
-Co všechno může takový skript napáchat? Může například odeslat útočníkovi libovolný obsah z napadené stránky, včetně citlivých údajů zobrazených po přihlášení. Může stránku pozměnit nebo provádět další požadavky jménem uživatele.
-Pokud by se například jednalo o webmail, může si přečíst citlivé zprávy, pozměnit zobrazovaný obsah nebo přenastavit konfiguraci, např. zapnout přeposílání kopií všech zpráv na útočníkovu adresu, aby získal přístup i k budoucím emailům.
+Takový škodlivý skript může napáchat značné škody. Může například:
 
-Proto také XSS figuruje na předních místech žebříčků nejnebezpečnějších zranitelností. Pokud se na webové stránce zranitelnost objeví, je nutné ji co nejdříve odstranit, aby se zabránilo zneužití.
+- Odeslat útočníkovi jakýkoli obsah z napadené stránky, včetně citlivých údajů zobrazených po přihlášení
+- Modifikovat obsah stránky
+- Provádět akce jménem přihlášeného uživatele
+
+Představte si například napadení webmailové služby. Útočník by mohl číst citlivé zprávy, měnit zobrazovaný obsah nebo upravovat nastavení, třeba zapnout přeposílání kopií všech zpráv na svou adresu, čímž by získal přístup i k budoucí komunikaci.
+
+Proto se XSS pravidelně objevuje na předních příčkách žebříčků nejnebezpečnějších zranitelností. Pokud se na webové stránce objeví tato zranitelnost, je klíčové ji co nejrychleji odstranit, aby se zabránilo potenciálnímu zneužití.
 
 
 Jak zranitelnost vzniká?
 ------------------------
 
-Chyba vzniká v místě, kde se webová stránka generuje a vypisují se proměnné. Představte si, že vytváříte stránku s vyhledáváním, a na začátku bude odstavec s hledaným výrazem v podobě:
+XSS zranitelnost vzniká v místě, kde se generuje webová stránka a vypisují se proměnné. Představte si například stránku s vyhledáváním, kde se zobrazuje hledaný výraz:
 
 ```php
 echo '<p>Výsledky vyhledávání pro <em>' . $search . '</em></p>';
 ```
 
-Útočník může do vyhledávacího políčka a potažmo do proměnné `$search` zapsat libovolný řetězec, tedy i HTML kód jako `<script>alert("Hacked!")</script>`. Protože výstup není nijak ošetřen, stane se součástí zobrazené stránky:
+Útočník může do vyhledávacího pole a následně do proměnné `$search` vložit libovolný řetězec, včetně HTML kódu jako `<script>alert("Hacked!")</script>`. Pokud není výstup nijak ošetřen, stane se součástí zobrazené stránky:
 
 ```html
 <p>Výsledky vyhledávání pro <em><script>alert("Hacked!")</script></em></p>
 ```
 
-Prohlížeč místo toho, aby vypsal hledaný řetězec, spustí JavaScript. A tím přebírá vládu nad stránkou útočník.
+Prohlížeč místo zobrazení hledaného výrazu spustí vložený JavaScript, čímž útočník získává kontrolu nad stránkou.
 
-Můžete namítnout, že vložením kódu do proměnné sice dojde ke spuštění JavaScriptu, ale jen v útočníkově prohlížeči. Jak se dostane k oběti? Z tohoto pohledu rozlišujeme několik typů XSS. V našem příkladu s vyhledáváním hovoříme o *reflected XSS*.
-Zde je ještě potřeba navést oběť, aby klikla na odkaz, který bude obsahovat škodlivý kód v parametru:
+Existuje několik typů XSS útoků. V našem příkladu s vyhledáváním jde o tzv. *reflected XSS*. Zde útočník potřebuje přimět oběť kliknout na odkaz obsahující škodlivý kód v parametru:
 
 ```
 https://example.com/?search=<script>alert("Hacked!")</script>
 ```
 
-Navedení uživatele na odkaz sice vyžaduje určité sociální inženýrství, ale není to nic složitého. Uživatelé na odkazy, ať už v emailech nebo na sociálních sítích, klikají bez větších rozmyslů. A že je v adrese něco podezřelého se dá zamaskovat pomocí zkracovače URL, uživatel pak vidí jen `bit.ly/xxx`.
+I když to vyžaduje určité sociální inženýrství, není to nic složitého. Uživatelé často klikají na odkazy v emailech nebo na sociálních sítích bez většího rozmyslu. Podezřelou část adresy lze navíc zamaskovat pomocí zkracovače URL.
 
-Nicméně existuje i druhá a mnohem nebezpečnější forma útoku označovaná jako *stored XSS* nebo *persistent XSS*, kdy se útočníkovi podaří uložit škodlivý kód na server tak, aby byl automaticky vkládán do některých stránek.
+Ještě nebezpečnější formou je *stored XSS* nebo *persistent XSS*, kdy se útočníkovi podaří uložit škodlivý kód přímo na server. Typickým příkladem jsou stránky s uživatelskými komentáři. Útočník odešle příspěvek obsahující škodlivý kód, který se uloží na server. Pokud nejsou stránky dostatečně zabezpečené, bude se tento kód spouštět v prohlížeči každého návštěvníka.
 
-Příkladem jsou stránky, kam uživatelé píší komentáře. Útočník pošle příspěvek obsahující kód a ten se uloží na server. Pokud stránky nejsou dostatečně zabezpečené, bude se pak spouštět v prohlížeči každého návštěvníka.
+Mohlo by se zdát, že jádro útoku spočívá ve vložení řetězce `<script>` do stránky. Ve skutečnosti existuje "mnoho způsobů vložení JavaScriptu":https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html.
 
-Mohlo by se zdát, že jádro útoku spočívá v tom dostat do stránky řetězec `<script>`. Ve skutečnosti "způsobů vložení JavaScriptu je mnoho":https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html.
-Ukážeme si třeba příklad vložení pomocí HTML atributu. Mějme fotogalerii, kde lze vkládat k obrázkům popisek, který se vypíše v atributu `alt`:
+Podívejme se na příklad vložení pomocí HTML atributu. Představte si fotogalerii, kde lze k obrázkům přidávat popisky, které se vypíší v atributu `alt`:
 
 ```php
 echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">';
 ```
 
-Útočníkovi stačí jako popisek vložit šikovně sestavený řetězec `" onload="alert('Hacked!')` a když vypsání nebude ošetřeno, výsledný kód bude vypadat takto:
+Útočníkovi stačí jako popisek vložit chytře sestavený řetězec `" onload="alert('Hacked!')`. Pokud není výstup ošetřen, výsledný kód bude vypadat takto:
 
 ```html
 <img src="photo0145.webp" alt="" onload="alert('Hacked!')">
 ```
 
-Součástí stránky se nyní stává podvržený atribut `onload`. Prohlížeč kód v něm obsažený spustí hned po stažení obrázku. Hacked!
+Do stránky se tak dostává podvržený atribut `onload`. Prohlížeč spustí kód v tomto atributu ihned po načtení obrázku. A útočník opět získává kontrolu.
 
 
 Jak se bránit XSS?
 ------------------
 
-Jakékoliv pokusy útok detekovat pomocí blacklistu, jako například blokovat řetězec `<script>` apod., jsou nedostačující. Základem funkční obrany je **důsledná sanitizace všech dat vypisovaných uvnitř stránky.**
+Pokusy detekovat útok pomocí blacklistu, například blokováním řetězce `<script>`, jsou nedostatečné. Základem účinné obrany je **důsledná sanitizace všech dat vypisovaných na stránce**.
 
-Především jde o nahrazení všech znaků se speciálním významem za jiné odpovídající sekvence, čemuž se slangově říká **escapování** (první znak sekvence se nazývá únikovým, odtud pojmenování).
-Třeba v textu HTML má speciální význam znak `<`, který když nemá být interpretován jako začátek tagu, musíme jej nahradit vizuálně odpovídající sekvencí, tzv. HTML entitou `&lt;`.
-A prohlížeč vypíše menšítko.
+Klíčovým prvkem je nahrazení všech znaků se speciálním významem za odpovídající sekvence. Tento proces se nazývá **escapování**. Například v HTML textu má speciální význam znak `<`, který musí být nahrazen HTML entitou `&lt;`, pokud nemá být interpretován jako začátek tagu.
 
-**Velmi důležité je rozlišovat kontext, ve kterém data vypisujeme**. Protože v různých kontextech se řetězce různě sanitizují. V různých kontextech mají speciální význam různé znaky.
-Například se liší escapování v textu HTML, v atributech HTML, uvnitř některých speciálních elementů, atd. Za chvíli to probereme podrobně.
+**Zásadní je rozlišovat kontext, ve kterém data vypisujeme**. V různých kontextech se totiž řetězce sanitizují odlišně, protože různé znaky mají speciální význam. Liší se například escapování v textu HTML, v atributech HTML, uvnitř některých speciálních elementů atd. Podrobněji se na to podíváme později.
 
-Ošetření je nejlepší provádět přímo při vypsáním řetězce ve stránce, čímž zajistíme, že se opravdu provede a provede se právě jednou. Nejlepší je, pokud ošetření obstará **automaticky** přímo šablonovací systém.
-Protože pokud ošetření neprobíhá automaticky, může na něj programátor zapomenout. A jedno opomenutí znamená, že web je zranitelný.
+Ošetření je nejlepší provádět přímo při vypsání řetězce na stránce. Tím zajistíme, že se skutečně provede, a to právě jednou. Ideální je, když ošetření provádí **automaticky** přímo šablonovací systém. Pokud ošetření není automatické, může na něj programátor snadno zapomenout. A jediné opomenutí stačí k tomu, aby byl web zranitelný.
 
-Nicméně XSS se netýká jen vypisování dat v šablonách, ale i dalších částí aplikace, které musí správně zacházet s nedůvěryhodnými daty. Například je nutné, aby JavaScript ve vaší aplikaci nepoužíval ve spojitosti s nimi `innerHTML`, ale pouze `innerText` nebo `textContent`.
-Speciální pozor je potřeba dávat na funkce, které vyhodnocují řetězce jako JavaScript, což je `eval()`, ale taky `setTimeout()`, případně použití funkce `setAttribute()` s eventovými atributy jako `onload` apod. Tohle už ale jde mimo oblast, kterou pokrývají šablony.
+XSS se netýká jen vypisování dat v šablonách, ale i dalších částí aplikace, které musí správně zacházet s nedůvěryhodnými daty. Například je nutné, aby JavaScript ve vaší aplikaci nepoužíval ve spojení s nimi `innerHTML`, ale pouze `innerText` nebo `textContent`. Zvláštní pozornost je třeba věnovat funkcím, které vyhodnocují řetězce jako JavaScript, což je `eval()`, ale také `setTimeout()`, případně použití funkce `setAttribute()` s eventovými atributy jako `onload`. Toto však již přesahuje oblast, kterou pokrývají šablony.
 
-**Ideální obrana ve 3 bodech:**
+**Ideální obrana ve třech bodech:**
 
-1) rozezná kontext, ve kterém se data vypisují
-2) sanitizuje data podle pravidel daného kontextu (tedy „kontextově sensitivně“)
+1) rozpozná kontext, ve kterém se data vypisují
+2) sanitizuje data podle pravidel daného kontextu (tedy "kontextově sensitivně")
 3) dělá to automaticky
 
 
 Kontextově sensitivní escapování
 ================================
 
-Co se přesně myslí slovem kontext? Jde o místo v dokumentu s vlastními pravidly pro ošetřování vypisovaných dat. Odvíjí se od typu dokumentu (HTML, XML, CSS, JavaScript, plain text, ...) a může se lišit v jeho konkrétních částech.
-Například v HTML dokumentu je takových míst (kontextů), kde platí velmi odlišná pravidla, celá řada. Možná budete překvapeni, kolik jich je. Tady máme první čtveřici:
+Co přesně znamená slovo kontext? Jde o místo v dokumentu s vlastními pravidly pro ošetřování vypisovaných dat. Odvíjí se od typu dokumentu (HTML, XML, CSS, JavaScript, plain text, ...) a může se lišit v jeho konkrétních částech.
+
+V HTML dokumentu existuje celá řada míst (kontextů) s velmi odlišnými pravidly. Možná budete překvapeni, kolik jich je. Zde je první čtveřice:
 
 ```html
 <p>#text</p>
@@ -107,18 +106,18 @@ Například v HTML dokumentu je takových míst (kontextů), kde platí velmi od
 <!-- #komentář -->
 ```
 
-Výchozím a základním kontextem HTML stránky je HTML text. Jaká zde platí pravidla? Speciální význam mají znaky `<` a `&`, které představují začátek značky nebo entity, takže je musíme escapovat, a to nahrazením za HTML entitu (`<` za `&lt;` `&` za `&amp`).
+Výchozím a základním kontextem HTML stránky je HTML text. Jaká zde platí pravidla? Speciální význam mají znaky `<` a `&`, které představují začátek značky nebo entity. Musíme je escapovat nahrazením za HTML entity (`<` za `&lt;`, `&` za `&amp;`).
 
-Druhým nejběžnějším kontextem je hodnota HTML atributu. Od textu se liší v tom, že speciální význam tu má uvozovka `"` nebo `'`, která atribut ohraničuje. Tu je třeba zapsat entitou, aby nebyla chápána jako konec atributu.
-Naopak v atributu lze bezpečně používat znak `<`, protože tady žádný speciální význam nemá, tady nemůže být chápán jako začátek značky či komentáře.
-Ale pozor, v HTML lze psát hodnoty atributů i bez uvozovek, v takovém případě má speciální význam celá řada znaků, jde tedy o další samostatný kontext.
+Druhým nejběžnějším kontextem je hodnota HTML atributu. Od textu se liší tím, že speciální význam zde mají uvozovky `"` nebo `'`, které atribut ohraničují. Ty je třeba zapsat jako entity, aby nebyly chápány jako konec atributu.
+Naopak v atributu lze bezpečně používat znak `<`, protože zde nemá žádný speciální význam.
+Pozor však na to, že v HTML lze psát hodnoty atributů i bez uvozovek. V takovém případě má speciální význam celá řada znaků, jde tedy o další samostatný kontext.
 
-Možná vás překvapí, ale speciální pravidla platí uvnitř elementů `<textarea>` a `<title>`, kde se znak `<` nemusí (ale může) escapovat, pokud za ním nenásleduje `/`. Ale to je spíš perlička.
+Možná vás překvapí, ale speciální pravidla platí i uvnitř elementů `<textarea>` a `<title>`, kde se znak `<` nemusí (ale může) escapovat, pokud za ním nenásleduje `/`. To je však spíše zajímavost.
 
 Zajímavé je to uvnitř HTML komentářů. Tady se totiž k escapování nepoužívají HTML entity. Dokonce žádná specifikace neuvádí, jak by se mělo v komentářích escapovat.
 Jen je nutné dodržet poněkud "kuriozní pravidla":https://html.spec.whatwg.org/multipage/syntax.html#comments a vyhnout se v nich určitým kombinacím znaků.
 
-Kontexty se také mohou vrstvit, k čemuž dochází, když vložíme JavaScript nebo CSS do HTML. To lze udělat dvěma odlišnými způsoby, elementem a atributem:
+Kontexty se mohou také vrstvit, k čemuž dochází, když vložíme JavaScript nebo CSS do HTML. To lze udělat dvěma odlišnými způsoby, elementem a atributem:
 
 ```html
 <script>#js-element</script>
@@ -128,41 +127,41 @@ Kontexty se také mohou vrstvit, k čemuž dochází, když vložíme JavaScript
 <p style="#css-atribut"></p>
 ```
 
-Dvě cesty a dva různé způsoby escapování dat. Uvnitř elementu `<script>` a `<style>` se stejně jako v případě HTML komentářů escapování pomocí HTML entit neprovádí. Při vypisování dat uvnitř těchto elementů je potřeba dodržet jediné pravidlo: text nesmí obsahovat sekvenci `</script` resp. `</style`.
+Dvě cesty a dva různé způsoby escapování dat. Uvnitř elementů `<script>` a `<style>` se stejně jako v případě HTML komentářů escapování pomocí HTML entit neprovádí. Při vypisování dat uvnitř těchto elementů je potřeba dodržet jediné pravidlo: text nesmí obsahovat sekvenci `</script>` resp. `</style>`.
 
 Naopak v atributech `style` a `on***` se pomocí HTML entit escapuje.
 
-A samozřejmě uvnitř vnořeného JavaScriptu nebo CSS platí escapovací pravidla těchto jazyků. Takže řetezec v atributu např. `onload` se nejprve escapuje podle pravidel JS a potom podle pravidel HTML atributu.
+A samozřejmě uvnitř vnořeného JavaScriptu nebo CSS platí escapovací pravidla těchto jazyků. Řetězec v atributu například `onload` se nejprve escapuje podle pravidel JS a potom podle pravidel HTML atributu.
 
-Uff... Jak vidíte, HTML je velmi komplexní dokument, kde se vrství kontexty, a bez uvědomění si, kde přesně data vypisuji (tj. v jakém kontextu), nelze říct, jak to správně udělat.
+Jak vidíte, HTML je velmi komplexní dokument, kde se vrství kontexty. Bez uvědomění si, kde přesně data vypisuji (tj. v jakém kontextu), nelze říct, jak to správně udělat.
 
 
 Chcete příklad?
 ---------------
 
-Mějme řetězec `Rock'n'Roll`.
+Vezměme řetězec `Rock'n'Roll`.
 
-Pokud jej budete vypisovat v HTML textu, zrovna v tomhle případě netřeba dělat žádné záměny, protože řetězec neobsahuje žádný znak se speciálním významem. Jiná situace nastane, pokud jej vypíšete uvnitř HTML atributu uvozeného do jednoduchých uvozovek. V takovém případě je potřeba escapovat uvozovky na HTML entity:
+Pokud jej budete vypisovat v HTML textu, v tomto konkrétním případě není třeba provádět žádné záměny, protože řetězec neobsahuje žádný znak se speciálním významem. Jiná situace nastane, pokud jej vypíšete uvnitř HTML atributu ohraničeného jednoduchými uvozovkami. V takovém případě je potřeba escapovat uvozovky na HTML entity:
 
 ```html
 <div title='Rock&apos;n&apos;Roll'></div>
 ```
 
-Tohle bylo jednoduché. Mnohem zajímavější situace nastane při vrstvení kontextů, například pokud řetězec bude součástí JavaScriptu.
+To bylo jednoduché. Mnohem zajímavější situace nastane při vrstvení kontextů, například pokud řetězec bude součástí JavaScriptu.
 
-Nejprve jej tedy vypíšeme do samotného JavaScriptu. Tj. obalíme jej do uvozovek a zároveň escapujeme pomocí znaku `\` uvozovky v něm obsažené:
+Nejprve jej vypíšeme do samotného JavaScriptu. Obalíme jej do uvozovek a zároveň escapujeme pomocí znaku `\` uvozovky v něm obsažené:
 
 ```js
 'Rock\'n\'Roll'
 ```
 
-Ještě můžeme doplnit volání nějaké funkce, ať kód něco dělá:
+Doplňme volání nějaké funkce, ať kód něco dělá:
 
 ```js
 alert('Rock\'n\'Roll');
 ```
 
-Pokud tento kód vložíme do HTML dokumentu pomocí `<script>`, netřeba nic dalšího upravovat, protože se v něm nevyskytuje zakázaná sekvence `</script`:
+Pokud tento kód vložíme do HTML dokumentu pomocí `<script>`, není třeba nic dalšího upravovat, protože se v něm nevyskytuje zakázaná sekvence `</script>`:
 
 ```html
 <script> alert('Rock\'n\'Roll'); </script>
@@ -174,13 +173,13 @@ Pokud bychom jej však chtěli vložit do HTML atributu, musíme ještě escapov
 <div onclick='alert(&apos;Rock\&apos;n\&apos;Roll&apos;)'></div>
 ```
 
-Vnořeným kontextem ale nemusí být jen JS nebo CSS. Běžně jím je také URL. Parametry v URL se escapují tak, že se znaky se speciálním významen převádějí na sekvence začínající `%`. Příklad:
+Vnořeným kontextem ale nemusí být jen JS nebo CSS. Běžně jím je také URL. Parametry v URL se escapují tak, že se znaky se speciálním významem převádějí na sekvence začínající `%`. Příklad:
 
 ```
 https://example.org/?a=Jazz&b=Rock%27n%27Roll
 ```
 
-A když tento řetězec vypíšeme v atributu, ještě aplikujeme escapování podle tohoto kontextu a nahradíme `&` za `&amp`:
+A když tento řetězec vypíšeme v atributu, ještě aplikujeme escapování podle tohoto kontextu a nahradíme `&` za `&amp;`:
 
 ```html
 <a href="https://example.org/?a=Jazz&amp;b=Rock%27n%27Roll">
@@ -192,13 +191,13 @@ Pokud jste dočetli až sem, gratulujeme, bylo to vyčerpávající. Teď už m
 Latte vs naivní systémy
 =======================
 
-Ukázali jsem si, jak se správně escapuje v HTML dokumentu a jak zásadní je znalost kontextu, tedy místa, kde data vypisujeme. Jinými slovy, jak funguje kontextově sensitvní escapování.
-Ačkoliv jde o nezbytný předpoklad funkční obrany před XSS, **Latte je jediný šablonovací systém pro PHP, který tohle umí.**
+Ukázali jsme si, jak se správně escapuje v HTML dokumentu a jak zásadní je znalost kontextu, tedy místa, kde data vypisujeme. Jinými slovy, jak funguje kontextově sensitivní escapování.
+Ačkoliv jde o nezbytný předpoklad funkční obrany před XSS, **Latte je jediný šablonovací systém pro PHP, který tohle umí**.
 
 Jak je to možné, když všechny systémy dnes tvrdí, že mají automatické escapování?
-Automatické escapování bez znalosti kontextu je trošku bullshit, který **vytváří falešný dojem bezpečí**.
+Automatické escapování bez znalosti kontextu je poněkud zavádějící a **vytváří falešný dojem bezpečí**.
 
-Šablonovací systémy, jako je Twig, Laravel Blade a další, nevidí v šabloně žádnou HTML strukturu. Nevidí tudíž ani kontexty. Oproti Latte jsou slepé a naivní. Zpracovávají jen vlastní značky, vše ostatní je pro ně nepodstatný tok znaků:
+Šablonovací systémy jako Twig, Laravel Blade a další nevidí v šabloně žádnou HTMLstrukturu. Nevidí tudíž ani kontexty. Oproti Latte jsou slepé a naivní. Zpracovávají jen vlastní značky, vše ostatní je pro ně nepodstatný tok znaků:
 
 <div class="juxtapose juxtapose--dark-handle" data-startingposition="80" data-animation="juxtapose-wiper">
 
@@ -230,7 +229,7 @@ Automatické escapování bez znalosti kontextu je trošku bullshit, který **vy
 
 </div>
 
-Naivní systémy jen mechanicky převádějí znaky `< > & ' "` na HTML entity, což je sice ve většině případů užití platný způsob escapování, ale zdaleka ne vždy. Nemohou tak odhalit ani předejít vzniku různých bezpečnostní děr, jak si ukážeme dále.
+Naivní systémy pouze mechanicky převádějí znaky `< > & ' "` na HTML entity, což je sice ve většině případů platný způsob escapování, ale zdaleka ne vždy. Nemohou tak odhalit ani předejít vzniku různých bezpečnostních děr, jak si ukážeme dále.
 
 Latte šablonu vidí stejně jako vy. Chápe HTML, XML, rozeznává značky, atributy atd. A díky tomu rozlišuje jednotlivé kontexty a podle nich ošetřuje data. Nabízí tak opravdu efektivní ochranu proti kritické zranitelnosti Cross-site Scripting.
 
@@ -270,63 +269,60 @@ Vlevo vidíte šablonu v Latte, vpravo je vygenerovaný HTML kód. Několikrát
 </div>
 </div>
 
-Není to skvělé! Latte dělá kontextově sensitivní escapování automaticky, takže programátor:
+Není to skvělé! Latte provádí kontextově sensitivní escapování automaticky, takže programátor:
 
 - nemusí přemýšlet ani vědět, jak se kde escapuje
 - nemůže se splést
 - nemůže na escapování zapomenout
 
-Tohle dokonce nejsou všechny kontexty, které Latte při vypisování rozlišuje a pro které přizpůsobuje ošetření dat. Další zajimavé případy si projdeme nyní.
+Tohle dokonce nejsou všechny kontexty, které Latte při vypisování rozlišuje a pro které přizpůsobuje ošetření dat. Další zajímavé případy si projdeme nyní.
 
 
 Jak hacknout naivní systémy
 ===========================
 
-Na několika praktických příkladech si ukážeme, jak je rozlišování kontextů důležité a proč naivní šablonovací systémy neposkytují dostatečnou ochranu před XSS, na rozdíl od Latte.
-Jako zástupce naivního systému použijeme v ukázkách Twig, ale totéž platí i pro ostatní systémy.
+Nyní si na praktických příkladech ukážeme, proč je rozlišování kontextů tak důležité a proč naivní šablonovací systémy neposkytují dostatečnou ochranu před XSS, na rozdíl od Latte.
+V ukázkách použijeme Twig jako zástupce naivních systémů, ale podobné principy platí i pro ostatní systémy.
 
 
-Zranitelnost atributem
-----------------------
+Zranitelnost pomocí atributu
+----------------------------
 
-Pokusíme se do stránky injektovat škodlivý kód pomocí HTML atributu, jak jsme si [ukazovali výše|#Jak zranitelnost vzniká]. Mějme šablonu v Twigu vykreslující obrázek:
+Pokusme se injektovat škodlivý kód do stránky pomocí HTML atributu. Představme si šablonu v Twigu pro vykreslení obrázku:
 
 ```twig .{file:Twig}
 <img src={{ imageFile }} alt={{ imageAlt }}>
 ```
 
-Všimněte si, že okolo hodnot atributů nejsou uvozovky. Kodér na ně mohl zapomenout, což se prostě stává. Například v Reactu se kód píše takto, bez uvozovek, a kodér, který střídá jazyky, pak na uvozovky může snadno zapomenout.
+Všimněte si chybějících uvozovek kolem hodnot atributů. Takové opomenutí se může snadno stát, zejména když vývojář střídá různé technologie (např. v Reactu se atributy píší bez uvozovek).
 
-Útočník jako popisek obrázku vloží šikovně sestavený řetězec `foo onload=alert('Hacked!')`. Už víme, že Twig nemůže poznat, jestli se proměnná vypisuje v toku HTML textu, uvnitř atributu, HTML komentáře, atd., zkrátka nerozlišuje kontexty. A jen mechanicky převádí znaky `< > & ' "` na HTML entity.
-Takže výsledný kód bude vypadat takto:
+Útočník by mohl jako popisek obrázku vložit řetězec `foo onload=alert('Hacked!')`. Twig nedokáže rozpoznat kontext, ve kterém se proměnná vypisuje, a pouze mechanicky převede znaky `< > & ' "` na HTML entity. Výsledný kód bude vypadat takto:
 
 ```html
 <img src=photo0145.webp alt=foo onload=alert(&#039;Hacked!&#039;)>
 ```
 
-**A vznikla bezpečností díra!**
+**Vznikla bezpečnostní díra!** Do stránky se dostal podvržený atribut `onload`, který prohlížeč spustí ihned po načtení obrázku.
 
-Součástí stránky se stal podvržený atribut `onload` a prohlížeč ihned po stažení obrázku jej spustí.
-
-Nyní se podíváme, jak si se stejnou šablonou poradí Latte:
+Srovnejme to s Latte:
 
 ```latte .{file:Latte}
 <img src={$imageFile} alt={$imageAlt}>
 ```
 
-Latte vidí šablonu stejně jako vy. Na rozdíl od Twigu chápe HTML a ví, že proměnná se vypisuje jako hodnota atributu, který není v uvozovkách. Proto je doplní. Když útočník vloží stejný popisek, výsledný kód bude vypadat takto:
+Latte chápe strukturu HTML a rozpozná, že proměnná se vypisuje jako hodnota atributu bez uvozovek. Proto je automaticky doplní. I když útočník vloží stejný škodlivý řetězec, výsledek bude bezpečný:
 
 ```html
 <img src="photo0145.webp" alt="foo onload=alert(&apos;Hacked!&apos;)">
 ```
 
-**Latte úspěšně zabránilo XSS.**
+**Latte úspěšně odvrátilo XSS útok.**
 
 
-Vypsání proměnné v JavaScript
------------------------------
+Bezpečné použití proměnných v JavaScriptu
+-----------------------------------------
 
-Díky kontextově sensitivnímu escapování je možné zcela nativně používat PHP proměnné uvnitř JavaScriptu.
+Díky kontextově citlivému escapování můžete v Latte bezpečně používat PHP proměnné přímo v JavaScriptu:
 
 ```latte
 <p onclick="alert({$movie})">{$movie}</p>
@@ -334,7 +330,7 @@ Díky kontextově sensitivnímu escapování je možné zcela nativně používa
 <script>var movie = {$movie};</script>
 ```
 
-Pokud bude proměnná `$movie` obsahovat řetězec `'Amarcord & 8 1/2'`, vygeneruje se následující výstup. Všimněte si, že uvnitř HTML se použije jiné escapování, než uvnitř JavaScriptu a ještě jiné v atributu `onclick`:
+Pokud `$movie` obsahuje řetězec `'Amarcord & 8 1/2'`, Latte vygeneruje následující kód:
 
 ```latte
 <p onclick="alert(&quot;Amarcord &amp; 8 1\/2&quot;)">Amarcord &amp; 8 1/2</p>
@@ -342,30 +338,44 @@ Pokud bude proměnná `$movie` obsahovat řetězec `'Amarcord & 8 1/2'`, vygener
 <script>var movie = "Amarcord & 8 1\/2";</script>
 ```
 
+Všimněte si, jak Latte použilo různé metody escapování pro HTML text, JavaScript v atributu `onclick` a JavaScript uvnitř tagu `<script>`.
+
 
 Kontrola odkazů
 ---------------
 
-Latte automaticky kontroluje, zda proměnná použitá v atributech `src` nebo `href` obsahuje webovou URL (tj. protokol HTTP) a předchází vypsání odkazů, které mohou představovat bezpečnostní riziko.
+Latte jde v ochraně ještě dál. Automaticky kontroluje obsah atributů `src` a `href`, aby zabránilo potenciálně nebezpečným odkazům:
 
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">klikni</a>
+<a href={$link}>klikni</a>
 ```
 
-Vypíše:
+Latte rozpozná nebezpečný odkaz a vypíše:
 
 ```latte
 <a href="">klikni</a>
 ```
 
-Kontrola se dá vypnout pomocí filtru [nocheck|filters#nocheck].
+Tuto kontrolu lze v případě potřeby vypnout pomocí filtru [nocheck|filters#nocheck].
 
 
 Limity Latte
 ============
 
-Latte není zcela kompletní ochranou před XSS pro celou aplikaci. Byli bychom neradi, kdybyste při použití Latte přestali nad bezpečností přemýšlet.
-Cílem Latte je zajistit, aby útočník nemohl pozměnit strukturu stránky, podvrhnout HTML elementy nebo atributy. Ale nekontroluje obsahovou správnost vypisovaných dat. Nebo správnost chování JavaScriptu.
-To už jde mimo kompetence šablonovacího systému. Ověřování správnosti dat, zejména těch vložených uživatelem a tedy nedůvěryhodných, je důležitým úkolem programátora.
+I když Latte poskytuje vynikající ochranu proti XSS, není to všelék na všechny bezpečnostní problémy webových aplikací. Bylo by nebezpečné, kdyby vývojáři při použití Latte přestali o bezpečnosti přemýšlet.
+
+Latte se zaměřuje na to, aby útočník nemohl:
+- Změnit strukturu HTML stránky
+- Vložit nežádoucí HTML elementy nebo atributy
+- Spustit JavaScript v kontextu, kde by neměl
+
+Co Latte nekontroluje:
+- Obsahovou správnost vypisovaných dat
+- Logiku a správnost chování JavaScriptu
+- Bezpečnost na úrovni aplikační logiky
+
+Tyto aspekty zůstávají v kompetenci vývojáře. Je crucial věnovat pozornost validaci a sanitizaci vstupních dat, zejména těch pocházejících od uživatelů. Také je důležité pravidelně aktualizovat všechny komponenty aplikace a sledovat nové bezpečnostní hrozby.
+
+Latte poskytuje silný první obranný val proti XSS útokům, ale komplexní bezpečnost vyžaduje holistický přístup zahrnující správné praktiky v celém vývojovém procesu.
diff --git a/latte/cs/sandbox.texy b/latte/cs/sandbox.texy
index 2948cd5d21..9e8f6e5f88 100644
--- a/latte/cs/sandbox.texy
+++ b/latte/cs/sandbox.texy
@@ -2,9 +2,9 @@ Sandbox
 *******
 
 .[perex]
-Sandbox poskytuje bezpečnostní vrstvu, která vám dává kontrolu nad tím, jaké značky, PHP funkce, metody apod. mohou být v šablonách použity. Díky sandbox režimu můžete bezpečně spolupracovat s klientem nebo externím kodérem na tvorbě šablon, aniž byste se museli obávat, že dojde k narušení aplikace nebo nežádoucím operacím.
+Sandbox v Latte poskytuje robustní bezpečnostní vrstvu, která vám umožňuje precizně kontrolovat, jaké značky, PHP funkce, metody apod mohou být v šablonách použity. Díky tomuto mechanismu můžete bezpečně spolupracovat na tvorbě šablon s klienty nebo externími vývojáři, aniž byste riskovali narušení bezpečnosti vaší aplikace nebo nežádoucí operace.
 
-Jak to funguje? Jednoduše nadefinujeme, co všechno šabloně dovolíme. Přičemž v základu je všechno zakázané a my postupně povolujeme. Následujícím kódem umožníme autorovi šablony používat značky `{block}`, `{if}`, `{else}` a `{=}`, což je značka pro [vypsání proměnné nebo výrazu|tags#Vypisování] a všechny filtry:
+Sandbox funguje na principu explicitního povolování. Ve výchozím stavu je vše zakázáno a vy postupně definujete, co šabloně dovolíte. Například takto povolíme používání značek `{block}`, `{if}`, `{else}` a `{=}` (pro [vypisování proměnných nebo výrazů|tags#Vypisování]) spolu se všemi filtry:
 
 ```php
 $policy = new Latte\Sandbox\SecurityPolicy;
@@ -14,7 +14,7 @@ $policy->allowFilters($policy::All);
 $latte->setPolicy($policy);
 ```
 
-Dále můžeme povolit jednotlivé funkce, metody nebo properties objektů:
+Dále můžeme selektivně povolit konkrétní funkce, metody objektů nebo jejich vlastnosti:
 
 ```php
 $policy->allowFunctions(['trim', 'strlen']);
@@ -22,37 +22,76 @@ $policy->allowMethods(Nette\Security\User::class, ['isLoggedIn', 'isAllowed']);
 $policy->allowProperties(Nette\Database\Row::class, $policy::All);
 ```
 
-Není to úžasné? Můžete na velmi nízké úrovni kontrolovat úplně všechno. Pokud se šablona pokusí zavolat nepovolenou funkci nebo přistoupit k nepovolené metodě nebo property, skončí to výjimkou `Latte\SecurityViolationException`.
+Tato úroveň granularity vám dává naprostou kontrolu nad tím, co může být v šablonách použito. Pokud se šablona pokusí o nepovolený úkon, Latte vyhodí výjimku `Latte\SecurityViolationException`.
 
-Tvořit policy od bodu nula, kdy je zakázáno úplně vše, nemusí být pohodlné, proto můžete začít od bezpečného základu:
+
+Předpřipravená bezpečná politika
+--------------------------------
+
+Vytváření politiky od nuly může být časově náročné, proto Latte nabízí předpřipravenou bezpečnou výchozí politiku:
 
 ```php
 $policy = Latte\Sandbox\SecurityPolicy::createSafePolicy();
 ```
 
-Bezpečný základ znamená, že jsou povoleny všechny standardní tagy kromě  `contentType`, `debugbreak`, `dump`, `extends`, `import`, `include`, `layout`, `php`, `sandbox`, `snippet`, `snippetArea`, `templatePrint`, `varPrint`, `widget`.
-Jsou povoleny standardní filtry kromě `datastream`, `noescape` a `nocheck`. A nakonec je povolený přístup k metodám a properites objektu `$iterator`.
+Tato politika povoluje všechny standardní značky kromě potenciálně nebezpečných jako `contentType`, `debugbreak`, `dump`, `extends`, `import`, `include`, `layout`, `php`, `sandbox`, `snippet`, `snippetArea`, `templatePrint`, `varPrint` a `widget`. Jsou povoleny všechny standardní filtry vyjma `datastream`, `noescape` a `nocheck`. Navíc je povolen přístup k metodám a vlastnostem objektu `$iterator`.
+
 
-Pravidla se aplikují pro šablonu, kterou vložíme značkou [`{sandbox}` |tags#Vložení šablon]. Což je jakási obdoba `{include}`, která však zapíná bezpečný režim a také nepředává žádné proměnné:
+Aplikace sandboxu
+-----------------
+
+Pravidla sandboxu se aplikují na šablony vložené pomocí značky [`{sandbox}` |tags#Vložení šablon]. Ta funguje podobně jako `{include}`, ale aktivuje bezpečný režim a nepředává žádné proměnné:
 
 ```latte
 {sandbox 'untrusted.latte'}
 ```
 
-Tedy layout a jednotlivé stránky mohou nerušeně využívat všechny tagy a proměnné, pouze na šablonu `untrusted.latte` budou uplatněny restrikce.
+Díky tomu mohou hlavní šablony (layout a jednotlivé stránky) využívat plnou funkcionalitu, zatímco na `untrusted.latte` se aplikují omezení.
+
+Některá porušení pravidel, jako použití zakázané značky nebo filtru, se odhalí při kompilaci. Jiná, například volání nepovolených metod objektu, se detekují až za běhu.
 
-Některé prohřešky, jako použití zakázaného tagu nebo filtru, se odhalí v době kompilace. Jiné, jako třeba volání nepovolených metod objektu, až za běhu.
-Šablona také může obsahovat jakékoliv jiné chyby. Aby vám ze sandboxované šablony nemohla vyskočit výjimka, která naruší celé vykreslování, lze definovat vlastní [obslužný handler pro výjimky|develop#exception handler], který ji třeba zaloguje.
+Pro zachycení chyb v sandboxovaných šablonách můžete definovat vlastní [obslužný handler pro výjimky|develop#exception handler], který například zaloguje chybu bez narušení vykreslování celé stránky.
 
-Pokud bychom chtěli sandbox režim zapnout přímo pro všechny šablony, jde to snadno:
+
+Globální aktivace sandboxu
+--------------------------
+
+Pokud chcete aplikovat sandbox režim na všechny šablony, stačí použít:
 
 ```php
 $latte->setSandboxMode();
 ```
 
-Abyste měli jistotu, že uživatel do stránky nevloží PHP kód, který je sice syntakticky správný, ale zakázaný a způsobí PHP Compile Error, doporučujeme nechávat [šablony kontrolovat PHP linterem |develop#Kontrola vygenerovaného kódu]. Tuto funkčnost zapnete metodou `Engine::enablePhpLint()`. Jelikož ke kontrole potřebuje volat binárku PHP, cestu k ní předejte jako parametr:
+
+Dodatečná ochrana
+-----------------
+
+Pro ještě vyšší úroveň bezpečnosti doporučujeme zapnout kontrolu vygenerovaného PHP kódu pomocí PHP linteru. Tím se ujistíte, že uživatel nevložil do šablony syntakticky správný, ale zakázaný PHP kód, který by mohl způsobit PHP Compile Error. Aktivujte tuto funkci metodou `Engine::enablePhpLint()`:
 
 ```php
 $latte = new Latte\Engine;
-$latte->enablePhpLinter('/path/to/php');
+$latte->enablePhpLinter('/cesta/k/php');
 ```
+
+
+Vlastní implementace Policy
+---------------------------
+
+Pokud potřebujete více flexibility při definování pravidel pro sandbox, můžete vytvořit vlastní třídu, která implementuje rozhraní `Latte\Policy` nebo rozšiřuje třídu `Latte\Sandbox\SecurityPolicy`. To vám umožní přesně definovat, jak se má kontrolovat povolení pro tagy, filtry, funkce, metody a vlastnosti.
+
+Například, pokud chcete povolit všechny metody a vlastnosti objektů kromě několika specifických, můžete to snadno implementovat přepsáním metod `isMethodAllowed` a `isPropertyAllowed`:
+
+```php
+class MyPolicy extends Latte\Sandbox\SecurityPolicy
+{
+    public function isMethodAllowed(string $class, string $method): bool
+    {
+        // zakážeme pouze specifické metody $method ve třídě $class
+        return ...
+    }
+}
+
+$latte->setPolicy(new MyPolicy);
+```
+
+Tento přístup vám dává plnou kontrolu nad bezpečnostní politikou a umožňuje vám efektivně spravovat povolení pro velké množství objektů bez nutnosti definovat každou metodu a vlastnost jednotlivě.
diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy
index 8ddca234ec..84deaaff0f 100644
--- a/latte/cs/syntax.texy
+++ b/latte/cs/syntax.texy
@@ -2,10 +2,9 @@ Syntaxe
 *******
 
 .[perex]
-Syntax Latte vzešla z praktických požadavků webdesignerů. Hledali jsme tu nejpřívětivější syntax, se kterou elegantně zapíšete i konstrukce, které jinak představují skutečný oříšek.
-Zároveň všechny výrazy se píší úplně stejně jako v PHP, takže se nemusíte učit nový jazyk. Prostě zúročíte co už dávno umíte.
+Syntax Latte byla navržena s ohledem na praktické potřeby webdesignérů. Hledali jsme co nejpřívětivější syntax, která umožní elegantně zapsat i složité konstrukce. Zároveň jsme zachovali kompatibilitu s PHP, takže se nemusíte učit nový jazyk - stačí využít to, co již znáte.
 
-Níže je uvedena minimální šablona, která ilustruje několik základních prvků: tagy, n:atributy, komentáře a filtry.
+Níže uvádíme minimální šablonu, která ilustruje několik základních prvků: tagy, n:atributy, komentáře a filtry.
 
 ```latte
 {* toto je komentář *}
@@ -22,34 +21,34 @@ Podívejme se blíže na tyto důležité prvky a na to, jak vám mohou pomoci v
 Tagy
 ====
 
-Šablona obsahuje tagy (neboli značky či makra), které řídí logiku šablony (například smyčky *foreach*) nebo vypisují výrazy. Pro obojí se používá jediný delimiter `{ ... }`, takže nemusíte přemýšlet, jaký delimiter v jaké situaci použít, jako je tomu u jiných systémů.
-Pokud za znakem `{` následuje uvozovka nebo mezera, Latte jej nepovažuje za začátek značky, díky čemuž můžete v šablonách bez problémů používat i JavaScriptové konstrukce, JSON nebo pravidla v CSS.
+Šablona obsahuje tagy (neboli značky či makra), které řídí logiku šablony (například smyčky *foreach*) nebo vypisují výrazy. Pro obojí se používá jednotný delimiter `{ ... }`, což eliminuje nutnost přemýšlet, jaký delimiter v jaké situaci použít, na rozdíl od některých jiných systémů.
+Pokud bezprostředně za `{` následuje uvozovka nebo mezera, Latte tento znak nepovažuje za začátek tagu. To umožňuje bezproblémové použití JavaScriptových konstrukcí, JSONu nebo pravidel v CSS přímo v šablonách.
 
-Podívejte se na [přehled všech tagů|tags]. Krom toho si můžete vytvářet i [vlastní tagy|extending-latte#tagy].
+Kompletní [přehled všech tagů|tags] najdete v dokumentaci. Navíc máte možnost vytvářet i [vlastní tagy|extending-latte#tagy] pro specifické potřeby vašeho projektu.
 
 
 Latte rozumí PHP
 ================
 
-Uvnitř značek můžete používat PHP výrazy, které dobře znáte:
+Uvnitř tagů můžete používat standardní PHP výrazy:
 
 - proměnné
-- řetězce (včetně HEREDOC a NOWDOC), pole, čísla, apod.
+- řetězce (včetně HEREDOC a NOWDOC), pole, čísla, atd.
 - [operátory |https://www.php.net/manual/en/language.operators.php]
-- volání funkcí a metod (které lze omezit [sandboxem|sandbox])
+- volání funkcí a metod (které lze v případě potřeby omezit [sandboxem|sandbox])
 - [match |https://www.php.net/manual/en/control-structures.match.php]
 - [anonymní funkce |https://www.php.net/manual/en/functions.arrow.php]
 - [callbacky |https://www.php.net/manual/en/functions.first_class_callable_syntax.php]
 - víceřádkové komentáře `/* ... */`
-- atd…
+- a mnoho dalšího...
 
-Latte navíc syntaxi PHP doplňuje o několik [příjemných rozšíření |#Syntaktický cukr].
+Latte navíc rozšiřuje PHP syntax o několik [užitečných vylepšení |#Syntaktický cukr].
 
 
 n:atributy
 ==========
 
-Všechny párové značky, například `{if} … {/if}`, operující nad jedním HTML elementem, se dají přepsat do podoby n:atributů. Takto by bylo možné zapsat například i `{foreach}` v úvodní ukázce:
+Všechny párové tagy, jako například `{if} … {/if}`, které operují nad jedním HTML elementem, lze přepsat do podoby n:atributů. Takto by bylo možné zapsat i `{foreach}` z úvodní ukázky:
 
 ```latte
 <ul n:if="$items">
@@ -57,7 +56,7 @@ Všechny párové značky, například `{if} … {/if}`, operující nad jedním
 </ul>
 ```
 
-Funkcionalita se pak vztahuje na HTML element, do něhož je umístěný:
+Funkcionalita se vztahuje na HTML element, ve kterém je n:atribut umístěn:
 
 ```latte
 {var $items = ['I', '♥', 'Latte']}
@@ -65,7 +64,7 @@ Funkcionalita se pak vztahuje na HTML element, do něhož je umístěný:
 <p n:foreach="$items as $item">{$item}</p>
 ```
 
-vypíše:
+Tento kód vypíše:
 
 ```latte
 <p>I</p>
@@ -73,7 +72,7 @@ vypíše:
 <p>Latte</p>
 ```
 
-Pomocí prefixu `inner-` můžeme chování poupravit tak, aby se vztahovalo jen na vnitřní část elementu:
+Pomocí prefixu `inner-` můžeme upravit chování tak, aby se vztahovalo pouze na vnitřní obsah elementu:
 
 ```latte
 <div n:inner-foreach="$items as $item">
@@ -82,7 +81,7 @@ Pomocí prefixu `inner-` můžeme chování poupravit tak, aby se vztahovalo jen
 </div>
 ```
 
-Vypíše se:
+Výsledek bude:
 
 ```latte
 <div>
@@ -95,13 +94,13 @@ Vypíše se:
 </div>
 ```
 
-Nebo pomocí prefixu `tag-` aplikujeme funkcionalitu jen na samotné HTML značky:
+Prefix `tag-` umožňuje aplikovat funkcionalitu pouze na samotné HTML tagy:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
-Což vypíše v závislosti na proměnné `$url`:
+V závislosti na hodnotě proměnné `$url` se vypíše:
 
 ```latte
 {* když je $url prázdné *}
@@ -111,60 +110,75 @@ Což vypíše v závislosti na proměnné `$url`:
 <p><a href="https://nette.org">Title</a></p>
 ```
 
-Avšak n:atributy nejsou jen zkratkou pro párové značky. Existují i ryzí n:atributy, jako třeba [n:href |application:creating-links#V šabloně presenteru] nebo velešikovný pomocník kodéra [n:class |tags#n:class].
+N:atributy nejsou jen zkratkou pro párové tagy. Existují i specifické n:atributy jako [n:href |application:creating-links#V šabloně presenteru] nebo velmi užitečný [n:class |tags#n:class].
 
 
 Filtry
 ======
 
-Podívejte se na přehled [standardních filtrů |filters].
+Kompletní seznam [standardních filtrů |filters] najdete v dokumentaci.
 
-Filtry se zapisují za svislítko (může být před ním mezera):
+Filtry se zapisují za svislítko (před kterým může být mezera):
 
 ```latte
 <h1>{$heading|upper}</h1>
 ```
 
-Filtry lze zřetězit a poté se aplikují v pořadí od levého k pravému:
+Filtry lze řetězit, přičemž se aplikují zleva doprava:
 
 ```latte
 <h1>{$heading|lower|capitalize}</h1>
 ```
 
-Parametry se zadávají za jménem filtru oddělené dvojtečkami nebo čárkami:
+Parametry filtrů se zadávají za jménem filtru, oddělené dvojtečkami nebo čárkami:
 
 ```latte
-<h1>{$heading|truncate:20,''}</h1>
+<h1>{$heading|truncate:20, ''}</h1>
 ```
 
-Filtry lze aplikovat i na výraz:
+Filtry lze aplikovat i na výrazy:
 
 ```latte
 {var $name = ($title|upper) . ($subtitle|lower)}
 ```
 
-Na blok:
+Na bloky:
 
 ```latte
 <h1>{block |lower}{$heading}{/block}</h1>
 ```
 
-Nebo přímo na hodnotu (v kombinaci s tagem [`{=expr}`| https://latte.nette.org/cs/tags#Vypisování]):
+Nebo přímo na hodnoty (v kombinaci s tagem [`{=expr}`| https://latte.nette.org/cs/tags#Vypisování]):
+
 ```latte
 <h1>{='  Hello world  '|trim}<h1>
 ```
 
 
+Dynamické HTML tagy .{data-version:3.0.9}
+=========================================
+
+Latte podporuje dynamické HTML tagy, což je užitečné, když potřebujete flexibilitu v názvech tagů:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Tento kód může generovat například `<h1>Heading</h1>` nebo `<h2>Heading</h2>` v závislosti na hodnotě proměnné `$level`. Dynamické HTML tagy v Latte musí být vždy párové. Alternativou je použití [n:tag |tags#n:tag].
+
+Latte jako bezpečný šablonovací systém kontroluje, zda je výsledný název tagu validní a neobsahuje nežádoucí nebo potenciálně škodlivé hodnoty. Zároveň zajišťuje, že název koncového tagu bude vždy shodný s názvem otevíracího tagu.
+
+
 Komentáře
 =========
 
-Komentáře se zapisují tímto způsobem a do výstupu se nedostanou:
+Komentáře se zapisují následujícím způsobem a nejsou součástí výstupu:
 
 ```latte
 {* tohle je komentář v Latte *}
 ```
 
-Uvnitř značek fungují PHP komentáře:
+Uvnitř tagů lze použít standardní PHP komentáře:
 
 ```latte
 {include 'file.info', /* value: 123 */}
@@ -181,25 +195,25 @@ Syntaktický cukr
 U jednoduchých řetězců lze vynechat uvozovky:
 
 ```latte
-jako v PHP:  {var $arr = ['hello', 'btn--default', '€']}
+standardní PHP:  {var $arr = ['hello', 'btn--default', '€']}
 
-zkráceně:    {var $arr = [hello, btn--default, €]}
+zkrácená verze:  {var $arr = [hello, btn--default, €]}
 ```
 
-Jednoduché řetězce jsou ty, které jsou tvořeny čistě z písmen, číslic, podtržítek, pomlček a teček. Nesmí začínat číslicí a nesmí začínat nebo končit pomlčkou.
-Nesmí být složený jen z velkých písmen a podtržítek, protože pak se považuje za konstantu (např. `PHP_VERSION`).
-A nesmí kolidovat s klíčovými slovy: `and`, `array`, `clone`, `default`, `false`, `in`, `instanceof`, `new`, `null`, `or`, `return`, `true`, `xor`.
+Jednoduché řetězce se skládají výhradně z písmen, číslic, podtržítek, pomlček a teček. Nesmí začínat číslicí a nesmí začínat nebo končit pomlčkou.
+Nesmí být tvořeny pouze velkými písmeny a podtržítky, protože ty jsou považovány za konstanty (např. `PHP_VERSION`).
+Také nesmí kolidovat s klíčovými slovy: `and`, `array`, `clone`, `default`, `false`, `in`, `instanceof`, `new`, `null`, `or`, `return`, `true`, `xor`.
 
 
 Zkrácený ternární operátor
 --------------------------
 
-Je-li třetí hodnota ternárního operátoru prázdná, lze ji vynechat:
+Pokud je třetí hodnota ternárního operátoru prázdná, lze ji vynechat:
 
 ```latte
-jako v PHP:  {$stock ? 'Skladem' : ''}
+standardní PHP:  {$stock ? 'Skladem' : ''}
 
-zkráceně:    {$stock ? 'Skladem'}
+zkrácená verze:  {$stock ? 'Skladem'}
 ```
 
 
@@ -209,16 +223,16 @@ Moderní zápis klíčů v poli
 Klíče v poli lze zapisovat podobně jako pojmenované parametry při volání funkcí:
 
 ```latte
-jako v PHP:  {var $arr = ['one' => 'item 1', 'two' => 'item 2']}
+standardní PHP:  {var $arr = ['one' => 'item 1', 'two' => 'item 2']}
 
-moderně:     {var $arr = [one: 'item 1', two: 'item 2']}
+moderní zápis:   {var $arr = [one: 'item 1', two: 'item 2']}
 ```
 
 
 Filtry
 ------
 
-Filtry lze použít pro jakékoliv výrazy, stačí celek uzavřít do závorek:
+Filtry lze aplikovat na libovolné výrazy, stačí celý výraz uzavřít do závorek:
 
 ```latte
 {var $content = ($text|truncate: 30|upper)}
@@ -228,10 +242,10 @@ Filtry lze použít pro jakékoliv výrazy, stačí celek uzavřít do závorek:
 Operátor `in`
 -------------
 
-Operátorem `in` lze nahradit funkci `in_array()`. Porovnání je vždy striktní:
+Operátor `in` nahrazuje funkci `in_array()`. Porovnání je vždy striktní:
 
 ```latte
-{* obdoba in_array($item, $items, true) *}
+{* ekvivalent in_array($item, $items, true) *}
 {if $item in $items}
 	...
 {/if}
@@ -241,16 +255,16 @@ Operátorem `in` lze nahradit funkci `in_array()`. Porovnání je vždy striktn
 Historické okénko
 -----------------
 
-Latte přišlo v průběhu své historie s celou řadou syntaktických cukříků, které se po pár letech objevily v samotném PHP. Například v Latte bylo možné psát pole jako `[1, 2, 3]` místo `array(1, 2, 3)` nebo používat nullsafe operátor `$obj?->foo` dávno předtím, než to bylo možné v samotném PHP. Latte také zavedlo operátor pro rozbalení pole `(expand) $arr`, který je ekvivalentem dnešního operátoru `...$arr` z PHP.
+Latte v průběhu své historie zavedlo mnoho syntaktických vylepšení, která se později objevila i v samotném PHP. Například v Latte bylo možné používat zápis pole jako `[1, 2, 3]` místo `array(1, 2, 3)` nebo nullsafe operátor `$obj?->foo` dlouho před tím, než to umožnilo PHP. Latte také představilo operátor pro rozbalení pole `(expand) $arr`, který je ekvivalentem dnešního PHP operátoru `...$arr`.
 
-Undefined-safe operator `??->`, což je obdoba nullsafe operatoru `?->`, který ale nevyvolá chybu pokud proměnná neexistuje, vznikl z historických důvodů a dnes doporučujeme používat standardní PHP operátor `?->`.
+Undefined-safe operátor `??->`, podobný nullsafe operátoru `?->`, ale nezpůsobující chybu při neexistující proměnné, vznikl z historických důvodů. Dnes doporučujeme používat standardní PHP operátor `?->`.
 
 
 Omezení PHP v Latte
 ===================
 
-V Latte lze zapisovat jen PHP výrazy. Tedy nelze používat statementy ukončené středníkem. Nelze deklarovat třídy nebo používat [řídící struktury |https://www.php.net/manual/en/language.control-structures.php], např. `if`, `foreach`, `switch`, `return`, `try`, `throw` a další, místo kterých Latte nabízí své [značky|tags].
-Také nelze používat [atributy |https://www.php.net/manual/en/language.attributes.php], [backticks |https://www.php.net/manual/en/language.operators.execution.php] či některé [magické konstanty |https://www.php.net/manual/en/language.constants.magic.php].
-Nelze používat ani `unset`, `echo`, `include`, `require`, `exit`, `eval`, protože nejde o funkce, ale speciální jazykové konstrukce PHP, a nejsou to tedy výrazy. Komentáře jsou podporované jen víceřádkové `/* ... */`.
+V Latte lze používat pouze PHP výrazy. Nelze používat příkazy ukončené středníkem, deklarovat třídy nebo používat [řídící struktury |https://www.php.net/manual/en/language.control-structures.php] jako `if`, `foreach`, `switch`, `return`, `try`, `throw` atd. Místo nich Latte nabízí své vlastní [tagy|tags].
+Nelze používat ani [atributy |https://www.php.net/manual/en/language.attributes.php], [backticks |https://www.php.net/manual/en/language.operators.execution.php] či některé [magické konstanty |https://www.php.net/manual/en/language.constants.magic.php].
+Také nelze použít `unset`, `echo`, `include`, `require`, `exit`, `eval`, protože nejde o funkce, ale o speciální jazykové konstrukce PHP. Z komentářů jsou podporovány pouze víceřádkové `/* ... */`.
 
-Tyto omezení lze nicméně obejít tím, že si aktivujete rozšíření [RawPhpExtension |develop#RawPhpExtension], díky kterému lze pak používat ve značce `{php ...}` jakýkoliv PHP kód na zodpovědnost autora šablony.
+Tato omezení lze obejít aktivací rozšíření [RawPhpExtension |develop#RawPhpExtension], které umožňuje používat ve značce `{php ...}` jakýkoliv PHP kód na zodpovědnost autora šablony.
diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy
index e0cf7e30b6..c4e6c59bdb 100644
--- a/latte/cs/tags.texy
+++ b/latte/cs/tags.texy
@@ -2,7 +2,7 @@ Latte tagy (makra)
 ******************
 
 .[perex]
-Přehled a popis všech tagů (neboli značek či maker) šablonovacího systému Latte, které jsou vám standardně k dispozici.
+Přehled a popis všech tagů (značek či maker) šablonovacího systému Latte, které máte standardně k dispozici.
 
 .[table-latte-tags language-latte]
 |## Vypisování
@@ -14,8 +14,9 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém
 |## Podmínky
 | `{if}` … `{elseif}` … `{else}` … `{/if}`    | [podmínka if|#if-elseif-else]
 | `{ifset}` … `{elseifset}` … `{/ifset}`      | [podmínka ifset|#ifset-elseifset]
-| `{ifchanged}` … `{/ifchanged}`              | [test jestli došlo ke změně |#ifchanged]
+| `{ifchanged}` … `{/ifchanged}`              | [test, zda došlo ke změně |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [podmínka switch|#switch-case-default]
+| `n:else`                                    | [alternativní obsah pro podmínky |#n:else]
 
 .[table-latte-tags language-latte]
 |## Cykly
@@ -26,9 +27,9 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém
 | `{skipIf $cond}`               | [přeskočit iteraci |#continueif-skipif-breakif]
 | `{breakIf $cond}`              | [přerušení cyklu |#continueif-skipif-breakif]
 | `{exitIf $cond}`               | [včasné ukončení |#exitif]
-| `{first}` … `{/first}`         | [jde o první průchod? |#first-last-sep]
-| `{last}` … `{/last}`           | [jde o poslední průchod? |#first-last-sep]
-| `{sep}` … `{/sep}`             | [bude ještě následovat průchod? |#first-last-sep]
+| `{first}` … `{/first}`         | [první průchod? |#first-last-sep]
+| `{last}` … `{/last}`           | [poslední průchod? |#first-last-sep]
+| `{sep}` … `{/sep}`             | [bude následovat další průchod? |#first-last-sep]
 | `{iterateWhile}` … `{/iterateWhile}` | [strukturovaný foreach|#iterateWhile]
 | `$iterator`                    | [speciální proměnná uvnitř foreach |#$iterator]
 
@@ -40,8 +41,8 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém
 .[table-latte-tags language-latte]
 |## Bloky, layouty, dědičnost šablon
 | `{block}`                      | [anonymní blok|#block]
-| `{block blockname}`            | [definuje blok |template-inheritance#bloky]
-| `{define blockname}`           | [definuje blok pro pozdější použití |template-inheritance#definice]
+| `{block blockname}`            | [definice bloku |template-inheritance#bloky]
+| `{define blockname}`           | [definice bloku pro pozdější použití |template-inheritance#definice]
 | `{include blockname}`          | [vykreslení bloku|template-inheritance#Vykreslení bloků]
 | `{include blockname from 'file.latte'}` | [vykreslí blok ze souboru |template-inheritance#Vykreslení bloků]
 | `{import 'file.latte'}`        | [načte bloky ze šablony |template-inheritance#horizontální znovupoužití]
@@ -89,7 +90,7 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém
 | `n:class`                      | [dynamický zápis HTML atributu class |#n:class]
 | `n:attr`                       | [dynamický zápis jakýchkoliv HTML atributů |#n:attr]
 | `n:tag`                        | [dynamický zápis jména HTML elementu |#n:tag]
-| `n:ifcontent`                  | [Vynechá prázdný HTML tag |#n:ifcontent]
+| `n:ifcontent`                  | [vynechá prázdný HTML tag |#n:ifcontent]
 
 .[table-latte-tags language-latte]
 |## Dostupné pouze v Nette Frameworku
@@ -97,8 +98,8 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém
 | `{link}`                       | [vypíše odkaz |application:creating-links#V šabloně presenteru]
 | `{plink}`                      | [vypíše odkaz na presenter |application:creating-links#V šabloně presenteru]
 | `{control}`                    | [vykreslí komponentu |application:components#Vykreslení]
-| `{snippet}` … `{/snippet}`     | [výstřižek, který lze odeslat AJAXem |application:ajax#tag-snippet]
-| `{snippetArea}`                | obálka pro výstřižky
+| `{snippet}` … `{/snippet}`     | [výstřižek, který lze odeslat AJAXem |application:ajax#snippety-v-latte]
+| `{snippetArea}`                | [obálka pro výstřižky |application:ajax#oblasti-snippetu]
 | `{cache}` … `{/cache}`         | [cachuje část šablony |caching:#cachovani-v-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém
 | `{input}`                      | [vykreslí formulářový prvek |forms:rendering#label-input]
 | `{inputError}`                 | [vypíše chybovou hlášku formulářového prvku |forms:rendering#inputError]
 | `n:name`                       | [oživí formulářový prvek |forms:rendering#n:name]
-| `{formPrint}`                  | [navrhne Latte kód pro formulář |forms:rendering#formPrint]
-| `{formPrintClass}`             | [navrhne PHP kód třídy s daty formuláře |forms:in-presenter#mapovani-na-tridy]
-| `{formContext}` … `{/formContext}` | [částečné kreslení formuláře |forms:rendering#specialni-pripady]
 | `{formContainer}` … `{/formContainer}` | [kreslení formulářového kontejneru |forms:rendering#specialni-pripady]
 
 
@@ -121,15 +119,14 @@ Vypisování
 `{$var}` `{...}` `{=...}`
 -------------------------
 
-V Latte se používá značka `{=...}` pro výpis jakéhokoliv výrazu na výstup. Latte záleží na vašem pohodlí, takže pokud výraz začíná proměnnou nebo voláním funkce, není potřeba rovnítko psát. Což v praxi znamená, že ho není potřeba psát téměř nikdy:
+Latte používá značku `{=...}` pro výpis jakéhokoliv výrazu. Pro vaše pohodlí Latte nevyžaduje rovnítko, pokud výraz začíná proměnnou nebo voláním funkce. To v praxi znamená, že ho téměř nikdy nemusíte psát:
 
 ```latte
 Jméno: {$name} {$surname}<br>
 Věk: {date('Y') - $birth}<br>
 ```
 
-Jako výraz můžete zapsat cokoliv, co znáte z PHP. Nemusíte se zkrátka učit nový jazyk. Tak třeba:
-
+Můžete zapsat libovolný výraz, který znáte z PHP. Není třeba se učit nový jazyk. Například:
 
 ```latte
 {='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}
@@ -141,30 +138,30 @@ Prosím, nehledejte v předchozím příkladu žádný smysl, ale kdybyste tam n
 Escapování výstupu
 ------------------
 
-Jaký je nejdůležitější úkol šablonovacího systému? Zamezit bezpečnostním dírám. A přesně tohle dělá Latte vždy, když něco vypisujete. Automaticky to escapuje:
+Nejdůležitějším úkolem šablonovacího systému je zabránit bezpečnostním dírám. A přesně to Latte dělá vždy, když něco vypisujete. Automaticky to escapuje:
 
 ```latte
 <p>{='one < two'}</p>   {* vypíše: '<p>one &lt; two</p>' *}
 ```
 
-Abychom byli přesní, Latte používá kontextově sensitivně escapování, což je tak důležitá a unikátní věc, že jsme tomu věnovali [samostatnou kapitolu|safety-first#Kontextově sensitivní escapování].
+Přesněji řečeno, Latte používá kontextově sensitivní escapování, což je tak důležitá a unikátní vlastnost, že jsme jí věnovali [samostatnou kapitolu|safety-first#Kontextově sensitivní escapování].
 
-A co když vypisujte obsah kódovaný v HTML z důvěryhodného zdroje? Pak lze snadno escapování vypnout:
+Co když potřebujete vypsat obsah kódovaný v HTML z důvěryhodného zdroje? Jednoduše můžete escapování vypnout:
 
 ```latte
 {$trustedHtmlString|noescape}
 ```
 
 .[warning]
-Špatné použití filtru `noescape` může vést ke vzniku zranitelnosti XSS! Nikdy jej nepoužívejte, pokud si nejste **zcela jisti** co děláte, a že vypisovaný řetězec pochází z důvěryhodného zdroje.
+Nesprávné použití filtru `noescape` může vést ke vzniku zranitelnosti XSS! Nikdy jej nepoužívejte, pokud si nejste **naprosto jisti**, co děláte a že vypisovaný řetězec pochází z důvěryhodného zdroje.
 
 
 Vypsání v JavaScriptu
 ---------------------
 
-Díky kontextově sensitivnímu escapování je nádherně snadné vypisovat proměnné uvnitř JavaScriptu a správné escapování zařídí Latte.
+Díky kontextově sensitivnímu escapování je neobyčejně snadné vypisovat proměnné uvnitř JavaScriptu a Latte se postará o správné escapování.
 
-Proměnná nemusí být jen řetězec, podporován je kterýkoliv datový typ, který se pak zakóduje jako JSON:
+Proměnná nemusí být jen řetězec, podporován je kterýkoliv datový typ, který se zakóduje jako JSON:
 
 ```latte
 {var $foo = ['hello', true, 1]}
@@ -181,7 +178,7 @@ Vygeneruje:
 </script>
 ```
 
-To je také důvod, proč se kolem proměnné **nepíší uvozovky**: Latte je u řetězců doplní samo. A pokud byste chtěli řetězcovou proměnnou vložit do jiného řetězce, jednoduše je spojte:
+To je také důvod, proč se kolem proměnné **nepíší uvozovky**: Latte je u řetězců doplní samo. Pokud chcete řetězcovou proměnnou vložit do jiného řetězce, jednoduše je spojte:
 
 ```latte
 <script>
@@ -197,13 +194,13 @@ To je také důvod, proč se kolem proměnné **nepíší uvozovky**: Latte je u
 Filtry
 ------
 
-Vypsaný výraz může být upraven [filtrem|syntax#filtry]. Takto třeba řetězec převedeme na velká písmena a zkrátíme na maximálně 30 znaků:
+Vypsaný výraz může být upraven [filtrem|syntax#filtry]. Například takto řetězec převedeme na velká písmena a zkrátíme na maximálně 30 znaků:
 
 ```latte
 {$string|upper|truncate:30}
 ```
 
-Filtry můžete používat i na dílčí části výrazu tímto způsobem:
+Filtry můžete používat i na dílčí části výrazu:
 
 ```latte
 {$left . ($middle|upper) . $right}
@@ -217,7 +214,7 @@ Podmínky
 `{if}` `{elseif}` `{else}`
 --------------------------
 
-Podmínky se chovají stejně, jako jejich protějšky v PHP. Můžete v nich používat i stejné výrazy, jaké znáte z PHP, nemusíte se učit nový jazyk.
+Podmínky v Latte se chovají stejně jako jejich protějšky v PHP. Můžete v nich používat stejné výrazy, jaké znáte z PHP, takže se nemusíte učit nový jazyk.
 
 ```latte
 {if $product->inStock > Stock::Minimum}
@@ -229,13 +226,13 @@ Podmínky se chovají stejně, jako jejich protějšky v PHP. Můžete v nich po
 {/if}
 ```
 
-Jako každou párovou značku, tak i dvojici `{if} ... {/if}` lze zapisovat i v podobě [n:attributu|syntax#n:atributy], například:
+Jako každou párovou značku lze i `{if} ... {/if}` zapsat v podobě [n:attributu|syntax#n:atributy]:
 
 ```latte
 <p n:if="$count > 0">Skladem {$count} kusů</p>
 ```
 
-Víte, že k n:atributům můžete připojit prefix `tag-`? Pak se bude podmínka vztahovat jen na vypsání HTML značek a obsah mezi nimi se vypíše vždycky:
+Můžete k n:atributům připojit prefix `tag-`. Pak se podmínka bude vztahovat jen na vypsání HTML značek a obsah mezi nimi se vypíše vždy:
 
 ```latte
 <a href="..." n:tag-if="$clickable">Hello</a>
@@ -244,15 +241,29 @@ Víte, že k n:atributům můžete připojit prefix `tag-`? Pak se bude podmínk
 {* vypíše '<a href="...">Hello</a>' když $clickable je pravdivá *}
 ```
 
-Boží.
+Praktické, že?
+
+
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Pokud podmínku `{if} ... {/if}` zapíšete v podobě [n:attributu|syntax#n:atributy], můžete uvést i alternativní větev pomocí `n:else`:
+
+```latte
+<strong n:if="$count > 0">Skladem {$count} kusů</strong>
+
+<em n:else>není dostupné</em>
+```
+
+Atribut `n:else` můžete použít také ve dvojici s [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent] a [`n:ifchanged` |#ifchanged].
 
 
 `{/if $cond}`
 -------------
 
-Možná vás překvapí, že výraz v podmínce `{if}` lze uvést také v ukončovací značce. To se hodí v situacích, kdy při otevírání podmínky ještě jeho hodnotu neznáme. Říkejme tomu odložené rozhodnutí.
+Výraz v podmínce `{if}` lze uvést také v ukončovací značce. To se hodí v situacích, kdy při otevírání podmínky ještě jeho hodnotu neznáme. Říkáme tomu odložené rozhodnutí.
 
-Například začneme vypisovat tabulku se záznamy z databáze a teprve po dokončení výpisu si uvědomíme, že v databázi žádný záznam nebyl. Tak dáme na to podmínku do koncové značky `{/if}` a pokud žádný záznam nebude, nic z toho se nevypíše:
+Například začneme vypisovat tabulku se záznamy z databáze a teprve po dokončení výpisu si uvědomíme, že v databázi žádný záznam nebyl. Tak dáme podmínku do koncové značky `{/if}` a pokud žádný záznam nebude, nic se nevypíše:
 
 ```latte
 {if}
@@ -277,19 +288,19 @@ V odložené podmínce lze použít i `{else}`, ale nikoliv `{elseif}`.
 .[note]
 Viz také [`{ifset block}` |template-inheritance#Kontrola existence bloků]
 
-Pomocí podmínky `{ifset $var}` zjistíme, zda proměnná (nebo více proměnných) existuje a má ne*null*ovou hodnotu. Vlastně jde o totéž, jako `if (isset($var))` v PHP. Jako každou párovou značku ji lze zapisovat i v podobě [n:attributu|syntax#n:atributy], tak si to ukažme jako příklad:
+Pomocí podmínky `{ifset $var}` zjistíme, zda proměnná (nebo více proměnných) existuje a má ne*null*ovou hodnotu. Je to ekvivalent `if (isset($var))` v PHP. Jako každou párovou značku ji lze zapsat i v podobě [n:attributu|syntax#n:atributy]:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
 `{ifchanged}`
 -------------
 
-`{ifchanged}` zkontroluje, zda se hodnota proměnné změnila od poslední iterace ve smyčce (foreach, for nebo while).
+`{ifchanged}` kontroluje, zda se hodnota proměnné změnila od poslední iterace ve smyčce (foreach, for nebo while).
 
-Pokud ve značce uvedeme jednu či více proměnných, bude kontrolovat, zda se nějaká z nich změnila, a podle toho vypíše obsah. Například následující příklad vypíše první písmenko jména jako nadpis pokaždé, když se při výpisu jmen změní:
+Pokud ve značce uvedeme jednu či více proměnných, bude kontrolovat, zda se nějaká z nich změnila, a podle toho vypíše obsah. Například tento kód vypíše první písmenko jména jako nadpis pokaždé, když se při výpisu jmen změní:
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -299,7 +310,7 @@ Pokud ve značce uvedeme jednu či více proměnných, bude kontrolovat, zda se
 {/foreach}
 ```
 
-Pokud však neuvedeme žádný argument, bude se kontrolovat vykreslený obsah oproti jeho předchozímu stavu. To znamená, že v předchozím příkladě můžeme klidně argument ve značce vynechat. A samozřejmě také můžeme použít [n:attribut|syntax#n:atributy]:
+Pokud neuvedeme žádný argument, bude se kontrolovat vykreslený obsah oproti jeho předchozímu stavu. V předchozím příkladu tedy můžeme argument ve značce vynechat. Samozřejmě také můžeme použít [n:attribut|syntax#n:atributy]:
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -309,17 +320,17 @@ Pokud však neuvedeme žádný argument, bude se kontrolovat vykreslený obsah o
 {/foreach}
 ```
 
-Uvnitř `{ifchanged}` lze také uvést klauzuli `{else}`.
+Uvnitř `{ifchanged}` lze také použít klauzuli `{else}`.
 
 
 `{switch}` `{case}` `{default}`
 -------------------------------
-Porovnává hodnotu s více možnostmi. Jde o obdobu podmíněnému příklazu `switch`, který znáte z PHP. Nicméně Latte jej vylepšuje:
+Porovnává hodnotu s více možnostmi. Je to obdoba podmíněného příkazu `switch` z PHP, ale Latte ho vylepšuje:
 
 - používá striktní porovnání (`===`)
 - nepotřebuje `break`
 
-Je to tedy přesný ekvivalent struktury `match` se kterou přichází PHP 8.0.
+Je to tedy přesný ekvivalent struktury `match`, kterou přináší PHP 8.0.
 
 ```latte
 {switch $transport}
@@ -351,7 +362,7 @@ V Latte najdete všechny cykly, které znáte z PHP: foreach, for a while.
 `{foreach}`
 -----------
 
-Cyklus zapíšeme úplně stejně jako v PHP:
+Cyklus zapíšeme stejně jako v PHP:
 
 ```latte
 {foreach $langs as $code => $lang}
@@ -359,11 +370,11 @@ Cyklus zapíšeme úplně stejně jako v PHP:
 {/foreach}
 ```
 
-Navíc má několik šikovných vychytávek, o kterých si nyní povíme.
+Navíc má několik šikovných vylepšení, o kterých si nyní povíme.
 
-Latte třeba kontroluje, zda vytvořené proměnné omylem nepřepisují globální proměnné téhož jména. Zachrání to situace, kdy počítáte s tím, že v `$lang` je aktuální jazyk stránky, a neuvědomíte si, že `foreach $langs as $lang` vám tu proměnnou přepsalo.
+Latte kontroluje, zda vytvořené proměnné nechtěně nepřepisují globální proměnné téhož jména. To vás ochrání před situací, kdy počítáte s tím, že v `$lang` je aktuální jazyk stránky, ale `foreach $langs as $lang` vám tu proměnnou přepíše.
 
-Cyklus foreach lze také velmi elegantně a úsporně zapsat pomocí [n:attributu|syntax#n:atributy]:
+Cyklus foreach lze také elegantně a úsporně zapsat pomocí [n:attributu|syntax#n:atributy]:
 
 ```latte
 <ul>
@@ -395,7 +406,7 @@ Takže se vypíše něco jako:
 `{else}` .{toc: foreach-else}
 -----------------------------
 
-Uvnitř cyklu `foreach` může uvést klauzuli `{else}`, jejíž obsah se zobrazí, pokud je cyklus prázdný:
+Uvnitř cyklu `foreach` můžete použít klauzuli `{else}`, jejíž obsah se zobrazí, pokud je cyklus prázdný:
 
 ```latte
 <ul>
@@ -411,18 +422,17 @@ Uvnitř cyklu `foreach` může uvést klauzuli `{else}`, jejíž obsah se zobraz
 `$iterator`
 -----------
 
-Uvnitř cyklu `foreach` vytvoří Latte proměnnou `$iterator`, pomocí které můžeme zjišťovat užitečné informace o probíhajícím cyklu:
-
-- `$iterator->first` - prochází se cyklem poprvé?
-- `$iterator->last` - jde o poslední průchod?
-- `$iterator->counter` - kolikátý je to průchod počítáno od jedné?
-- `$iterator->counter0` - kolikátý je to průchod počítáno od nuly?
-- `$iterator->odd` - jde o lichý průchod?
-- `$iterator->even` - jde o sudý průchod?
-- `$iterator->parent` - iterátor obklopující ten aktuální
-- `$iterator->nextValue` - následující položka v cyklu
-- `$iterator->nextKey` - klíč následující položky v cyklu
+Uvnitř cyklu `foreach` vytvoří Latte proměnnou `$iterator`, která poskytuje užitečné informace o probíhajícím cyklu:
 
+- `$iterator->first` - je to první průchod?
+- `$iterator->last` - je to poslední průchod?
+- `$iterator->counter` - počítadlo, začíná od 1
+- `$iterator->counter0` - počítadlo, začíná od 0
+- `$iterator->odd` - je to lichý průchod?
+- `$iterator->even` - je to sudý průchod?
+- `$iterator->parent` - iterator obklopující ten aktuální
+- `$iterator->nextValue` - následující položka
+- `$iterator->nextKey` - klíč následující položky
 
 ```latte
 {foreach $rows as $row}
@@ -437,20 +447,20 @@ Uvnitř cyklu `foreach` vytvoří Latte proměnnou `$iterator`, pomocí které m
 {/foreach}
 ```
 
-Latte je mazané a `$iterator->last` funguje nejen u polí, ale i když cyklus probíhá nad obecným iterátorem, kde není dopředu znám počet položek.
+Latte je chytré a `$iterator->last` funguje nejen u polí, ale i když cyklus probíhá nad obecným iterátorem, kde není dopředu znám počet položek.
 
 
 `{first}` `{last}` `{sep}`
 --------------------------
 
-Tyto značky lze používat uvnitř cyklu `{foreach}`. Obsah `{first}` se vykreslí, pokud jde o první průchod.
-Obsah `{last}` se vykreslí … jestlipak to uhádnete? Ano, pokud jde o poslední průchod. Jde vlastně o zkratky pro `{if $iterator->first}` a `{if $iterator->last}`.
+Tyto značky lze používat uvnitř cyklu `{foreach}`. Obsah `{first}` se vykreslí při prvním průchodu.
+Obsah `{last}` se vykreslí při posledním průchodu. Jde vlastně o zkratky pro `{if $iterator->first}` a `{if $iterator->last}`.
 
-Značky lze také elegantně použít jako [n:attribut|syntax#n:atributy]:
+Značky lze také elegantně použít jako [n:attributy|syntax#n:atributy]:
 
 ```latte
 {foreach $rows as $row}
-	{first}<h1>List of names</h1>{/first}
+	{first}<h1>Seznam jmen</h1>{/first}
 
 	<p>{$row->name}</p>
 
@@ -458,7 +468,7 @@ Značky lze také elegantně použít jako [n:attribut|syntax#n:atributy]:
 {/foreach}
 ```
 
-Obsah značky `{sep}` se vykreslí, pokud průchod není poslední, hodí se tedy pro vykreslování oddělovačů, například čárek mezi vypisovanými položkami:
+Obsah značky `{sep}` se vykreslí, pokud průchod není poslední. Hodí se pro vykreslování oddělovačů, například čárek mezi vypisovanými položkami:
 
 ```latte
 {foreach $items as $item} {$item} {sep}, {/sep} {/foreach}
@@ -470,7 +480,7 @@ To je docela praktické, že?
 `{iterateWhile}`
 ----------------
 
-Zjednodušuje seskupování lineárních dat během iterování v cyklu foreach tím, že iteraci provádí ve vnořené smyčce, dokud je splněná podmínka. [Přečtěte si návod|cookbook/iteratewhile].
+Zjednodušuje seskupování lineárních dat během iterování v cyklu foreach tím, že iteraci provádí ve vnořené smyčce, dokud je splněná podmínka. [Přečtěte si podrobný návod|cookbook/grouping].
 
 Může také elegantně nahradit `{first}` a `{last}` v příkladu výše:
 
@@ -489,11 +499,13 @@ Může také elegantně nahradit `{first}` a `{last}` v příkladu výše:
 {/foreach}
 ```
 
+Viz také filtry [batch|filters#batch] a [group|filters#group].
+
 
 `{for}`
 -------
 
-Cyklus zapisujeme úplně stejně jako v PHP:
+Cyklus zapisujeme stejně jako v PHP:
 
 ```latte
 {for $i = 0; $i < 10; $i++}
@@ -511,7 +523,7 @@ Značku lze také použít jako [n:attribut|syntax#n:atributy]:
 `{while}`
 ---------
 
-Cyklus opět zapisujeme úplně stejně jako v PHP:
+Opět zapisujeme cyklus stejně jako v PHP:
 
 ```latte
 {while $row = $result->fetch()}
@@ -539,7 +551,7 @@ Je možná i varianta s podmínkou v koncové značce, která odpovídá v PHP c
 `{continueIf}` `{skipIf}` `{breakIf}`
 -------------------------------------
 
-Pro řízení jakéhokoliv cyklu lze používat značky `{continueIf ?}` a `{breakIf ?}`, které přejdou na další prvek resp. ukončí cyklus při splnění podmínky:
+Pro řízení jakéhokoliv cyklu můžete použít značky `{continueIf ?}` a `{breakIf ?}`, které přejdou na další prvek resp. ukončí cyklus při splnění podmínky:
 
 ```latte
 {foreach $rows as $row}
@@ -549,8 +561,7 @@ Pro řízení jakéhokoliv cyklu lze používat značky `{continueIf ?}` a `{bre
 {/foreach}
 ```
 
-
-Značka `{skipIf}` je velmi podobná jako `{continueIf}`, ale nezvyšuje počítadlo `$iterator->counter`, takže pokud jej vypisujeme a zároveň přeskočíme některé položky, nebudou v číslování díry. A také klauzule `{else}` se vykreslí, když přeskočíme všechny položky.
+Značka `{skipIf}` je velmi podobná `{continueIf}`, ale nezvyšuje počítadlo `$iterator->counter`. Takže pokud vypisujete počítadlo a zároveň přeskočíte některé položky, nebudou v číslování mezery. A také klauzule `{else}` se vykreslí, když přeskočíte všechny položky.
 
 ```latte
 <ul>
@@ -572,7 +583,7 @@ Ukončí vykreslování šablony nebo bloku při splnění podmínky (tzv. "earl
 ```latte
 {exitIf !$messages}
 
-<h1>Messages</h1>
+<h1>Zprávy</h1>
 <div n:foreach="$messages as $message">
    {$message}
 </div>
@@ -589,7 +600,7 @@ Vložení šablony
 .[note]
 Viz také [`{include block}` |template-inheritance#Vykreslení bloků]
 
-Značka `{include}` načte a vykreslí uvedenou šablonu. Pokud bychom se bavili v řeči našeho oblíbeného jazyka PHP, je to něco jako:
+Značka `{include}` načte a vykreslí uvedenou šablonu. V PHP bychom to přirovnali k:
 
 ```php
 <?php include 'header.phtml'; ?>
@@ -597,32 +608,32 @@ Značka `{include}` načte a vykreslí uvedenou šablonu. Pokud bychom se bavili
 
 Vložené šablony nemají přístup k proměnným aktivního kontextu, mají přístup jen ke globálním proměnným.
 
-Proměnné do vložené šablony můžete předávat tímto způsobem:
+Proměnné do vložené šablony můžete předávat takto:
 
 ```latte
 {include 'template.latte', foo: 'bar', id: 123}
 ```
 
-Název šablony může být jakákoliv výraz v PHP:
+Název šablony může být jakýkoliv výraz v PHP:
 
 ```latte
 {include $someVar}
 {include $ajax ? 'ajax.latte' : 'not-ajax.latte'}
 ```
 
-Vložený obsah lze upravit pomocí [filtrů|syntax#filtry]. Následující příklad odebere všechno HTML a upraví velikost písmen:
+Vložený obsah lze upravit pomocí [filtrů|syntax#filtry]. Následující příklad odstraní veškeré HTML a upraví velikost písmen:
 
 ```latte
 <title>{include 'heading.latte' |stripHtml|capitalize}</title>
 ```
 
-Defaultně [dědičnost šablon|template-inheritance] v tomto případě nijak nefiguruje. I když v inkludované šabloně můžeme používat bloky, nedojde k nahrazení odpovídajících bloků v šabloně, do které se inkluduje. Přemýšlejte o inkludovaných šabloných jako samostatných odstíněných částech stránek nebo modulů. Toto chování se dá změnit pomocí modifikátoru `with blocks`:
+Ve výchozím nastavení [dědičnost šablon|template-inheritance] v tomto případě nehraje roli. I když v inkludované šabloně můžeme používat bloky, nedojde k nahrazení odpovídajících bloků v šabloně, do které se inkluduje. Inkludované šablony považujte za samostatné odstíněné části stránek nebo modulů. Toto chování můžete změnit pomocí modifikátoru `with blocks`:
 
 ```latte
 {include 'template.latte' with blocks}
 ```
 
-Vztah mezi názvem souboru uvedeným ve značce a souborem na disku je věcí [loaderu|extending-latte#Loadery].
+Vztah mezi názvem souboru uvedeným ve značce a souborem na disku je záležitostí [loaderu|extending-latte#Loadery].
 
 
 `{sandbox}`
@@ -641,7 +652,7 @@ Při vkládání šablony vytvořené koncovým uživatelem byste měli zvážit
 .[note]
 Viz také [`{block name}` |template-inheritance#bloky]
 
-Bloky bez jména slouží jako způsob jak aplikovat [filtry|syntax#filtry] na část šablony. Například takto lze aplikovat filtr [strip|filters#strip], který odstraní zbytečné mezery:
+Anonymní bloky slouží jako způsob, jak aplikovat [filtry|syntax#filtry] na část šablony. Například takto můžete použít filtr [strip|filters#strip], který odstraní zbytečné mezery:
 
 ```latte
 {block|strip}
@@ -661,7 +672,7 @@ Bloky bez jména slouží jako způsob jak aplikovat [filtry|syntax#filtry] na 
 
 Díky této značce je extrémně snadné vytvářet robustní šablony.
 
-Pokud při vykreslování bloku `{try}` dojde k výjimce, celý blok se zahodí a vykreslování bude pokračovat až po něm:
+Pokud při vykreslování bloku `{try}` dojde k výjimce, celý blok se zahodí a vykreslování bude pokračovat za ním:
 
 ```latte
 {try}
@@ -673,7 +684,7 @@ Pokud při vykreslování bloku `{try}` dojde k výjimce, celý blok se zahodí
 {/try}
 ```
 
-Obsah ve volitelné klauzuli `{else}` se vykreslí jen když nastane výjimka:
+Volitelná klauzule `{else}` se vykreslí jen když nastane výjimka:
 
 ```latte
 {try}
@@ -734,7 +745,7 @@ Nové proměnné vytvoříme v šabloně značkou `{var}`:
 {var $name = 'John Smith', $age = 27}
 ```
 
-Značka `{default}` funguje podobně s tím rozdílem, že vytváří proměnné jen tehdy, pokud neexistují:
+Značka `{default}` funguje podobně, ale vytváří proměnné jen tehdy, pokud neexistují:
 
 ```latte
 {default $lang = 'cs'}
@@ -751,7 +762,7 @@ Můžete uvádět i [typy proměnných|type-system]. Zatím jsou informativní a
 `{parameters}`
 --------------
 
-Tak jako funkce deklaruje své parametry, může i šablona na začátku deklarovat své proměnné:
+Podobně jako funkce deklaruje své parametry, může i šablona na začátku deklarovat své proměnné:
 
 ```latte
 {parameters
@@ -799,7 +810,7 @@ Ostatní
 `{contentType}`
 ---------------
 
-Značkou určíte, jaký typ obsahu šablona představuje. Možnosti jsou:
+Značka určuje, jaký typ obsahu šablona představuje. Možnosti jsou:
 
 - `html` (výchozí typ)
 - `xml`
@@ -810,7 +821,7 @@ Značkou určíte, jaký typ obsahu šablona představuje. Možnosti jsou:
 
 Její použití je důležité, protože nastaví [kontextově sensitivní escapování |safety-first#Kontextově sensitivní escapování] a jen tak může escapovat správně. Například `{contentType xml}` přepne do režimu XML, `{contentType text}` escapování zcela vypne.
 
-Pokud je parametrem plnohodnotný MIME type, jako například `application/xml`, tak ještě navíc odešle HTTP hlavičku `Content-Type` do prohlížeče:
+Pokud je parametrem plnohodnotný MIME type, jako například `application/xml`, tak navíc odešle HTTP hlavičku `Content-Type` do prohlížeče:
 
 ```latte
 {contentType application/xml}
@@ -882,7 +893,7 @@ Odstraní zbytečné bílé místo z výstupu. Funguje podobně jako filtr [spac
 {/spaceless}
 ```
 
-Vygeneruje
+Vygeneruje:
 
 ```latte
 <ul> <li>Hello</li> </ul>
@@ -894,7 +905,7 @@ Značku lze také zapsat jako [n:attribut|syntax#n:atributy].
 `{syntax}`
 ----------
 
-Latte značky nemusejí být ohraničeny pouze do jednoduchých složených závorek. Můžeme si zvolit i jiný oddělovač a to dokonce za běhu. Slouží k tomu `{syntax …}`, kde jako parametr lze uvést:
+Latte značky nemusejí být ohraničeny pouze jednoduchými složenými závorkami. Můžete si zvolit i jiný oddělovač a to dokonce za běhu. Slouží k tomu `{syntax …}`, kde jako parametr lze uvést:
 
 - double: `{{...}}`
 - off: zcela vypne zpracování Latte značek
@@ -907,9 +918,9 @@ S využitím n:atributů lze vypnout Latte třeba jen jednomu bloku JavaScriptu:
 </script>
 ```
 
-Latte lze velmi pohodlně používat i uvnitř JavaScriptu, jen se stačí vynout konstrukcím jako v tomto příkladě, kdy následuje písmeno hned za `{`, viz [Latte uvnitř JavaScriptu nebo CSS|recipes#Latte uvnitř JavaScriptu nebo CSS].
+Latte lze velmi pohodlně používat i uvnitř JavaScriptu, jen se stačí vyhnout konstrukcím jako v tomto příkladě, kdy následuje písmeno hned za `{`, viz [Latte uvnitř JavaScriptu nebo CSS|recipes#Latte uvnitř JavaScriptu nebo CSS].
 
-Pokud Latte vypnete pomocí `{syntax off}` (tj. značkou, nikoliv n:atributem), bude důsledně ignorovat všechny značky až do `{/syntax}`
+Pokud Latte vypnete pomocí `{syntax off}` (tj. značkou, nikoliv n:atributem), bude důsledně ignorovat všechny značky až do `{/syntax}`.
 
 
 {trace}
@@ -927,7 +938,7 @@ n:class
 
 Díky `n:class` velice snadno vygenerujete HTML atribut `class` přesně podle představ.
 
-Příklad: potřebuji, aby aktivní prvek měl třídu `active`:
+Příklad: potřebujeme, aby aktivní prvek měl třídu `active`:
 
 ```latte
 {foreach $items as $item}
@@ -957,7 +968,7 @@ A všechny prvky mají mít třídu `list-item`:
 n:attr
 ------
 
-Atribut `n:attr` umí se stejnou elegancí jako má [n:class|#n:class] generovat libovolné HTML atributy.
+Atribut `n:attr` umí se stejnou elegancí jako [n:class|#n:class] generovat libovolné HTML atributy.
 
 ```latte
 {foreach $data as $item}
@@ -991,6 +1002,8 @@ Pokud je `$heading === null`, vypíše se beze změny tag `<h1>`. Jinak se změn
 <h3 class="main">...</h3>
 ```
 
+Protože Latte je bezpečný šablonovací systém, kontroluje, zda je nový název značky platný a neobsahuje žádné nežádoucí nebo škodlivé hodnoty.
+
 
 n:ifcontent
 -----------
diff --git a/latte/cs/template-inheritance.texy b/latte/cs/template-inheritance.texy
index 6d3c2bf2c0..de256ad7ca 100644
--- a/latte/cs/template-inheritance.texy
+++ b/latte/cs/template-inheritance.texy
@@ -2,15 +2,15 @@ Dědičnost a znovupoužitelnost šablon
 ************************************
 
 .[perex]
-Mechanismy opětovného použití a dědičnosti šablon zvýší vaši produktivitu, protože každá šablona obsahuje pouze svůj jedinečný obsah a opakované prvky a struktury se znovupoužijí. Představujeme tři koncepty: [#layoutová dědičnost], [#horizontální znovupoužití] a [#jednotková dědičnost].
+Mechanismy dědičnosti a znovupoužitelnosti šablon v Latte významně zvyšují produktivitu vývojářů. Každá šablona tak může obsahovat pouze svůj jedinečný obsah, zatímco opakující se prvky a struktury se efektivně znovupoužívají. V této kapitole představíme tři klíčové koncepty: [layoutovou dědičnost|#layoutová dědičnost], [#horizontální znovupoužití] a [jednotkovou dědičnost|#jednotková dědičnost].
 
-Koncept dědičnosti šablon Latte je podobný dědičnosti tříd v PHP. Definujete **nadřazenou šablonu**, od které mohou dědit další **podřízené šablony** a mohou přepsat části nadřazené šablony. Funguje to skvěle, když prvky sdílejí společnou strukturu. Zní to komplikovaně? Nebojte se, je to velmi snadné.
+Koncept dědičnosti šablon v Latte je analogický k dědičnosti tříd v PHP. Definujete **nadřazenou šablonu**, od které mohou další **podřízené šablony** dědit a případně přepisovat její části. Tento přístup je zvláště účinný, když různé prvky sdílejí společnou strukturu. Ačkoli to může znít složitě, v praxi jde o velmi intuitivní a snadno použitelný systém.
 
 
 Layoutová dědičnost `{layout}` .{toc:Layoutová dědičnost}
 =========================================================
 
-Podívejme se na dědičnost šablony rozložení, tedy layoutu, rovnou příkladem. Toto je nadřazená šablona, kterou budeme nazývat například `layout.latte` a která definuje kostru HTML dokumentu:
+Podívejme se na layoutovou dědičnost na konkrétním příkladu. Následující ukázka představuje nadřazenou šablonu, kterou můžeme nazvat například `layout.latte`. Tato šablona definuje základní kostru HTML dokumentu:
 
 ```latte
 <!doctype html>
@@ -30,36 +30,36 @@ Podívejme se na dědičnost šablony rozložení, tedy layoutu, rovnou příkla
 </html>
 ```
 
-Značky `{block}` definují tři bloky, které mohou podřízené šablony vyplnit. Značka block dělá jen to, že oznámí, že toto místo může podřízená šablona přepsat definováním vlastního bloku se stejným názvem.
+Značky `{block}` zde vymezují tři bloky, které mohou podřízené šablony naplnit vlastním obsahem. Blok v tomto kontextu jednoduše označuje místo, které může podřízená šablona přepsat definováním vlastního bloku se stejným názvem.
 
-Podřízená šablona může vypadat takto:
+Podřízená šablona pak může vypadat například takto:
 
 ```latte
 {layout 'layout.latte'}
 
-{block title}My amazing blog{/block}
+{block title}Můj úžasný blog{/block}
 
 {block content}
-	<p>Welcome to my awesome homepage.</p>
+	<p>Vítejte na mé skvělé domovské stránce.</p>
 {/block}
 ```
 
-Klíčem je zde značka `{layout}`. Říká Latte, že tato šablona „rozšiřuje“ další šablonu. Když Latte vykresluje tuto šablonu, nejprve najde nadřazenou šablonu - v tomto případě `layout.latte`.
+Klíčovým prvkem je zde značka `{layout}`. Ta Latte sděluje, že tato šablona "rozšiřuje" jinou šablonu. Při vykreslování této šablony Latte nejprve nalezne nadřazenou šablonu - v tomto případě `layout.latte`.
 
-V tomto okamžiku si Latte všimne tří blokových značek v `layout.latte` a nahradí tyto bloky obsahem podřízené šablony. Vzhledem k tomu, že podřízená šablona nedefinovala blok *footer*, použije se místo toho obsah z nadřazené šablony. Obsah ve značce `{block}` v nadřazené šabloně se vždy používá jako záložní.
+V tomto okamžiku Latte identifikuje tři blokové značky v `layout.latte` a nahradí tyto bloky obsahem z podřízené šablony. Vzhledem k tomu, že podřízená šablona nedefinovala blok *footer*, použije se pro tento blok obsah z nadřazené šablony. Obsah uvnitř značky `{block}` v nadřazené šabloně vždy slouží jako výchozí, pokud není přepsán.
 
-Výstup může vypadat takto:
+Výsledný výstup může vypadat následovně:
 
 ```latte
 <!doctype html>
 <html lang="en">
 <head>
-	<title>My amazing blog</title>
+	<title>Můj úžasný blog</title>
 	<link rel="stylesheet" href="style.css">
 </head>
 <body>
 	<div id="content">
-		<p>Welcome to my awesome homepage.</p>
+		<p>Vítejte na mé skvělé domovské stránce.</p>
 	</div>
 	<div id="footer">
 		&copy; Copyright 2008
@@ -68,15 +68,15 @@ Výstup může vypadat takto:
 </html>
 ```
 
-V podřízené šabloně mohou být bloky umístěny pouze na nejvyšší úrovni nebo uvnitř jiného bloku, tj .:
+V podřízené šabloně mohou být bloky umístěny pouze na nejvyšší úrovni nebo uvnitř jiného bloku, tj.:
 
 ```latte
 {block content}
-	<h1>{block title}Welcome to my awesome homepage{/block}</h1>
+	<h1>{block title}Vítejte na mé úžasné domovské stránce{/block}</h1>
 {/block}
 ```
 
-Také bude vždy vytvořen blok bez ohledu na to, zda je okolní `{if}` podmínka vyhodnocena jako pravdivá nebo nepravdivá. Takže i když to tak nevypadá, tato šablona blok nadefinuje.
+Je důležité si uvědomit, že blok bude vždy vytvořen bez ohledu na to, zda je okolní `{if}` podmínka vyhodnocena jako pravdivá nebo nepravdivá. Takže i když to tak na první pohled nevypadá, následující šablona blok skutečně definuje:
 
 ```latte
 {if false}
@@ -86,7 +86,7 @@ Také bude vždy vytvořen blok bez ohledu na to, zda je okolní `{if}` podmínk
 {/if}
 ```
 
-Pokud chcete, aby se výstup uvnitř bloku zobrazoval podmíněně, použijte místo toho následující:
+Pokud chcete, aby se obsah uvnitř bloku zobrazoval podmíněně, použijte místo toho následující přístup:
 
 ```latte
 {block head}
@@ -96,7 +96,7 @@ Pokud chcete, aby se výstup uvnitř bloku zobrazoval podmíněně, použijte m
 {/block}
 ```
 
-Prostor mimo bloky v podřízené šabloně se provádí před vykreslením šablony layoutu, takže je můžete použít k definování proměnných jako `{var $foo = bar}` a k šíření dat do celého řetězce dědičnosti:
+Prostor mimo bloky v podřízené šabloně se zpracovává před vykreslením šablony layoutu. Můžete jej tedy využít k definování proměnných pomocí `{var $foo = bar}` a k šíření dat do celého řetězce dědičnosti:
 
 ```latte
 {layout 'layout.latte'}
@@ -108,46 +108,46 @@ Prostor mimo bloky v podřízené šabloně se provádí před vykreslením šab
 
 Víceúrovňová dědičnost
 ----------------------
-Můžete použít tolik úrovní dědičnosti, kolik potřebujete. Běžný způsob použití layoutové dědičnosti je následující tříúrovňový přístup:
+Latte umožňuje použít tolik úrovní dědičnosti, kolik potřebujete. Běžný způsob využití layoutové dědičnosti je následující tříúrovňový přístup:
 
 1) Vytvořte šablonu `layout.latte`, která obsahuje hlavní kostru vzhledu webu.
-2) Vytvořte šablonu `layout-SECTIONNAME.latte` pro každou sekci svého webu. Například `layout-news.latte`, `layout-blog.latte` atd. Všechny tyto šablony rozšiřují `layout.latte` a zahrnují styly & design specifické pro jednotlivé sekce.
+2) Vytvořte šablonu `layout-SECTIONNAME.latte` pro každou sekci vašeho webu. Například `layout-news.latte`, `layout-blog.latte` atd. Všechny tyto šablony rozšiřují `layout.latte` a zahrnují styly a design specifické pro jednotlivé sekce.
 3) Vytvořte individuální šablony pro každý typ stránky, například novinový článek nebo položku blogu. Tyto šablony rozšiřují příslušnou šablonu sekce.
 
 
 Dynamická dědičnost
 -------------------
-Jako název nadřazené šablony lze použít proměnnou nebo jakýkoli výraz PHP, takže dědičnost se může chovat dynamicky:
+Jako název nadřazené šablony lze použít proměnnou nebo jakýkoli výraz PHP, což umožňuje dynamické chování dědičnosti:
 
 ```latte
 {layout $standalone ? 'minimum.latte' : 'layout.latte'}
 ```
 
-Můžete také použít Latte API k [automatickému |develop#automaticke-dohledavani-layoutu] výběru šablony layoutu.
+Latte API také nabízí možnost [automatického výběru |develop#automaticke-dohledavani-layoutu] šablony layoutu.
 
 
-Tipy
-----
-Zde je několik tipů pro práci s layoutovou dědičností:
+Tipy pro práci s layoutovou dědičností
+--------------------------------------
+Zde je několik užitečných tipů pro efektivní práci s layoutovou dědičností:
 
-- Pokud v šabloně použijete `{layout}`, musí to být první značka šablony v této šabloně.
+- Pokud v šabloně použijete `{layout}`, musí to být první značka šablony.
 
-- Layout se může [dohledávat automaticky |develop#automaticke-dohledavani-layoutu] (jako třeba v [presenterech |application:templates#hledani-sablon]). V takovém případě pokud šablona nemá mít layout, oznámí to značkou `{layout none}`.
+- Layout lze [dohledávat automaticky |develop#automaticke-dohledavani-layoutu] (např. v [presenterech |application:templates#hledani-sablon]). V takovém případě, pokud šablona nemá mít layout, oznámí to značkou `{layout none}`.
 
 - Značka `{layout}` má alias `{extends}`.
 
-- Název souboru layoutu závisí na [loaderu |extending-latte#Loadery].
+- Název souboru layoutu závisí na použitém [loaderu |extending-latte#Loadery].
 
-- Můžete mít tolik bloků, kolik chcete. Pamatujte, že podřízené šablony nemusí definovat všechny nadřazené bloky, takže můžete vyplnit přiměřené výchozí hodnoty v několika blocích a poté definovat pouze ty, které potřebujete později.
+- Můžete definovat libovolný počet bloků. Pamatujte, že podřízené šablony nemusí definovat všechny nadřazené bloky, takže můžete nastavit vhodné výchozí hodnoty v několika blocích a později definovat pouze ty, které potřebujete upravit.
 
 
 Bloky `{block}` .{toc: Bloky}
 =============================
 
 .[note]
-Viz také anonymní [`{block}` |tags#block]
+Viz také [anonymní `{block}` |tags#block]
 
-Blok představuje způsob, jak změnit způsob vykreslování určité části šablony, ale nijak nezasahuje do logiky kolem něj. V následujícím příkladu si ukážeme, jak blok funguje, ale také jak nefunguje:
+Blok představuje způsob, jak změnit způsob vykreslování určité části šablony, aniž by to ovlivnilo logiku kolem něj. Následující příklad ilustruje, jak blok funguje a také jeho omezení:
 
 ```latte .{file: parent.latte}
 {foreach $posts as $post}
@@ -158,7 +158,7 @@ Blok představuje způsob, jak změnit způsob vykreslování určité části 
 {/foreach}
 ```
 
-Pokud tuto šablonu vykreslíte, bude výsledek přesně stejný se značkami `{block}` i bez nich. Bloky mají přístup k proměnným z vnějších oborů. Jen dávají možnost se nechat přepsat podřízenou šablonou:
+Při vykreslení této šablony bude výsledek identický s verzí bez značek `{block}` i s nimi. Bloky mají přístup k proměnným z vnějších oborů. Jejich hlavním účelem je poskytnout možnost přepsání obsahu v podřízené šabloně:
 
 ```latte .{file: child.latte}
 {layout 'parent.Latte'}
@@ -171,7 +171,7 @@ Pokud tuto šablonu vykreslíte, bude výsledek přesně stejný se značkami `{
 {/block}
 ```
 
-Nyní při vykreslování podřízené šablony bude smyčka používat blok definovaný v podřízené šabloně `child.Latte` namísto bloku definovaného v `parent.Latte`; spuštěná šablona je pak ekvivalentní následující:
+Nyní při vykreslování podřízené šablony bude smyčka používat blok definovaný v `child.Latte` místo bloku v `parent.Latte`. Výsledná šablona je ekvivalentní následujícímu kódu:
 
 ```latte
 {foreach $posts as $post}
@@ -182,26 +182,26 @@ Nyní při vykreslování podřízené šablony bude smyčka používat blok def
 {/foreach}
 ```
 
-Pokud však vytvoříme novou proměnnou uvnitř pojmenovaného bloku nebo nahradíme hodnotu stávajícího, změna bude viditelná pouze uvnitř bloku:
+Je důležité si uvědomit, že pokud vytvoříte novou proměnnou uvnitř pojmenovaného bloku nebo změníte hodnotu existující proměnné, tato změna bude viditelná pouze uvnitř daného bloku:
 
 ```latte
 {var $foo = 'foo'}
 {block post}
-	{do $foo = 'new value'}
+	{do $foo = 'nová hodnota'}
 	{var $bar = 'bar'}
 {/block}
 
-foo: {$foo}                  // prints: foo
-bar: {$bar ?? 'not defined'} // prints: not defined
+foo: {$foo}                   // vypíše: foo
+bar: {$bar ?? 'nedefinováno'} // vypíše: nedefinováno
 ```
 
-Obsah bloku lze upravit pomocí [filtrů |syntax#filtry]. Následující příklad odebere všechny HTML a změní velikost písmen:
+Obsah bloku lze upravit pomocí [filtrů |syntax#filtry]. Následující příklad odstraní všechny HTML značky a změní velikost písmen:
 
 ```latte
 <title>{block title|stripHtml|capitalize}...{/block}</title>
 ```
 
-Značku lze také zapsat jako [n:attribut|syntax#n:atributy]:
+Značku lze také zapsat jako [n:attribut |syntax#n:atributy]:
 
 ```latte
 <article n:block=post>
@@ -213,7 +213,7 @@ Značku lze také zapsat jako [n:attribut|syntax#n:atributy]:
 Lokální bloky
 -------------
 
-Každý blok přepisuje obsah nadřazeného bloku se stejným názvem – kromě lokálních bloků. Ve třídách by šlo o něco jako privátní metody. Šablonu tak můžete tvořit bez obav, že kvůli shodě jmen bloků by byly přepsány z jiné šablony.
+Každý blok standardně přepisuje obsah nadřazeného bloku se stejným názvem – s výjimkou lokálních bloků. Ty fungují podobně jako privátní metody ve třídách. Díky nim můžete vytvářet šablonu bez obav, že by kvůli shodě jmen bloků došlo k nechtěnému přepsání z jiné šablony.
 
 ```latte
 {block local helper}
@@ -228,7 +228,7 @@ Vykreslení bloků `{include}` .{toc: Vykreslení bloků}
 .[note]
 Viz také [`{include file}` |tags#include]
 
-Chcete-li blok vypsat na určitém místě, použijte značku `{include blockname}`:
+Pro vypsání bloku na určitém místě použijte značku `{include blockname}`:
 
 ```latte
 <title>{block title}{/block}</title>
@@ -236,13 +236,13 @@ Chcete-li blok vypsat na určitém místě, použijte značku `{include blocknam
 <h1>{include title}</h1>
 ```
 
-Lze také vypsat blok z jiné šablony:
+Můžete také vypsat blok z jiné šablony:
 
 ```latte
 {include footer from 'main.latte'}
 ```
 
-Vykreslovaný blok nemá přístup k proměnným aktivního kontextu, kromě případů, kdy je blok definován ve stejném souboru, kde je i vložen. Má však přístup ke globálním proměnným.
+Vykreslovaný blok nemá přístup k proměnným aktivního kontextu, s výjimkou případů, kdy je blok definován ve stejném souboru, kde je i vložen. Má však přístup ke globálním proměnným.
 
 Proměnné můžete do bloku předávat tímto způsobem:
 
@@ -250,14 +250,14 @@ Proměnné můžete do bloku předávat tímto způsobem:
 {include footer, foo: bar, id: 123}
 ```
 
-Jako název bloku lze použít proměnnou nebo jakýkoli výraz v PHP. V takovém případě před proměnnou ještě doplníme klíčové slovo `block`, aby už v době kompilace Latte vědělo, že jde blok, a nikoliv o [vkládání šablony|tags#include], jejíž název by také mohl být v proměnné:
+Jako název bloku lze použít proměnnou nebo jakýkoli výraz v PHP. V takovém případě před proměnnou doplníme klíčové slovo `block`, aby Latte vědělo, že jde o blok, a nikoli o [vkládání šablony |tags#include], jejíž název by také mohl být v proměnné:
 
 ```latte
 {var $name = footer}
 {include block $name}
 ```
 
-Blok lze vykreslit i uvnitř sebe samého, což je například užitečné při vykreslování stromové struktury:
+Blok lze vykreslit i uvnitř sebe samého, což je užitečné například při vykreslování stromové struktury:
 
 ```latte
 {define menu, $items}
@@ -275,9 +275,9 @@ Blok lze vykreslit i uvnitř sebe samého, což je například užitečné při
 {/define}
 ```
 
-Místo `{include menu, ...}` pak můžeme napsat `{include this, ...}`, kde `this` znamená aktuální blok.
+Místo `{include menu, ...}` můžeme také napsat `{include this, ...}`, kde `this` odkazuje na aktuální blok.
 
-Vykreslovaný blok lze upravit pomocí [filtrů |syntax#filtry]. Následující příklad odebere všechna HTML a změní velikost písmen:
+Vykreslovaný blok lze upravit pomocí [filtrů |syntax#filtry]. Následující příklad odstraní všechny HTML značky a změní velikost písmen:
 
 ```latte
 <title>{include heading|stripHtml|capitalize}</title>
@@ -287,7 +287,7 @@ Vykreslovaný blok lze upravit pomocí [filtrů |syntax#filtry]. Následující
 Rodičovský blok
 ---------------
 
-Pokud potřebujete vypsat obsah bloku z nadřazené šablony, použijte `{include parent}`. To je užitečné, pokud chcete jen doplnit obsah nadřazeného bloku místo jeho úplného přepsání.
+Pokud potřebujete vypsat obsah bloku z nadřazené šablony, použijte `{include parent}`. To je užitečné, pokud chcete pouze doplnit obsah nadřazeného bloku místo jeho úplného přepsání.
 
 ```latte
 {block footer}
@@ -301,9 +301,9 @@ Pokud potřebujete vypsat obsah bloku z nadřazené šablony, použijte `{includ
 Definice `{define}` .{toc: Definice}
 ------------------------------------
 
-Kromě bloků existují v Latte také „definice“. V běžných programovacích jazycích bychom je přirovnali k funkcím. Jsou užitečné k opětovnému použití fragmentů šablony, abyste se neopakovali.
+Kromě bloků existují v Latte také „definice". V běžných programovacích jazycích by se daly přirovnat k funkcím. Jsou užitečné pro opakované použití fragmentů šablony, čímž se vyhnete duplikaci kódu.
 
-Latte se snaží dělat věci jednoduše, takže v zásadě jsou definice stejné jako bloky a **všechno, co je o blocích řečeno, platí také pro definice**. Liší se od bloků tím, že:
+Latte se snaží zjednodušovat věci, takže v zásadě jsou definice stejné jako bloky a **vše, co platí pro bloky, platí také pro definice**. Liší se od bloků v následujících aspektech:
 
 1) jsou uzavřeny ve značkách `{define}`
 2) vykreslí se teprve, až když je vložíte přes `{include}`
@@ -311,16 +311,16 @@ Latte se snaží dělat věci jednoduše, takže v zásadě jsou definice stejn
 
 ```latte
 {block foo}<p>Hello</p>{/block}
-{* prints: <p>Hello</p> *}
+{* vypíše: <p>Hello</p> *}
 
 {define bar}<p>World</p>{/define}
-{* prints nothing *}
+{* nevypíše nic *}
 
 {include bar}
-{* prints: <p>World</p> *}
+{* vypíše: <p>World</p> *}
 ```
 
-Představte si, že máte pomocnou šablonu s kolekcí definic, jak kreslit formuláře HTML.
+Představte si, že máte pomocnou šablonu s kolekcí definic pro vykreslování HTML formulářů:
 
 ```latte .{file: forms.latte}
 {define input, $name, $value, $type = 'text'}
@@ -332,9 +332,9 @@ Představte si, že máte pomocnou šablonu s kolekcí definic, jak kreslit form
 {/define}
 ```
 
-Argumenty jsou vždy volitelné s výchozí hodnotou `null`, pokud není uvedena výchozí hodnota (zde `'text'` je výchozí hodnota pro `$type`). Lze deklarovat také typy parametrů: `{define input, string $name, ...}`.
+Argumenty jsou vždy volitelné s výchozí hodnotou `null`, pokud není uvedena explicitní výchozí hodnota (zde `'text'` je výchozí hodnota pro `$type`). Můžete také deklarovat typy parametrů: `{define input, string $name, ...}`.
 
-Šablonu s definicemi nahrajeme pomocí [`{import}` |#horizontalni-znovupouziti]. Samotné definice se vykreslují [stejným způsobem jako bloky |#Vykreslení bloků]:
+Šablonu s definicemi načteme pomocí [`{import}` |#horizontalni-znovupouziti]. Samotné definice se vykreslují [stejným způsobem jako bloky |#Vykreslení bloků]:
 
 ```latte
 <p>{include input, 'password', null, 'password'}</p>
@@ -347,26 +347,26 @@ Definice nemají přístup k proměnným aktivního kontextu, ale mají přístu
 Dynamické názvy bloků
 ---------------------
 
-Latte dovoluje velkou flexibilitu při definování bloků, protože název bloku může být jakýkoli výraz PHP. Tento příklad definuje tři bloky s názvy `hi-Peter`, `hi-John` a `hi-Mary`:
+Latte nabízí velkou flexibilitu při definování bloků, protože název bloku může být jakýkoli výraz PHP. Tento příklad definuje tři bloky s názvy `hi-Peter`, `hi-John` a `hi-Mary`:
 
 ```latte .{file: parent.latte}
 {foreach [Peter, John, Mary] as $name}
-	{block "hi-$name"}Hi, I am {$name}.{/block}
+	{block "hi-$name"}Ahoj, já jsem {$name}.{/block}
 {/foreach}
 ```
 
 V podřízené šabloně pak můžeme předefinovat například jen jeden blok:
 
 ```latte .{file: child.latte}
-{block hi-John}Hello. I am {$name}.{/block}
+{block hi-John}Zdravím. Jmenuji se {$name}.{/block}
 ```
 
-Takže výstup bude vypadat takto:
+Výstup bude vypadat takto:
 
 ```latte
-Hi, I am Peter.
-Hello. I am John.
-Hi, I am Mary.
+Ahoj, já jsem Peter.
+Zdravím. Jmenuji se John.
+Ahoj, já jsem Mary.
 ```
 
 
@@ -376,7 +376,7 @@ Kontrola existence bloků `{ifset}` .{toc: Kontrola existence bloků}
 .[note]
 Viz také [`{ifset $var}` |tags#ifset-elseifset]
 
-Pomocí testu `{ifset blockname}` zkontrolujeme, zda v aktuálním kontextu blok (nebo více bloků) existuje:
+Pomocí testu `{ifset blockname}` můžete zkontrolovat, zda v aktuálním kontextu existuje blok (nebo více bloků):
 
 ```latte
 {ifset footer}
@@ -388,7 +388,7 @@ Pomocí testu `{ifset blockname}` zkontrolujeme, zda v aktuálním kontextu blok
 {/ifset}
 ```
 
-Jako název bloku lze použít proměnnou nebo jakýkoli výraz v PHP. V takovém případě před proměnnou ještě doplníme klíčové slovo `block`, aby bylo jasné, že nejde o test existence [proměnných|tags#ifset-elseifset]:
+Jako název bloku lze použít proměnnou nebo jakýkoli výraz v PHP. V takovém případě před proměnnou doplníme klíčové slovo `block`, aby bylo jasné, že nejde o test existence [proměnných |tags#ifset-elseifset]:
 
 ```latte
 {ifset block $name}
@@ -396,28 +396,36 @@ Jako název bloku lze použít proměnnou nebo jakýkoli výraz v PHP. V takové
 {/ifset}
 ```
 
+Existenci bloků ověřuje také funkce [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
-Tipy
-----
-Několik tipů pro práci s bloky:
+Tipy pro práci s bloky
+----------------------
+Několik užitečných tipů pro efektivní práci s bloky:
 
 - Poslední blok nejvyšší úrovně nemusí mít uzavírací značku (blok končí koncem dokumentu). To zjednodušuje psaní podřízených šablon, které obsahují jeden primární blok.
 
-- Pro lepší čitelnost můžete název bloku uvést ve značce `{/block}`, například `{/block footer}`. Název se však musí shodovat s názvem bloku. Ve větších šablonách vám tato technika pomůže zjistit, které značky bloku se zavírají.
+- Pro lepší čitelnost můžete název bloku uvést ve značce `{/block}`, například `{/block footer}`. Název se však musí shodovat s názvem bloku. Ve větších šablonách vám tato technika pomůže snadno identifikovat, které bloky se uzavírají.
 
-- Ve stejné šabloně nemůžete přímo definovat více značek bloků se stejným názvem. Toho však lze dosáhnout pomocí [dynamických názvů bloků|#dynamické názvy bloků].
+- Ve stejné šabloně nemůžete přímo definovat více značek bloků se stejným názvem. Toho však lze dosáhnout pomocí [dynamických názvů bloků |#dynamické názvy bloků].
 
-- Můžete použít [n:atributy |syntax#n:atributy] k definování bloků jako `<h1 n:block=title>Welcome to my awesome homepage</h1>`
+- Můžete použít [n:atributy |syntax#n:atributy] k definování bloků, například: `<h1 n:block=title>Vítejte na mé úžasné domovské stránce</h1>`
 
-- Bloky lze také použít bez názvů pouze k použití [filtrů|syntax#filtry]: `{block|strip} hello {/block}`
+- Bloky lze také použít bez názvů pouze k aplikaci [filtrů |syntax#filtry]: `{block|strip} hello {/block}`
 
 
 Horizontální znovupoužití `{import}` .{toc: Horizontální znovupoužití}
 ======================================================================
 
-Horizontální znovupoužití je v Latte třetím mechanismem opětovné použitelnosti a dědičnosti. Umožňuje načíst bloky z jiných šablon. Je to podobné jako vytvoření souboru PHP s pomocnými funkcemi.
+Horizontální znovupoužití je v Latte třetím mechanismem pro opětovné použití a dědičnost. Umožňuje načítat bloky z jiných šablon. Je to podobné, jako když si v PHP vytvoříme soubor s pomocnými funkcemi, který potom načítáme pomocí `require`.
 
-I když je layoutová dědičnost šablony jednou z nejmocnějších funkcí Latte, je omezena na jednoduchou dědičnost - šablona může rozšířit pouze jednu další šablonu. Horizontální znovupoužití je způsob, jak dosáhnout vícenásobné dědičnosti.
+I když je layoutová dědičnost šablony jednou z nejsilnějších funkcí Latte, je omezena na jednoduchou dědičnost - šablona může rozšířit pouze jednu další šablonu. Horizontální znovupoužití je způsob, jak dosáhnout vícenásobné dědičnosti.
 
 Mějme soubor s definicemi bloků:
 
@@ -437,7 +445,7 @@ Pomocí příkazu `{import}` naimportujeme všechny bloky a [#definice] definova
 
 Pokud bloky importujete v nadřazené šabloně (tj. použijete `{import}` v `layout.latte`), budou bloky k dispozici i ve všech podřízených šablonách, což je velmi praktické.
 
-Šablona, která je určená k importování (např. `blocks.latte`), nesmí [rozšiřovat|#Layoutová dědičnost] další šablonu, tj. používat `{layout}`. Může však importovat další šablony.
+Šablona, která je určena k importování (např. `blocks.latte`), nesmí [rozšiřovat |#Layoutová dědičnost] další šablonu, tj. používat `{layout}`. Může však importovat další šablony.
 
 Značka `{import}` by měla být první značkou šablony po `{layout}`. Název šablony může být jakýkoli výraz PHP:
 
@@ -445,9 +453,9 @@ Značka `{import}` by měla být první značkou šablony po `{layout}`. Název
 {import $ajax ? 'ajax.latte' : 'not-ajax.latte'}
 ```
 
-V šabloně můžete použít tolik `{import}` příkazů, kolik chcete. Pokud dvě importované šablony definují stejný blok, vyhrává první z nich. Nejvyšší prioritu má ale hlavní šablona, která může přepsat jakýkoli importovaný blok.
+V šabloně můžete použít tolik `{import}` příkazů, kolik potřebujete. Pokud dvě importované šablony definují stejný blok, má přednost první z nich. Nejvyšší prioritu má ale hlavní šablona, která může přepsat jakýkoli importovaný blok.
 
-Ke všem přepsaným blokům se dá postupně dostat tím že je vložíme jako vložen jak [#rodičovský blok]:
+Obsah přepsaných bloků se dá zachovat tak, že blok vložíme stejně, jako se vkládá [#rodičovský blok]:
 
 ```latte
 {layout 'layout.latte'}
@@ -468,11 +476,11 @@ V tomto příkladu `{include parent}` zavolá blok `sidebar` ze šablony `blocks
 Jednotková dědičnost `{embed}` .{toc: Jednotková dědičnost}
 ===========================================================
 
-Jednotková dědičnost rozšiřuje myšlenku layoutové dědičnosti na úroveň fragmentů obsahu. Zatímco layoutová dědičnost pracuje s  „kostrou dokumentu“, kterou oživují podřízené šablony, jednotková dědičnost vám umožňuje vytvářet kostry pro menší jednotky obsahu a znovu je používat kdekoli chcete.
+Jednotková dědičnost rozšiřuje koncept layoutové dědičnosti na úroveň fragmentů obsahu. Zatímco layoutová dědičnost pracuje s  "kostrou dokumentu", kterou oživují podřízené šablony, jednotková dědičnost vám umožňuje vytvářet znovupoužitelné kostry pro menší jednotky obsahu a používat je kdekoli potřebujete.
 
-V jednotkové dědičnosti je klíčem značka `{embed}`. Kombinuje chování `{include}` a `{layout}`. Umožňuje vložit obsah jiné šablony či bloku a volitelně předat proměnné, stejně jako v případě `{include}`. Umožňuje také přepsat libovolný blok definovaný uvnitř vložené šablony, jako při použití `{layout}`.
+Klíčovým prvkem jednotkové dědičnosti je značka `{embed}`. Ta kombinuje funkčnost `{include}` a `{layout}`. Umožňuje vložit obsah jiné šablony či bloku a volitelně předat proměnné, stejně jako v případě `{include}`. Zároveň umožňuje přepsat libovolný blok definovaný uvnitř vložené šablony, podobně jako při použití `{layout}`.
 
-Například použijeme prvek akordeon. Podívejme se na kostru prvku uloženou v šabloně `collapsible.latte`:
+Podívejme se na příklad s prvkem akordeon. Nejprve definujeme kostru prvku v šabloně `collapsible.latte`:
 
 ```latte
 <section class="collapsible {$modifierClass}">
@@ -486,9 +494,9 @@ Například použijeme prvek akordeon. Podívejme se na kostru prvku uloženou v
 </section>
 ```
 
-Značky `{block}` definují dva bloky, které mohou podřízené šablony vyplnit. Ano, jako v případě nadřazené šablony v layoutové  dědičnosti. Vidíte také proměnnou `$modifierClass`.
+Značky `{block}` definují dva bloky, které mohou podřízené šablony naplnit. Fungují stejně jako v případě nadřazené šablony v layoutové dědičnosti. Všimněte si také proměnné `$modifierClass`.
 
-Pojďme použít náš prvek v šabloně. Tady přichází ke slovu `{embed}`. Jedná se o mimořádně výkonnou značku, která nám umožňuje dělat všechny věci: vložit obsah šablony prvku, přidat do něj proměnné a přidat do něj bloky s vlastním HTML:
+Nyní použijeme náš prvek v šabloně. Zde přichází ke slovu `{embed}`. Tato výkonná značka nám umožňuje provést několik věcí najednou: vložit obsah šablony prvku, přidat do něj proměnné a definovat bloky s vlastním HTML:
 
 ```latte
 {embed 'collapsible.latte', modifierClass: my-style}
@@ -518,7 +526,7 @@ Výstup může vypadat takto:
 </section>
 ```
 
-Bloky uvnitř vložených značek tvoří samostatnou vrstvu nezávislou na ostatních blocích. Proto mohou mít stejný název jako blok mimo vložení a nejsou nijak ovlivněny. Pomocí značky [include |#Vykreslení bloků] uvnitř značek `{embed}` můžete vložit bloky zde  vytvořené, bloky z vložené šablony (které *nejsou* [lokální |#lokální bloky]) a také bloky z hlavní šablony, které naopak *jsou* lokální. Můžete také [importovat bloky |#horizontální znovupoužití] z jiných souborů:
+Bloky uvnitř vložených značek tvoří samostatnou vrstvu nezávislou na ostatních blocích. Proto mohou mít stejný název jako blok mimo vložení a nejsou jím nijak ovlivněny. Pomocí značky [include |#Vykreslení bloků] uvnitř značek `{embed}` můžete vložit bloky zde vytvořené, bloky z vložené šablony (které *nejsou* [lokální |#lokální bloky]) a také bloky z hlavní šablony, které naopak *jsou* lokální. Můžete také [importovat bloky |#horizontální znovupoužití] z jiných souborů:
 
 ```latte
 {block outer}…{/block}
@@ -530,18 +538,18 @@ Bloky uvnitř vložených značek tvoří samostatnou vrstvu nezávislou na osta
 	{block inner}…{/block}
 
 	{block title}
-		{include inner} {* works, block is defined inside embed *}
-		{include hello} {* works, block is local in this template *}
-		{include content} {* works, block is defined in embedded template *}
-		{include aBlockDefinedInImportedTemplate} {* works *}
-		{include outer} {* does not work! - block is in outer layer *}
+		{include inner} {* funguje, blok je definován uvnitř embed *}
+		{include hello} {* funguje, blok je lokální v této šabloně *}
+		{include content} {* funguje, blok je definován ve vložené šabloně *}
+		{include aBlockDefinedInImportedTemplate} {* funguje *}
+		{include outer} {* nefunguje! - blok je ve vnější vrstvě *}
 	{/block}
 {/embed}
 ```
 
-Vložené šablony nemají přístup k proměnným aktivního kontextu, ale mají přístup k globálním proměnným.
+Vložené šablony nemají přístup k proměnným aktivního kontextu, ale mají přístup ke globálním proměnným.
 
-Pomocí `{embed}` lze vkládat nejen šablony, ale i jiné bloky, a tedy předchozí příklad by se dal zapsat tímto způsobem:
+Pomocí `{embed}` lze vkládat nejen šablony, ale i jiné bloky. Předchozí příklad by se dal zapsat tímto způsobem:
 
 ```latte
 {define collapsible}
@@ -572,7 +580,7 @@ Pokud do `{embed}` předáme výraz a není zřejmé, jestli jde o název bloku
 Případy použití
 ===============
 
-V Latte existují různé typy dědičnosti a opětovného použití kódu. Pojďme si shrnout hlavní koncepty pro větší srozumitelnost:
+V Latte existují různé typy dědičnosti a opětovného použití kódu. Pojďme si shrnout hlavní koncepty pro lepší pochopení:
 
 
 `{include template}`
@@ -629,7 +637,7 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 {layout 'layout.latte'}
 
 {block main}
-	<p>Homepage</p>
+	<p>Domovská stránka</p>
 {/block}
 ```
 
@@ -639,7 +647,7 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 {layout 'layout.latte'}
 
 {block main}
-	<p>About page</p>
+	<p>Stránka O nás</p>
 {/block}
 ```
 
@@ -647,12 +655,12 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 `{import}`
 ----------
 
-**Případ použití**: `sidebar.latte` v `single.product.latte` a `single.service.latte`.
+**Případ použití**: Použití `sidebar.latte` v `single.product.latte` a `single.service.latte`.
 
 `sidebar.latte`
 
 ```latte
-{block sidebar}<aside>This is sidebar</aside>{/block}
+{block sidebar}<aside>Toto je postranní panel</aside>{/block}
 ```
 
 `single.product.latte`
@@ -662,7 +670,7 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 
 {import 'sidebar.latte'}
 
-{block main}<main>Product page</main>{/block}
+{block main}<main>Stránka produktu</main>{/block}
 ```
 
 `single.service.latte`
@@ -672,14 +680,14 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 
 {import 'sidebar.latte'}
 
-{block main}<main>Service page</main>{/block}
+{block main}<main>Stránka služby</main>{/block}
 ```
 
 
 `{define}`
 ----------
 
-**Případ použití**: Funkce, které předáme proměnné a něco vykreslí.
+**Případ použití**: Funkce, kterým předáme proměnné a něco vykreslí.
 
 `form.latte`
 
@@ -697,7 +705,7 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 <form action="" method="post">
 	<div>{include form-input, username}</div>
 	<div>{include form-input, password}</div>
-	<div>{include form-input, submit, Submit, submit}</div>
+	<div>{include form-input, submit, Odeslat, submit}</div>
 </form>
 ```
 
@@ -725,8 +733,8 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 
 ```latte
 {embed 'pagination.latte', min: 1, max: $products->count}
-	{block first}First Product Page{/block}
-	{block last}Last Product Page{/block}
+	{block first}První stránka produktů{/block}
+	{block last}Poslední stránka produktů{/block}
 {/embed}
 ```
 
@@ -734,7 +742,23 @@ V Latte existují různé typy dědičnosti a opětovného použití kódu. Poj
 
 ```latte
 {embed 'pagination.latte', min: 1, max: $services->count}
-	{block first}First Service Page{/block}
-	{block last}Last Service Page{/block}
+	{block first}První stránka služeb{/block}
+	{block last}Poslední stránka služeb{/block}
 {/embed}
 ```
+
+Tyto příklady ilustrují, jak různé mechanismy dědičnosti a znovupoužitelnosti v Latte spolupracují, aby umožnily vytváření flexibilních, modulárních a snadno udržovatelných šablon. Každý z těchto přístupů má své specifické použití:
+
+1. `{include template}` je užitečný pro vkládání menších, opakujících se částí stránek, jako jsou hlavičky a patičky.
+
+2. `{layout}` umožňuje vytvářet konzistentní strukturu napříč různými stránkami webu, přičemž jednotlivé stránky mohou upravovat specifické části.
+
+3. `{import}` je skvělý pro sdílení bloků kódu mezi různými šablonami, což podporuje princip DRY (Don't Repeat Yourself).
+
+4. `{define}` je ideální pro vytváření znovupoužitelných komponent, které přijímají parametry, jako jsou formulářové prvky.
+
+5. `{embed}` kombinuje flexibilitu vkládání s možností přepisovat části vloženého obsahu, což je užitečné pro komplexnější komponenty jako je stránkování.
+
+Použitím těchto technik můžete vytvářet vysoce modulární, flexibilní a snadno udržovatelné šablony pro vaše webové aplikace. Latte tak nabízí pokročilé možnosti pro strukturování šablon, které uspokojí potřeby i těch nejnáročnějších projektů.
+
+{{leftbar: /@left-menu}}
diff --git a/latte/cs/type-system.texy b/latte/cs/type-system.texy
index 82d417b622..90fdf4f43c 100644
--- a/latte/cs/type-system.texy
+++ b/latte/cs/type-system.texy
@@ -3,19 +3,19 @@ Typový systém
 
 <div class=perex>
 
-Typový systém je klíčový pro vývoj robustních aplikací. Latte přináší podporou typů i do šablon. Díky tomu, že víme, jaký datový či objektový typ je v každé proměnné, může
+Typový systém je základním kamenem pro vývoj robustních aplikací. Latte přináší podporu typů i do šablon. Díky znalosti datových či objektových typů každé proměnné můžeme dosáhnout:
 
-- IDE správně našeptávat (viz [integrace|recipes#Editory a IDE])
-- statická analýza odhalit chyby
+- Přesného našeptávání v IDE (viz [integrace|recipes#Editory a IDE])
+- Odhalení chyb pomocí statické analýzy
 
-Obojí zásadním způsobem zvyšuje kvalitu a pohodlí vývoje.
+Tyto funkce výrazně zvyšují kvalitu kódu a usnadňují vývojový proces.
 
 </div>
 
 .[note]
-Deklarované typy jsou informativní a Latte je v tuto chvíli nekontroluje.
+Je důležité poznamenat, že deklarované typy jsou v současné době pouze informativní a Latte je aktivně nekontroluje.
 
-Jak začít používat typy? Vytvořte si třídu šablony, např. `CatalogTemplateParameters`, reprezentující předávané parametry, jejich typy a případně i výchozí hodnoty:
+Jak implementovat typový systém? Začněte vytvořením třídy reprezentující parametry šablony, například `CatalogTemplateParameters`. Tato třída definuje předávané parametry, jejich typy a případně i výchozí hodnoty:
 
 ```php
 class CatalogTemplateParameters
@@ -35,19 +35,22 @@ $latte->render('template.latte', new CatalogTemplateParameters(
 ));
 ```
 
-A dále na začátek šablony vložte značku `{templateType}` s plným názvem třídy (včetně namespace). To definuje, že v šabloně jsou proměnné `$langs` a `$products` včetně příslušných typů.
-Typy lokálních proměnných můžete uvést pomocí značek [`{var}` |tags#var-default], `{varType}`, [`{define}` |template-inheritance#definice].
+Následně na začátek šablony umístěte značku `{templateType}` s plně kvalifikovaným názvem třídy (včetně namespace). Tím definujete, že v šabloně jsou k dispozici proměnné `$langs` a `$products` s příslušnými typy.
+Pro lokální proměnné můžete typy specifikovat pomocí značek [`{var}` |tags#var-default], `{varType}`, nebo [`{define}` |template-inheritance#definice].
 
-Od té chvíle vám může IDE správně našeptávat.
+Tyto kroky umožní vašemu IDE poskytovat přesné našeptávání.
 
-Jak si ušetřit práci? Jak co nejsnáze napsat třídu s parametry šablony nebo značky `{varType}`? Nechte si je vygenerovat.
-Od toho existuje dvojice značek `{templatePrint}` a `{varPrint}`.
-Pokud je umístíte do šablony, místo běžného vykreslení se zobrazí návrh kódu třídy resp. seznam značek `{varType}`. Kód pak stačí jedním kliknutím označit a zkopírovat do projektu.
+Pro usnadnění práce s typovým systémem Latte nabízí nástroje pro automatické generování kódu:
+
+- `{templatePrint}` generuje návrh třídy s parametry šablony
+- `{varPrint}` vytváří seznam značek `{varType}` pro lokální proměnné
+
+Tyto značky při použití v šabloně zobrazí návrh kódu místo běžného vykreslení. Vygenerovaný kód lze pak jednoduše zkopírovat do vašeho projektu nebo šablony.
 
 
 `{templateType}`
 ----------------
-Typy parametrů předávaných do šablony deklarujeme pomocí třídy:
+Pro deklaraci typů parametrů předávaných do šablony použijte třídu následujícím způsobem:
 
 ```latte
 {templateType MyApp\CatalogTemplateParameters}
@@ -56,7 +59,7 @@ Typy parametrů předávaných do šablony deklarujeme pomocí třídy:
 
 `{varType}`
 -----------
-Jak deklarovat typy proměnných? K tomu slouží značky `{varType}` pro existující proměnné, nebo [`{var}` |tags#var-default]:
+Pro deklaraci typů existujících proměnných použijte `{varType}`, pro nové proměnné [`{var}` |tags#var-default]:
 
 ```latte
 {varType Nette\Security\User $user}
@@ -66,7 +69,7 @@ Jak deklarovat typy proměnných? K tomu slouží značky `{varType}` pro existu
 
 `{templatePrint}`
 -----------------
-Třídu si také můžete nechat vygenerovat pomocí značky `{templatePrint}`. Pokud ji umístíte na začátek šablony, místo běžného vykreslení se zobrazí návrh třídy. Kód pak stačí jedním kliknutím označit a zkopírovat do projektu.
+Pro automatické generování třídy parametrů šablony použijte `{templatePrint}` na začátku šablony. Místo běžného vykreslení se zobrazí návrh třídy, který můžete jednoduše zkopírovat do svého projektu.
 
 
 `{varPrint}`
@@ -74,3 +77,5 @@ Třídu si také můžete nechat vygenerovat pomocí značky `{templatePrint}`.
 Značka `{varPrint}` vám ušetří čas se psaním. Pokud ji umístíte do šablony, místo běžného vykreslení se zobrazí návrh značek `{varType}` pro lokální proměnné. Kód pak stačí jedním kliknutím označit a zkopírovat do šablony.
 
 Samotné `{varPrint}` vypisuje pouze lokální proměnné, které nejsou parametry šablony. Pokud chcete vypsat všechny proměnné, použijte `{varPrint all}`.
+
+Implementace typového systému v Latte významně přispívá k vytváření robustnějších a lépe udržovatelných šablon, což vede k celkovému zlepšení kvality vašich aplikací.
diff --git a/latte/de/@left-menu.texy b/latte/de/@left-menu.texy
index b0f0fc6fa1..5383a5178d 100644
--- a/latte/de/@left-menu.texy
+++ b/latte/de/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Erste Schritte |Guide]
 - [Warum Vorlagen verwenden? |why-use]
-- Konzepte
+- Konzepte ⚗️
 	- [Sicherheit zuerst |Safety First]
 	- [Vererbung von Vorlagen |Template Inheritance]
 	- [Typ-System |Type System]
 	- [Sandkasten |Sandbox]
 
-- Für Konstrukteure
+- Für Konstrukteure 🎨
 	- [Syntax]
 	- [Tags]
 	- [Filtern |Filters]
 	- [Funktionen |Functions]
 	- [Tipps und Tricks |recipes]
 
-- Für Entwickler
+- Für Entwickler 🧮
 	- [Praktiken für Entwickler |develop]
 	- [Erweitern von Latte |Extending Latte]
 	- [Erstellen einer Erweiterung |creating-extension]
 
-- [Kochbuch |cookbook/@home]
+- [Kochbuch 💡|cookbook/@home]
 	- [Migration von Twig |cookbook/migration-from-twig]
 	- [... mehr |cookbook/@home]
 
diff --git a/latte/de/cookbook/@home.texy b/latte/de/cookbook/@home.texy
index 32d8a0126c..a3a5ee44e1 100644
--- a/latte/de/cookbook/@home.texy
+++ b/latte/de/cookbook/@home.texy
@@ -4,7 +4,9 @@ Kochbuch
 .[perex]
 Beispielcodes und Rezepte für die Erledigung gängiger Aufgaben mit Latte.
 
-- [Alles, was Sie schon immer über {iterateWhile} wissen wollten |iteratewhile]
+- [Leitlinien für Entwickler |/develop]
+- [Übergabe von Variablen zwischen Vorlagen |passing-variables]
+- [Alles, was Sie schon immer über Gruppierung wissen wollten |grouping]
 - [Wie schreibt man SQL-Abfragen in Latte? |how-to-write-sql-queries-in-latte]
 - [Umstieg von PHP |migration-from-php]
 - [Umstieg von Twig |migration-from-twig]
diff --git a/latte/de/cookbook/grouping.texy b/latte/de/cookbook/grouping.texy
new file mode 100644
index 0000000000..269c862dbc
--- /dev/null
+++ b/latte/de/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Was Sie schon immer über Gruppierung wissen wollten
+***************************************************
+
+.[perex]
+Wenn Sie mit Daten in Vorlagen arbeiten, haben Sie oft das Bedürfnis, diese zu gruppieren oder sie nach bestimmten Kriterien anzuzeigen. Zu diesem Zweck bietet Latte mehrere leistungsstarke Werkzeuge.
+
+Der Filter und die Funktion `|group` ermöglichen eine effiziente Gruppierung von Daten nach bestimmten Kriterien, während der Filter `|batch` die Aufteilung von Daten in feste Chargen erleichtert und das Tag `{iterateWhile}` die Möglichkeit einer komplexeren Zyklussteuerung mit Bedingungen bietet.
+Jedes dieser Tags bietet spezifische Optionen für die Arbeit mit Daten, was sie zu unverzichtbaren Werkzeugen für die dynamische und strukturierte Anzeige von Informationen in Latte-Vorlagen macht.
+
+
+Filter und Funktionen `group` .[#toc-filter-and-function-group]
+===============================================================
+
+Stellen Sie sich eine Datenbanktabelle `items` mit in Kategorien unterteilten Artikeln vor:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Apfel
+| 2 | 1 | Banane
+| 3 | 2 | PHP
+| 4 | 3 | Grün
+| 5 | 3 | Rot
+| 6 | 3 | Blau
+
+Eine einfache Liste aller Elemente mit einer Latte-Vorlage würde wie folgt aussehen:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Wenn wir die Artikel jedoch nach Kategorien gruppieren wollen, müssen wir sie so unterteilen, dass jede Kategorie ihre eigene Liste hat. Das Ergebnis würde dann wie folgt aussehen:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Die Aufgabe kann einfach und elegant mit `|group` gelöst werden. Wir geben `categoryId` als Parameter an, was bedeutet, dass die Elemente auf der Grundlage des Werts `$item->categoryId` in kleinere Arrays aufgeteilt werden (wenn `$item` ein Array wäre, würden wir `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Der Filter kann auch als Funktion in Latte verwendet werden, wodurch wir eine alternative Syntax erhalten: `{foreach group($items, categoryId) ...}`.
+
+Wenn Sie Elemente nach komplexeren Kriterien gruppieren möchten, können Sie eine Funktion im Filterparameter verwenden. Eine Gruppierung nach der Länge des Namens würde zum Beispiel so aussehen:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Es ist wichtig zu beachten, dass `$categoryItems` kein normales Array ist, sondern ein Objekt, das sich wie ein Iterator verhält. Um auf das erste Element in der Gruppe zuzugreifen, können Sie die [`first()` |latte:functions#first] Funktion verwenden.
+
+Diese Flexibilität bei der Datengruppierung macht `group` zu einem äußerst nützlichen Werkzeug für die Darstellung von Daten in Latte-Vorlagen.
+
+
+Verschachtelte Schleifen .[#toc-nested-loops]
+---------------------------------------------
+
+Nehmen wir an, wir haben eine Datenbanktabelle mit einer weiteren Spalte `subcategoryId`, die Unterkategorien für jeden Artikel definiert. Wir möchten jede Hauptkategorie in einer separaten `<ul>` Liste und jede Unterkategorie in einer separaten geschachtelten `<ol>` Liste anzeigen:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Verbindung mit der Nette-Datenbank .[#toc-connection-with-nette-database]
+-------------------------------------------------------------------------
+
+Lassen Sie uns zeigen, wie Sie die Datengruppierung in Kombination mit Nette Database effektiv nutzen können. Nehmen wir an, wir arbeiten mit der Tabelle `items` aus dem ersten Beispiel, die über die Spalte `categoryId` mit dieser Tabelle `categories` verbunden ist:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Früchte |
+| 2 | Sprachen |
+| 3 | Farben |
+
+Wir laden die Daten aus der Tabelle `items` mit dem Nette Database Explorer Befehl `$items = $db->table('items')`. Bei der Iteration über diese Daten haben wir die Möglichkeit, nicht nur auf Attribute wie `$item->name` und `$item->categoryId` zuzugreifen, sondern dank der Verbindung mit der Tabelle `categories` auch auf die zugehörige Zeile in dieser Tabelle über `$item->category`. Diese Verbindung kann interessante Anwendungen aufweisen:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+In diesem Fall verwenden wir den Filter `|group`, um nach der verbundenen Zeile `$item->category` zu gruppieren, nicht nur nach der Spalte `categoryId`. Dadurch erhalten wir die `ActiveRow` der gegebenen Kategorie im variablen Schlüssel, so dass wir ihren Namen mit `{$category->name}` direkt anzeigen können. Dies ist ein praktisches Beispiel dafür, wie die Gruppierung die Vorlagen vereinfachen und die Datenverarbeitung erleichtern kann.
+
+
+Filter `|batch` .[#toc-filter-batch]
+====================================
+
+Mit dem Filter können Sie eine Liste von Elementen in Gruppen mit einer bestimmten Anzahl von Elementen aufteilen. Dieser Filter ist ideal für Situationen, in denen Sie Daten in mehreren kleineren Gruppen darstellen möchten, z. B. für eine bessere Übersichtlichkeit oder visuelle Organisation auf der Seite.
+
+Stellen Sie sich vor, Sie haben eine Liste von Elementen und möchten diese in Listen darstellen, die jeweils maximal drei Elemente enthalten. Die Verwendung des Filters `|batch` ist in einem solchen Fall sehr praktisch:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+In diesem Beispiel wird die Liste `$items` in kleinere Gruppen unterteilt, wobei jede Gruppe (`$batch`) bis zu drei Einträge enthält. Jede Gruppe wird dann in einer eigenen `<ul>` Liste angezeigt.
+
+Wenn die letzte Gruppe nicht genügend Elemente enthält, um die gewünschte Anzahl zu erreichen, können Sie mit dem zweiten Parameter des Filters festlegen, womit diese Gruppe ergänzt werden soll. Dies ist ideal, um Elemente ästhetisch auszurichten, bei denen eine unvollständige Reihe unordentlich aussehen könnte.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Tag `{iterateWhile}` .[#toc-tag-iteratewhile]
+=============================================
+
+Wir werden die gleichen Aufgaben, die wir mit dem `|group` Filter behandelt haben, mit dem `{iterateWhile}` Tag demonstrieren. Der Hauptunterschied zwischen den beiden Ansätzen besteht darin, dass `group` zunächst alle Eingabedaten verarbeitet und gruppiert, während `{iterateWhile}` den Fortschritt von Zyklen mit Bedingungen steuert, so dass die Iteration sequentiell erfolgt.
+
+Zunächst wird mit iterateWhile eine Tabelle mit Kategorien gezeichnet:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Während `{foreach}` den äußeren Teil des Zyklus markiert, d. h. das Zeichnen von Listen für jede Kategorie, markiert das Tag `{iterateWhile}` den inneren Teil, d. h. die einzelnen Elemente.
+Die Bedingung im End-Tag besagt, dass die Wiederholung so lange fortgesetzt wird, wie das aktuelle und das nächste Element zur selben Kategorie gehören (`$iterator->nextValue` ist das [nächste Element |/tags#$iterator]).
+
+Wenn die Bedingung immer erfüllt wäre, würden alle Elemente im inneren Zyklus gezeichnet werden:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Das Ergebnis sieht dann so aus:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Wozu dient iterateWhile auf diese Weise? Wenn die Tabelle leer ist und keine Elemente enthält, wird kein leeres `<ul></ul>` gedruckt.
+
+Wenn wir die Bedingung im einleitenden `{iterateWhile}` -Tag angeben, ändert sich das Verhalten: Die Bedingung (und der Übergang zum nächsten Element) wird am Anfang des inneren Zyklus ausgeführt, nicht am Ende.
+Während Sie also `{iterateWhile}` immer ohne Bedingungen eingeben, geben Sie `{iterateWhile $cond}` nur ein, wenn die Bedingung `$cond` erfüllt ist. Und gleichzeitig wird das nächste Element in `$item` geschrieben.
+
+Dies ist z. B. dann nützlich, wenn wir das erste Element in jeder Kategorie anders darstellen wollen, etwa so:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Wir ändern den ursprünglichen Code so, dass wir zuerst das erste Element darstellen und dann im inneren Zyklus `{iterateWhile}` die anderen Elemente derselben Kategorie darstellen:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Innerhalb eines Zyklus können wir mehrere innere Schleifen erstellen und diese sogar verschachteln. Auf diese Weise können zum Beispiel Unterkategorien gruppiert werden.
+
+Angenommen, die Tabelle hat eine weitere Spalte `subcategoryId`, und neben jeder Kategorie in einer separaten `<ul>`, jede Unterkategorie in einer separaten `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/de/cookbook/iteratewhile.texy b/latte/de/cookbook/iteratewhile.texy
deleted file mode 100644
index fa408e8cda..0000000000
--- a/latte/de/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Was Sie schon immer über {iterateWhile} wissen wollten
-******************************************************
-
-.[perex]
-Das Tag `{iterateWhile}` ist für verschiedene Tricks in foreach-Zyklen geeignet.
-
-Angenommen, wir haben die folgende Datenbanktabelle, in der die Elemente in Kategorien unterteilt sind:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Es ist natürlich einfach, Elemente in einer foreach-Schleife als Liste zu zeichnen:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Aber was ist zu tun, wenn Sie jede Kategorie in einer separaten Liste darstellen wollen? Mit anderen Worten, wie kann man die Aufgabe lösen, Elemente aus einer linearen Liste in einem foreach-Zyklus zu gruppieren. Die Ausgabe sollte wie folgt aussehen:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Wir werden Ihnen zeigen, wie einfach und elegant die Aufgabe mit iterateWhile gelöst werden kann:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Während `{foreach}` den äußeren Teil des Zyklus markiert, d.h. die Erstellung von Listen für jede Kategorie, geben die Tags `{iterateWhile}` den inneren Teil an, d.h. die einzelnen Elemente.
-Die Bedingung im End-Tag besagt, dass die Wiederholung so lange fortgesetzt wird, wie das aktuelle und das nächste Element zur selben Kategorie gehören (`$iterator->nextValue` ist das [nächste Element |/tags#$iterator]).
-
-Wenn die Bedingung immer erfüllt ist, werden alle Elemente im inneren Zyklus gezeichnet:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Das Ergebnis sieht dann so aus:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Wozu ist eine solche Verwendung von iterateWhile gut? Wie unterscheidet sie sich von der Lösung, die wir ganz am Anfang des Tutorials gezeigt haben? Der Unterschied besteht darin, dass die Tabelle, wenn sie leer ist und keine Elemente enthält, nicht leer dargestellt wird `<ul></ul>`.
-
-
-Lösung ohne `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-------------------------------------------------------------------
-
-Würden wir die gleiche Aufgabe mit ganz einfachen Konstruktionen von Template-Systemen lösen, zum Beispiel in Twig, Blade oder reinem PHP, würde die Lösung etwa so aussehen:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* die Kategorie hat sich geändert *}
-
-		{* wir schließen das vorherige <ul>, wenn es nicht das erste Element ist *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* wir öffnen eine neue Liste *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* wir schließen die letzte Liste *}
-	</ul>
-{/if}
-```
-
-Dieser Code ist jedoch unverständlich und unintuitiv. Der Zusammenhang zwischen den öffnenden und schließenden HTML-Tags ist überhaupt nicht klar. Es ist nicht auf den ersten Blick klar, ob ein Fehler vorliegt. Und es werden Hilfsvariablen wie `$prevCatId` benötigt.
-
-Im Gegensatz dazu ist die Lösung mit `{iterateWhile}` sauber, klar, benötigt keine Hilfsvariablen und ist narrensicher.
-
-
-Bedingung im abschließenden Tag .[#toc-condition-in-the-closing-tag]
---------------------------------------------------------------------
-
-Wenn wir im öffnenden Tag `{iterateWhile}` eine Bedingung angeben, ändert sich das Verhalten: Die Bedingung (und der Übergang zum nächsten Element) wird am Anfang des inneren Zyklus ausgeführt, nicht am Ende.
-Während also `{iterateWhile}` ohne Bedingung immer eingegeben wird, wird `{iterateWhile $cond}` nur eingegeben, wenn die Bedingung `$cond` erfüllt ist. Gleichzeitig wird das folgende Element in `$item` geschrieben.
-
-Dies ist z. B. dann nützlich, wenn Sie das erste Element in jeder Kategorie auf unterschiedliche Weise darstellen möchten, z. B:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Ändern wir den ursprünglichen Code, zeichnen wir das erste Element und dann weitere Elemente aus derselben Kategorie in der inneren Schleife `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Verschachtelte Schleifen .[#toc-nested-loops]
----------------------------------------------
-
-Wir können mehrere innere Schleifen in einem Zyklus erstellen und sie sogar verschachteln. Auf diese Weise können zum Beispiel Unterkategorien gruppiert werden.
-
-Angenommen, es gibt eine weitere Spalte in der Tabelle `subCatId` und jede Kategorie befindet sich nicht nur in einer separaten `<ul>`befindet, wird jede Unterkategorie in einer separaten `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filter |Batch .[#toc-filter-batch]
-----------------------------------
-
-Die Gruppierung von linearen Elementen erfolgt ebenfalls über einen Filter `batch` in Stapel mit einer festen Anzahl von Elementen:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Er kann wie folgt durch iterateWhile ersetzt werden:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/de/cookbook/passing-variables.texy b/latte/de/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..146456a1a8
--- /dev/null
+++ b/latte/de/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Übergabe von Variablen über Templates hinweg
+********************************************
+
+In diesem Leitfaden wird erklärt, wie Variablen zwischen Vorlagen in Latte mit Hilfe verschiedener Tags wie `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` und anderen übergeben werden. Sie erfahren auch, wie Sie mit Variablen in den Tags `{block}` und `{define}` arbeiten können und welchen Zweck das Tag `{parameters}` erfüllt.
+
+
+Arten von Variablen .[#toc-types-of-variables]
+----------------------------------------------
+Variablen in Latte können in drei Kategorien unterteilt werden, je nachdem, wie und wo sie definiert sind:
+
+**Eingabevariablen** sind diejenigen, die von außen an die Vorlage übergeben werden, z. B. von einem PHP-Skript oder mit einem Tag wie `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Umgebungsvariablen** sind Variablen, die an der Stelle eines bestimmten Tags existieren. Dazu gehören alle Eingabevariablen und andere Variablen, die mit Tags wie `{var}`, `{default}` oder innerhalb einer Schleife `{foreach}` erstellt werden.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Explizite Variablen** sind diejenigen, die direkt in einem Tag angegeben und an die Zielvorlage gesendet werden.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Das Tag `{block}` wird verwendet, um wiederverwendbare Codeblöcke zu definieren, die in vererbten Vorlagen angepasst oder erweitert werden können. Die vor dem Block definierten Umgebungsvariablen sind innerhalb des Blocks verfügbar, aber alle Änderungen an den Variablen werden nur innerhalb dieses Blocks berücksichtigt.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Das Tag `{define}` wird verwendet, um Blöcke zu erstellen, die nur gerendert werden, wenn sie mit `{include}` aufgerufen werden. Die innerhalb dieser Blöcke verfügbaren Variablen hängen davon ab, ob in der Definition Parameter angegeben sind. Wenn Parameter angegeben sind, sind nur diese Parameter zugänglich. Wenn nicht, sind alle Eingabevariablen der Vorlage, in der die Blöcke definiert sind, zugänglich.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Das Tag `{parameters}` wird verwendet, um erwartete Eingabevariablen am Anfang der Vorlage explizit zu deklarieren. Auf diese Weise können Sie erwartete Variablen und ihre Datentypen leicht dokumentieren. Es ist auch möglich, Standardwerte zu definieren.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Das Tag `{include file}` wird verwendet, um eine komplette Vorlage einzufügen. Dieser Vorlage werden sowohl die Eingabevariablen der Vorlage, in der das Tag verwendet wird, als auch explizit definierte Variablen übergeben. Die Zielvorlage kann jedoch den Umfang mit `{parameters}` einschränken.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Beim Einfügen eines Blocks, der in derselben Vorlage definiert ist, werden alle umgebenden und explizit definierten Variablen an ihn übergeben:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+In diesem Beispiel werden die Variablen `$name` und `$age` an den Block `blockName` übergeben. Das gleiche Verhalten gilt für `{include parent}`.
+
+Beim Einfügen eines Blocks aus einer anderen Vorlage werden nur Eingabevariablen und explizit definierte Variablen übergeben. Umgebende Variablen sind nicht automatisch verfügbar.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` oder `{extends}`
+---------------------------
+Diese Tags definieren ein Layout, an das Eingabevariablen der untergeordneten Vorlage und Variablen, die im Code vor den Blöcken erstellt wurden, übergeben werden:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Vorlage `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Der `{embed}` -Tag ähnelt dem `{include}` -Tag, ermöglicht aber die Einbettung von Blöcken in die Vorlage. Im Gegensatz zu `{include}` werden nur explizit deklarierte Variablen übergeben:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+In diesem Beispiel hat die Vorlage `menu.latte` nur Zugriff auf die Variable `$items`.
+
+Umgekehrt haben die Blöcke innerhalb von `{embed}` Zugriff auf alle umgebenden Variablen:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Das Tag `{import}` wird verwendet, um Blöcke aus anderen Vorlagen zu laden. Sowohl Eingabe- als auch explizit deklarierte Variablen werden an die importierten Blöcke übergeben.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Das Tag `{sandbox}` isoliert die Vorlage für eine sichere Verarbeitung. Variablen werden ausschließlich explizit übergeben.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/de/creating-extension.texy b/latte/de/creating-extension.texy
index feb6f1c164..a679750994 100644
--- a/latte/de/creating-extension.texy
+++ b/latte/de/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// eine Parsing-Funktion, die vorerst nur einen Knoten erstellt
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Wenn Sie ein neues Tag für Latte erstellen, ist es ratsam, eine eigene Knotenklasse dafür zu erstellen, die es im AST-Baum repräsentiert (siehe die Klasse `ForeachNode` im obigen Beispiel). In einigen Fällen kann die triviale Hilfsknotenklasse [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] nützlich sein, die es Ihnen ermöglicht, den Körper der Methode `print()` und die Liste der Knoten, die durch die Methode `getIterator()` zugänglich gemacht werden, als Konstruktorparameter zu übergeben:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Compiler übergibt .[#toc-compiler-passes]
 =========================================
 
diff --git a/latte/de/develop.texy b/latte/de/develop.texy
index 5f99949089..62d7c01529 100644
--- a/latte/de/develop.texy
+++ b/latte/de/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Schauplatz .[#toc-locale]{data-version:3.0.18}
+==============================================
+
+Mit Latte können Sie das Gebietsschema festlegen, das sich auf die Formatierung von Zahlen, Daten und die Sortierung auswirkt. Sie wird mit der Methode `setLocale()` festgelegt. Der Locale-Identifikator folgt dem IETF-Standard für Sprachtags, der die PHP-Erweiterung `intl` verwendet. Er besteht aus einem Sprachcode und möglicherweise einem Ländercode, z. B. `en_US` für Englisch in den Vereinigten Staaten, `de_DE` für Deutsch in Deutschland usw.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Die Locale-Einstellung wirkt sich auf die Filter [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] und [bytes |filters#bytes] aus.
+
+.[note]
+Erfordert die PHP-Erweiterung `intl`. Die Einstellung in Latte hat keinen Einfluss auf die globale Locale-Einstellung in PHP.
+
+
 Strenger Modus .[#toc-strict-mode]{data-version:3.0.8}
 ======================================================
 
@@ -271,19 +287,28 @@ Wenn Sie benutzerdefinierte Tags verwenden, erstellen Sie auch Ihren eigenen Lin
 #!/usr/bin/env php
 <?php
 
-// gibt den aktuellen Pfad zur Datei autoload.php an
+// den aktuellen Pfad zur Datei autoload.php eingeben
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// hier individuelle Erweiterungen hinzufügen
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// fügen Sie hier Ihre individuellen Erweiterungen hinzu
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternativ können Sie dem Linter auch Ihr eigenes `Latte\Engine` Objekt übergeben:
+
+```php
+$latte = new Latte\Engine;
+// hier konfigurieren wir das $latte-Objekt
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Laden von Templates aus einem String .[#toc-loading-templates-from-a-string]
 ============================================================================
diff --git a/latte/de/extending-latte.texy b/latte/de/extending-latte.texy
index ea40c60918..3c2e5a6872 100644
--- a/latte/de/extending-latte.texy
+++ b/latte/de/extending-latte.texy
@@ -68,6 +68,16 @@ Wie Sie sehen können, erhält die Funktion die linke Seite des Filters vor der
 
 Natürlich kann die Funktion, die den Filter darstellt, eine beliebige Anzahl von Parametern annehmen, und auch variable Parameter werden unterstützt.
 
+Wenn der Filter eine Zeichenkette in HTML zurückgibt, können Sie diese so markieren, dass Latte sie nicht automatisch (und damit doppelt) umbricht. Dadurch wird vermieden, dass Sie `|noescape` in der Vorlage angeben müssen.
+Am einfachsten ist es, die Zeichenkette in ein `Latte\Runtime\Html` Objekt zu verpacken, die andere Möglichkeit sind [kontextuelle Filter |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+In diesem Fall muss der Filter das korrekte Escaping der Daten sicherstellen.
+
 
 Filter, die die Klasse .[#toc-filters-using-the-class]
 ------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// Inhaltstyp in HTML ändern
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/de/filters.texy b/latte/de/filters.texy
index 3784d34eb4..a205f37276 100644
--- a/latte/de/filters.texy
+++ b/latte/de/filters.texy
@@ -1,99 +1,101 @@
-Latte Filtern
-*************
+Latte Filter
+************
 
 .[perex]
-Filter sind Funktionen, die die Daten in der gewünschten Form verändern oder formatieren. Dies ist eine Zusammenfassung der eingebauten Filter, die verfügbar sind.
+In Templates können wir Funktionen verwenden, die bei der Anpassung oder Umformatierung von Daten in die endgültige Form helfen. Wir nennen sie *Filter*.
 
 .[table-latte-filters]
-|## String / Array Transformation
-| `batch` | [Auflistung linearer Daten in einer Tabelle |#batch]
-| `breakLines` | [fügt HTML-Zeilenumbrüche vor allen Zeilenumbrüchen ein |#breakLines]
-| `bytes` | [formatiert Größe in Bytes |#bytes]
-| `clamp` | [klemmt Wert auf den Bereich |#clamp]
-| `dataStream` | [Konvertierung des Daten-URI-Protokolls |#datastream]
-| `date` | [formatiert Datum |#date]
-| `explode` | [trennt eine Zeichenkette durch das angegebene Trennzeichen auf |#explode]
-| `first` | [gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück |#first]
-| `implode` | [fügt ein Array zu einer Zeichenkette zusammen |#implode]
-| `indent` | [rückt den Text von links mit einer Anzahl von Tabulatorenein |#indent]
-| `join` | [verbindet ein Array mit einer Zeichenkette|#implode]
-| `last` | [gibt das letzte Element eines Arrays oder ein Zeichen einer Zeichenkette zurück |#last]
-| `length` | [gibt die Länge einer Zeichenkette oder eines Arrays zurück |#length]
-| `number` | [formatiert Zahlen |#number]
-| `padLeft` | [vervollständigt die Zeichenkette auf die angegebene Länge von links |#padLeft]
-| `padRight` | [vervollständigt die Zeichenkette auf die angegebene Länge von rechts |#padRight]
-| `random` | [gibt zufällige Elemente eines Arrays oder Zeichen einer Zeichenkette zurück |#random]
-| `repeat` | [Wiederholt die Zeichenkette |#repeat]
-| `replace` | [ersetzt alle Vorkommen der gesuchten Zeichenkette durch die Ersetzung |#replace]
-| `replaceRE` | [ersetzt alle Vorkommen entsprechend dem regulären Ausdruck |#replaceRE]
-| `reverse` | [kehrt eine UTF-8 Zeichenkette oder ein Array um |#reverse]
-| `slice` | [extrahiert einen Ausschnitt aus einem Array oder einer Zeichenkette |#slice]
-| `sort` | [sortiert ein Array |#sort]
-| `spaceless` | [entfernt Leerzeichen |#spaceless], ähnlich dem [spaceless |tags] tag
-| `split` | [trennt eine Zeichenkette durch das angegebene Trennzeichen auf |#explode]
-| `strip` | [Entfernt Leerzeichen |#spaceless]
-| `stripHtml` | [entfernt HTML-Tags und konvertiert HTML-Entities in Text |#stripHtml]
-| `substr` | [gibt einen Teil der Zeichenkette zurück |#substr]
-| `trim` | [entfernt Leerzeichen aus der Zeichenkette |#trim]
-| `translate` | [Übersetzung in andere Sprachen |#translate]
-| `truncate` | [verkürzt die Länge unter Beibehaltung ganzer Wörter |#truncate]
-| `webalize` | [passt die UTF-8-Zeichenfolge an die in der URL verwendete Forman |#webalize]
+|## Transformation
+| `batch`      | [Auflistung linearer Daten in einer Tabelle |#batch]
+| `breakLines` | [Fügt HTML-Zeilenumbrüche am Ende der Zeilen hinzu |#breakLines]
+| `bytes`      | [formatiert die Größe in Bytes |#bytes]
+| `clamp`      | [begrenzt einen Wert auf einen bestimmten Bereich |#clamp]
+| `dataStream` | [Konvertierung für das Data URI-Protokoll |#datastream]
+| `date`       | [formatiert Datum und Uhrzeit |#date]
+| `explode`    | [teilt eine Zeichenkette in ein Array anhand eines Trennzeichens |#explode]
+| `first`      | [gibt das erste Element eines Arrays oder Zeichen einer Zeichenkette zurück |#first]
+| `group`      | [gruppiert Daten nach verschiedenen Kriterien |#group]
+| `implode`    | [verbindet ein Array zu einer Zeichenkette |#implode]
+| `indent`     | [rückt Text von links um eine bestimmte Anzahl von Tabulatoren ein |#indent]
+| `join`       | [verbindet ein Array zu einer Zeichenkette |#implode]
+| `last`       | [gibt das letzte Element eines Arrays oder Zeichen einer Zeichenkette zurück |#last]
+| `length`     | [gibt die Länge einer Zeichenkette in Zeichen oder eines Arrays zurück |#length]
+| `localDate`  | [formatiert Datum und Uhrzeit entsprechend den Ländereinstellungen |#localDate]
+| `number`     | [formatiert eine Zahl |#number]
+| `padLeft`    | [füllt eine Zeichenkette links auf eine bestimmte Länge auf |#padLeft]
+| `padRight`   | [füllt eine Zeichenkette rechts auf eine bestimmte Länge auf |#padRight]
+| `random`     | [gibt ein zufälliges Element eines Arrays oder Zeichen einer Zeichenkette zurück |#random]
+| `repeat`     | [Wiederholung einer Zeichenkette |#repeat]
+| `replace`    | [ersetzt Vorkommen einer gesuchten Zeichenkette |#replace]
+| `replaceRE`  | [ersetzt Vorkommen anhand eines regulären Ausdrucks |#replaceRE]
+| `reverse`    | [kehrt eine UTF-8 Zeichenkette oder ein Array um |#reverse]
+| `slice`      | [extrahiert einen Teil eines Arrays oder einer Zeichenkette |#slice]
+| `sort`       | [sortiert ein Array |#sort]
+| `spaceless`  | [entfernt Leerzeichen |#spaceless], ähnlich wie das [spaceless |tags] Tag
+| `split`      | [teilt eine Zeichenkette in ein Array anhand eines Trennzeichens |#explode]
+| `strip`      | [entfernt Leerzeichen |#spaceless]
+| `stripHtml`  | [entfernt HTML-Tags und konvertiert HTML-Entities in Zeichen |#stripHtml]
+| `substr`     | [gibt einen Teil einer Zeichenkette zurück |#substr]
+| `trim`       | [entfernt führende und abschließende Leerzeichen oder andere Zeichen |#trim]
+| `translate`  | [Übersetzung in andere Sprachen |#translate]
+| `truncate`   | [kürzt die Länge unter Beibehaltung von Wörtern |#truncate]
+| `webalize`   | [passt eine UTF-8 Zeichenkette in eine in URLs verwendete Form an |#webalize]
 
 .[table-latte-filters]
-|## Buchstabenumbruch
-| `capitalize` | [Kleinschreibung, der erste Buchstabe eines jeden Wortes wird großgeschrieben |#capitalize]
-| `firstUpper` | [macht den ersten Buchstaben zu einem Großbuchstaben |#firstUpper]
-| `lower` | [macht eine Zeichenfolge klein |#lower]
-| `upper` | [macht eine Zeichenkette zu einem Großbuchstaben |#upper]
+|## Groß-/Kleinschreibung
+| `capitalize` | [Kleinbuchstaben, erste Buchstaben der Wörter groß |#capitalize]
+| `firstUpper` | [konvertiert den ersten Buchstaben in einen Großbuchstaben |#firstUpper]
+| `lower`      | [konvertiert in Kleinbuchstaben |#lower]
+| `upper`      | [konvertiert in Großbuchstaben |#upper]
 
 .[table-latte-filters]
-|## Rundung von Zahlen
-| `ceil` | [rundet eine Zahl auf eine bestimmte Genauigkeit auf|#ceil]
-| `floor` | [rundet eine Zahl auf eine bestimmte Genauigkeit ab |#floor]
-| `round` | [rundet eine Zahl auf eine bestimmte Genauigkeit|#round]
+|## Rundung
+| `ceil`       | [rundet eine Zahl auf eine bestimmte Genauigkeit auf |#ceil]
+| `floor`      | [rundet eine Zahl auf eine bestimmte Genauigkeit ab |#floor]
+| `round`      | [rundet eine Zahl auf eine bestimmte Genauigkeit |#round]
 
 .[table-latte-filters]
 |## Escaping
-| `escapeUrl` | [gibt einen Parameter in der URL als Escapezeichen aus|#escapeUrl]
-| `noescape` | [druckt eine Variable ohne Escaping |#noescape]
-| `query` | [erzeugt eine Abfragezeichenfolge in der URL |#query]
+| `escapeUrl`  | [escapet einen Parameter in einer URL |#escapeUrl]
+| `noescape`   | [gibt eine Variable ohne Escaping aus |#noescape]
+| `query`      | [generiert einen Query-String in einer URL |#query]
 
-Es gibt auch Escape-Filter für HTML (`escapeHtml` und `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) und iCalendar (`escapeICal`), die Latte dank [kontextsensitivem Escaping |safety-first#Context-aware escaping] selbst verwendet und die Sie nicht schreiben müssen.
+Es gibt außerdem Escaping-Filter für HTML (`escapeHtml` und `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) und iCalendar (`escapeICal`), die Latte selbst dank [kontextsensitivem Escaping |safety-first#Context-aware escaping] verwendet und die Sie nicht explizit schreiben müssen.
 
 .[table-latte-filters]
 |## Sicherheit
-| `checkUrl` | [säubert Zeichenketten für die Verwendung im href-Attribut |#checkUrl]
-| `nocheck` | [verhindert automatische URL-Sanitisierung |#nocheck]
+| `checkUrl`   | [behandelt eine URL-Adresse gegen gefährliche Eingaben |#checkUrl]
+| `nocheck`    | [verhindert die automatische Behandlung einer URL-Adresse |#nocheck]
 
-Latte der `src` und `href` Attribute [prüft automatisch |safety-first#link checking], so dass Sie den `checkUrl` Filter fast nicht verwenden müssen.
+Latte [überprüft automatisch |safety-first#link checking] die Attribute `src` und `href`, sodass Sie den `checkUrl`-Filter fast nie verwenden müssen.
 
 
 .[note]
-Alle eingebauten Filter arbeiten mit UTF-8 kodierten Zeichenketten.
+Alle Standard-Filter sind für Zeichenketten in UTF-8-Kodierung ausgelegt.
 
 
 Verwendung .[#toc-usage]
 ========================
 
-Latte erlaubt den Aufruf von Filtern unter Verwendung der Pipe-Schreibweise (vorangestelltes Leerzeichen ist erlaubt):
+Filter werden durch einen senkrechten Strich notiert (vor dem ein Leerzeichen stehen kann):
 
 ```latte
 <h1>{$heading|upper}</h1>
 ```
 
-Filter können verkettet werden, in diesem Fall gelten sie in der Reihenfolge von links nach rechts:
+Filter (in älteren Versionen Helper genannt) können verkettet werden und werden dann in der Reihenfolge von links nach rechts angewendet:
 
 ```latte
 <h1>{$heading|lower|capitalize}</h1>
 ```
 
-Die Parameter werden durch Doppelpunkt oder Komma getrennt hinter den Filternamen gesetzt:
+Parameter werden nach dem Filternamen durch Doppelpunkte oder Kommas getrennt angegeben:
 
 ```latte
 <h1>{$heading|truncate:20,''}</h1>
 ```
 
-Filter können auf Ausdrücke angewendet werden:
+Filter können auch auf Ausdrücke angewendet werden:
 
 ```latte
 {var $name = ($title|upper) . ($subtitle|lower)}</h1>
@@ -106,7 +108,7 @@ $latte = new Latte\Engine;
 $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len));
 ```
 
-Wir verwenden sie in einer Vorlage wie dieser:
+Im Template wird es dann so aufgerufen:
 
 ```latte
 <p>{$text|shortify}</p>
@@ -118,9 +120,9 @@ Filter .[#toc-filters]
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
-Filter, der die Auflistung von linearen Daten in Form einer Tabelle vereinfacht. Er gibt ein Array von Arrays mit der angegebenen Anzahl von Elementen zurück. Wenn Sie einen zweiten Parameter angeben, wird dieser verwendet, um fehlende Elemente in der letzten Zeile aufzufüllen.
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
+Ein Filter, der die Ausgabe linearer Daten in Form einer Tabelle vereinfacht. Er gibt ein Array von Arrays mit der angegebenen Anzahl von Elementen zurück. Wenn Sie einen zweiten Parameter angeben, wird er verwendet, um fehlende Elemente in der letzten Zeile zu ergänzen.
 
 ```latte
 {var $items = ['a', 'b', 'c', 'd', 'e']}
@@ -135,7 +137,7 @@ Filter, der die Auflistung von linearen Daten in Form einer Tabelle vereinfacht.
 </table>
 ```
 
-Druckt:
+Gibt aus:
 
 ```latte
 <table>
@@ -152,20 +154,22 @@ Druckt:
 </table>
 ```
 
+Siehe auch [#group] und das [iterateWhile |tags#iterateWhile] Tag.
+
 
 breakLines .[filter]
 --------------------
-Fügt HTML-Zeilenumbrüche vor allen Zeilenumbrüchen ein.
+Fügt vor jedem Zeilenumbruchzeichen ein HTML-Tag `<br>` ein
 
 ```latte
 {var $s = "Text & with \n newline"}
-{$s|breakLines}    {* gibt "Text &amp; with <br>\n newline" *}
+{$s|breakLines}    {* gibt "Text &amp; with <br>\n newline" aus *}
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formatiert eine Größe in Bytes in eine für Menschen lesbare Form.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formatiert die Größe in Bytes in eine menschenlesbare Form. Wenn [Ländereinstellungen |develop#locale] gesetzt sind, werden die entsprechenden Dezimal- und Tausendertrennzeichen verwendet.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,53 +177,53 @@ Formatiert eine Größe in Bytes in eine für Menschen lesbare Form.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
-Rundet eine Zahl bis zu einer bestimmten Genauigkeit.
+ceil(int $precision=0) .[filter]
+--------------------------------
+Rundet eine Zahl auf eine bestimmte Genauigkeit auf.
 
 ```latte
-{=3.4|ceil}         {* gibt 4      *}
-{=135.22|ceil:1}    {* gibt 135.3  *}
-{=135.22|ceil:3}    {* gibt 135.22 *}
+{=3.4|ceil}         {* gibt 4      aus *}
+{=135.22|ceil:1}    {* gibt 135.3  aus *}
+{=135.22|ceil:3}    {* gibt 135.22 aus *}
 ```
 
-Siehe auch [Stockwerk |#floor], [Runden |#round].
+Siehe auch [#floor], [#round].
 
 
 capitalize .[filter]
 --------------------
-Gibt eine Version des Wertes in Großbuchstaben zurück. Die Wörter beginnen mit Großbuchstaben, alle übrigen Zeichen sind Kleinbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
+Wörter beginnen mit Großbuchstaben, alle verbleibenden Zeichen sind klein. Erfordert die PHP-Erweiterung `mbstring`.
 
 ```latte
-{='i like LATTE'|capitalize}  {* gibt 'I Like Latte' *}
+{='i like LATTE'|capitalize}  {* gibt 'I Like Latte' aus *}
 ```
 
-Siehe auch [firstUpper |#firstUpper], [lower |#lower], [upper |#upper].
+Siehe auch [#firstUpper], [#lower], [#upper].
 
 
 checkUrl .[filter]
 ------------------
-Erzwingt URL-Sanitization. Sie prüft, ob die Variable eine Web-URL enthält (d. h. HTTP/HTTPS-Protokoll) und verhindert das Schreiben von Links, die ein Sicherheitsrisiko darstellen könnten.
+Erzwingt die Behandlung einer URL-Adresse. Überprüft, ob die Variable eine Web-URL enthält (d.h. HTTP/HTTPS-Protokoll) und verhindert die Ausgabe von Links, die ein Sicherheitsrisiko darstellen können.
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>geprüft</a>
+<a data-href={$link}>ungeprüft</a>
 ```
 
-Druckt:
+Gibt aus:
 
 ```latte
-<a data-href="">checked</a>
-<a data-href="javascript:window.close()">unchecked</a>
+<a data-href="">geprüft</a>
+<a data-href="javascript:window.close()">ungeprüft</a>
 ```
 
-Siehe auch [nocheck |#nocheck].
+Siehe auch [#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
-Gibt einen Wert zurück, der auf den einschließenden Bereich von min und max geklemmt ist.
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
+Begrenzt einen Wert auf den angegebenen inklusiven Bereich von min und max.
 
 ```latte
 {$level|clamp: 0, 255}
@@ -228,17 +232,17 @@ Gibt einen Wert zurück, der auf den einschließenden Bereich von min und max ge
 Existiert auch als [Funktion |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
-Konvertiert den Inhalt in ein Daten-URI-Schema. Es kann verwendet werden, um Bilder in HTML oder CSS einzufügen, ohne dass externe Dateien verlinkt werden müssen.
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
+Konvertiert den Inhalt in das Data URI-Schema. Damit können Bilder ohne die Notwendigkeit externer Dateien in HTML oder CSS eingebettet werden.
 
-Nehmen wir an, ein Bild befindet sich in einer Variablen `$img = Image::fromFile('obrazek.gif')`, dann
+Angenommen, wir haben ein Bild in der Variable `$img = Image::fromFile('bild.gif')`, dann
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
-Druckt zum Beispiel:
+Gibt beispielsweise aus:
 
 ```latte
 <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
@@ -250,105 +254,125 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Erfordert die PHP-Erweiterung `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Liefert ein Datum im angegebenen Format unter Verwendung der Optionen der PHP-Funktionen [php:strftime] oder [php:date]. Der Filter erhält ein Datum als UNIX-Zeitstempel, als String oder als Objekt vom Typ `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formatiert Datum und Uhrzeit gemäß der von der PHP-Funktion [php:date] verwendeten Maske. Der Filter akzeptiert Datum im UNIX-Timestamp-Format, als Zeichenkette oder als Objekt vom Typ `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Siehe auch [#localDate].
+
 
 escapeUrl .[filter]
 -------------------
-Entfernt eine Variable, die als Parameter in einer URL verwendet werden soll.
+Escapet eine Variable zur Verwendung als Parameter in einer URL.
 
 ```latte
 <a href="http://example.com/{$name|escapeUrl}">{$name}</a>
 ```
 
-Siehe auch [Abfrage |#query].
+Siehe auch [#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
-Teilt eine Zeichenkette durch den angegebenen Begrenzer und gibt ein Array von Zeichenketten zurück. Alias für `split`.
+explode(string $separator='') .[filter]
+---------------------------------------
+Teilt eine Zeichenkette anhand eines Trennzeichens in ein Array. Alias für `split`.
 
 ```latte
-{='one,two,three'|explode:','}    {* liefert ['one', 'two', 'three'] *}
+{='one,two,three'|explode:','}    {* gibt ['one', 'two', 'three'] zurück *}
 ```
 
 Wenn das Trennzeichen eine leere Zeichenkette ist (Standardwert), wird die Eingabe in einzelne Zeichen aufgeteilt:
 
 ```latte
-{='123'|explode}                  {* liefert ['1', '2', '3'] *}
+{='123'|explode}                  {* gibt ['1', '2', '3'] zurück *}
 ```
 
 Sie können auch den Alias `split` verwenden:
 
 ```latte
-{='1,2,3'|split:','}              {* liefert ['1', '2', '3'] *}
+{='1,2,3'|split:','}              {* gibt ['1', '2', '3'] zurück *}
 ```
 
-Siehe auch [implode |#implode].
+Siehe auch [#implode].
 
 
 first .[filter]
 ---------------
-Gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück:
+Gibt das erste Element eines Arrays oder das erste Zeichen einer Zeichenkette zurück:
 
 ```latte
-{=[1, 2, 3, 4]|first}    {* gibt 1 *}
-{='abcd'|first}          {* gibt 'a' *}
+{=[1, 2, 3, 4]|first}    {* gibt 1 aus *}
+{='abcd'|first}          {* gibt 'a' aus *}
 ```
 
-Siehe auch [last |#last], [random |#random].
+Siehe auch [#last], [#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Rundet eine Zahl auf eine bestimmte Genauigkeit ab.
 
 ```latte
-{=3.5|floor}        {* gibt 3      *}
-{=135.79|floor:1}   {* gibt 135.7  *}
-{=135.79|floor:3}   {* gibt 135.79 *}
+{=3.5|floor}        {* gibt 3      aus *}
+{=135.79|floor:1}   {* gibt 135.7  aus *}
+{=135.79|floor:3}   {* gibt 135.79 aus *}
 ```
 
-Siehe auch [ceil |#ceil], [round |#round].
+Siehe auch [#ceil], [#round].
 
 
 firstUpper .[filter]
 --------------------
-Konvertiert den ersten Buchstaben eines Wertes in Großbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
+Konvertiert den ersten Buchstaben in einen Großbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
 
 ```latte
-{='the latte'|firstUpper}  {* gibt 'The latte' *}
+{='the latte'|firstUpper}  {* gibt 'The latte' aus *}
 ```
 
-Siehe auch [capitalize |#capitalize], [lower |#lower], [upper |#upper].
+Siehe auch [#capitalize], [#lower], [#upper].
+
 
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Filter, der Daten nach verschiedenen Kriterien gruppiert.
 
-implode(string glue = '') .[filter]
------------------------------------
-Gibt eine Zeichenkette zurück, die die Verkettung der Zeichenketten im Array ist. Alias für `join`.
+In diesem Beispiel werden die Tabellenzeilen nach der Spalte `categoryId` gruppiert. Die Ausgabe ist ein Array von Arrays, wobei der Schlüssel der Wert in der Spalte `categoryId` ist. [Lesen Sie die detaillierte Anleitung |cookbook/grouping].
 
 ```latte
-{=[1, 2, 3]|implode}      {* gibt '123' *}
-{=[1, 2, 3]|implode:'|'}  {* gibt '1|2|3' *}
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
 ```
 
-Sie können auch einen Alias `join` verwenden:
+Siehe auch [#batch], die Funktion [group |functions#group] und das Tag [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
+Gibt eine Zeichenkette zurück, die eine Verkettung der Elemente einer Sequenz ist. Alias für `join`.
 
 ```latte
-{=[1, 2, 3]|join}         {* gibt '123' *}
+{=[1, 2, 3]|implode}      {* gibt '123' aus *}
+{=[1, 2, 3]|implode:'|'}  {* gibt '1|2|3' aus *}
 ```
 
+Sie können auch den Alias `join` verwenden:
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
-Rückt einen Text von links um eine bestimmte Anzahl von Tabulatoren oder anderen Zeichen ein, die wir im zweiten optionalen Argument angeben. Leerzeilen werden nicht eingerückt.
+```latte
+{=[1, 2, 3]|join}         {* gibt '123' aus *}
+```
+
+
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
+Rückt Text von links um eine bestimmte Anzahl von Tabulatoren oder anderen Zeichen ein, die im zweiten Argument angegeben werden können. Leere Zeilen werden nicht eingerückt.
 
 ```latte
 <div>
@@ -358,7 +382,7 @@ Rückt einen Text von links um eine bestimmte Anzahl von Tabulatoren oder andere
 </div>
 ```
 
-Druckt:
+Gibt aus:
 
 ```latte
 <div>
@@ -369,24 +393,24 @@ Druckt:
 
 last .[filter]
 --------------
-Gibt das letzte Element eines Arrays oder ein Zeichen einer Zeichenkette zurück:
+Gibt das letzte Element eines Arrays oder das letzte Zeichen einer Zeichenkette zurück:
 
 ```latte
-{=[1, 2, 3, 4]|last}    {* gibt 4 *}
-{='abcd'|last}          {* gibt 'd' *}
+{=[1, 2, 3, 4]|last}    {* gibt 4 aus *}
+{='abcd'|last}          {* gibt 'd' aus *}
 ```
 
-Siehe auch [first |#first], [random |#random].
+Siehe auch [#first], [#random].
 
 
 length .[filter]
 ----------------
 Gibt die Länge einer Zeichenkette oder eines Arrays zurück.
 
-- bei Strings wird die Länge in UTF-8 Zeichen zurückgegeben
-- für Arrays wird die Anzahl der Elemente zurückgegeben
-- bei Objekten, die die Schnittstelle Countable implementieren, wird der Rückgabewert der Funktion count() verwendet
-- für Objekte, die die Schnittstelle IteratorAggregate implementieren, wird der Rückgabewert von iterator_count() verwendet.
+- für Zeichenketten gibt es die Länge in UTF-8-Zeichen zurück
+- für Arrays gibt es die Anzahl der Elemente zurück
+- für Objekte, die das Countable-Interface implementieren, verwendet es den Rückgabewert der count()-Methode
+- für Objekte, die das IteratorAggregate-Interface implementieren, verwendet es den Rückgabewert der iterator_count()-Funktion
 
 
 ```latte
@@ -396,43 +420,105 @@ Gibt die Länge einer Zeichenkette oder eines Arrays zurück.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formatiert Datum und Uhrzeit gemäß den [Ländereinstellungen |develop#locale], was eine konsistente und lokalisierte Darstellung von Zeitangaben in verschiedenen Sprachen und Regionen gewährleistet. Der Filter akzeptiert ein Datum als UNIX-Timestamp, Zeichenkette oder Objekt vom Typ `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. April 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Wenn Sie den Filter ohne Parameter verwenden, wird das Datum auf der Ebene `long` ausgegeben, siehe unten.
+
+**a) Verwendung des Formats**
+
+Der Parameter `format` beschreibt, welche Zeitkomponenten angezeigt werden sollen. Es verwendet Buchstabencodes dafür, deren Wiederholungsanzahl die Breite der Ausgabe beeinflusst:
+
+| Jahr | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Monat | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `Aug` / `August`
+| Tag | `d` / `dd` / `E` / `EEEE` |  `1` / `01` / `So` / `Sonntag`
+| Stunde | `j` /  `H` / `h` | bevorzugt / 24-Stunden / 12-Stunden
+| Minute | `m` / `mm` | `5` / `05` <small>(2 Ziffern in Kombination mit Sekunden)</small>
+| Sekunde | `s` / `ss` | `8` / `08` <small>(2 Ziffern in Kombination mit Minuten)</small>
+
+Die Reihenfolge der Codes im Format spielt keine Rolle, da die Reihenfolge der Komponenten gemäß den Konventionen der Ländereinstellungen ausgegeben wird. Das Format ist also unabhängig davon. Zum Beispiel wird das Format `yyyyMMMMd` in der Umgebung `en_US` als `April 15, 2024` ausgegeben, während es in der Umgebung `de_DE` als `15. April 2024` ausgegeben wird:
+
+| locale:  | de-DE | en_US
+|---
+| `format: 'dMy'` | 10.8.2024 | 8/10/2024
+| `format: 'yM'` | 08/2024 | 8/2024
+| `format: 'yyyyMMMM'` | August 2024 | August 2024
+| `format: 'MMMM'` | August | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 PM | 5:54 PM
+
+
+**b) Verwendung vordefinierter Stile**
+
+Die Parameter `date` und `time` bestimmen, wie detailliert Datum und Uhrzeit ausgegeben werden sollen. Sie können aus mehreren Ebenen wählen: `full`, `long`, `medium`, `short`. Es ist möglich, nur das Datum, nur die Uhrzeit oder beides ausgeben zu lassen:
+
+| locale:  | de-DE | en_US
+|---
+| `date: short` | 23.01.78 | 1/23/78
+| `date: medium` | 23.01.1978 | Jan 23, 1978
+| `date: long` | 23. Januar 1978 | January 23, 1978
+| `date: full` | Montag, 23. Januar 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 MEZ | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.78, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23.01.1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23. Januar 1978 um 08:30 | January 23, 1978 at 8:30 AM
+
+Für das Datum können Sie außerdem das Präfix `relative-` verwenden (z.B. `relative-short`), das für Daten nahe der Gegenwart `gestern`, `heute` oder `morgen` anzeigt, andernfalls wird es auf die Standardweise ausgegeben.
+
+```latte
+{$date|localDate: date: relative-short}    {* gestern *}
+```
+
+Siehe auch [#date].
+
+
 lower .[filter]
 ---------------
-Konvertiert einen Wert in Kleinbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
+Konvertiert eine Zeichenkette in Kleinbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
 
 ```latte
-{='LATTE'|lower}   {* gibt 'latte' *}
+{='LATTE'|lower}   {* gibt 'latte' aus *}
 ```
 
-Siehe auch [capitalize |#capitalize], [firstUpper |#firstUpper], [upper |#upper].
+Siehe auch [#capitalize], [#firstUpper], [#upper].
 
 
 nocheck .[filter]
 -----------------
-Verhindert die automatische URL-Sanitization. Latte [prüft automatisch |safety-first#Link checking], ob die Variable eine Web-URL enthält (d.h. HTTP/HTTPS-Protokoll) und verhindert das Schreiben von Links, die ein Sicherheitsrisiko darstellen könnten.
+Verhindert die automatische Behandlung einer URL-Adresse. Latte [überprüft automatisch |safety-first#Link checking], ob die Variable eine Web-URL enthält (d.h. HTTP/HTTPS-Protokoll) und verhindert die Ausgabe von Links, die ein Sicherheitsrisiko darstellen können.
 
-Wenn der Link ein anderes Schema verwendet, z. B. `javascript:` oder `data:`, und Sie sich des Inhalts sicher sind, können Sie die Prüfung über `|nocheck` deaktivieren.
+Wenn der Link ein anderes Schema verwendet, z.B. `javascript:` oder `data:`, und Sie sich seines Inhalts sicher sind, können Sie die Überprüfung mit `|nocheck` deaktivieren.
 
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>geprüft</a>
+<a href={$link|nocheck}>ungeprüft</a>
 ```
 
-Drucke:
+Gibt aus:
 
 ```latte
-<a href="">checked</a>
-<a href="javascript:window.close()">unchecked</a>
+<a href="">geprüft</a>
+<a href="javascript:window.close()">ungeprüft</a>
 ```
 
-Siehe auch [checkUrl |#checkUrl].
+Siehe auch [#checkUrl].
 
 
 noescape .[filter]
 ------------------
-Deaktiviert das automatische Escaping.
+Deaktiviert automatisches Escaping.
 
 ```latte
 {var $trustedHtmlString = '<b>hello</b>'}
@@ -440,7 +526,7 @@ Escaped: {$trustedHtmlString}
 Unescaped: {$trustedHtmlString|noescape}
 ```
 
-Druckt:
+Gibt aus:
 
 ```latte
 Escaped: &lt;b&gt;hello&lt;/b&gt;
@@ -448,152 +534,200 @@ Unescaped: <b>hello</b>
 ```
 
 .[warning]
-Die missbräuchliche Verwendung des `noescape` Filters kann zu einer XSS-Schwachstelle führen! Verwenden Sie ihn nur, wenn Sie **absolut sicher** sind, was Sie tun und dass die Zeichenfolge, die Sie drucken, aus einer vertrauenswürdigen Quelle stammt.
+Falsche Verwendung des `noescape`-Filters kann zu XSS-Schwachstellen führen! Verwenden Sie ihn niemals, wenn Sie nicht **absolut sicher** sind, was Sie tun, und dass die ausgegebene Zeichenkette aus einer vertrauenswürdigen Quelle stammt.
+
+
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formatiert eine Zahl auf eine bestimmte Anzahl von Dezimalstellen. Wenn [Ländereinstellungen |develop#locale] gesetzt sind, werden die entsprechenden Dezimal- und Tausendertrennzeichen verwendet.
 
+```latte
+{1234.20|number}              1,234
+{1234.20|number:1}            1,234.2
+{1234.20|number:2}            1,234.20
+{1234.20|number:2, ',', ' '}  1 234,20
+```
+
+
+number(string $format) .[filter]
+--------------------------------
+Der Parameter `format` ermöglicht es Ihnen, das Aussehen von Zahlen genau nach Ihren Bedürfnissen zu definieren. Dafür müssen [Ländereinstellungen |develop#locale] gesetzt sein. Das Format besteht aus mehreren speziellen Zeichen, deren vollständige Beschreibung Sie in der Dokumentation "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns finden:
+
+- `0` obligatorische Ziffer, wird immer angezeigt, auch wenn es eine Null ist
+- `#` optionale Ziffer, wird nur angezeigt, wenn an dieser Stelle tatsächlich eine Zahl steht
+- `@` signifikante Ziffer, hilft, eine Zahl mit einer bestimmten Anzahl gültiger Ziffern anzuzeigen
+- `.` kennzeichnet, wo das Dezimalkomma (oder -punkt, je nach Land) sein soll
+- `,` dient zur Trennung von Zifferngruppen, meist Tausender
+- `%` multipliziert die Zahl mit 100 und fügt das Prozentzeichen hinzu
+
+Schauen wir uns einige Beispiele an. Im ersten Beispiel sind zwei Dezimalstellen obligatorisch, im zweiten optional. Das dritte Beispiel zeigt das Auffüllen mit Nullen links und rechts, das vierte zeigt nur existierende Ziffern:
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formatiert eine Zahl auf eine bestimmte Anzahl von Dezimalstellen. Sie können auch ein Zeichen für den Dezimalpunkt und das Tausendertrennzeichen angeben.
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Signifikante Ziffern bestimmen, wie viele Ziffern unabhängig vom Dezimalpunkt angezeigt werden sollen, wobei gerundet wird:
 
 ```latte
-{1234.20 |number}              1,234
-{1234.20 |number:1}            1,234.2
-{1234.20 |number:2}            1,234.20
-{1234.20 |number:2, ',', ' '}  1 234,20
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
 ```
 
+Ein einfacher Weg, eine Zahl als Prozentsatz anzuzeigen. Die Zahl wird mit 100 multipliziert und das `%`-Zeichen wird hinzugefügt:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
 
-padLeft(int length, string pad = ' ') .[filter]
+Wir können unterschiedliche Formate für positive und negative Zahlen definieren, getrennt durch ein `;`-Zeichen. Auf diese Weise können wir zum Beispiel festlegen, dass positive Zahlen mit einem `+`-Zeichen angezeigt werden sollen:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Beachten Sie, dass das tatsächliche Aussehen der Zahlen je nach den Ländereinstellungen variieren kann. In einigen Ländern wird beispielsweise ein Komma statt eines Punkts als Dezimaltrennzeichen verwendet. Dieser Filter berücksichtigt dies automatisch, und Sie müssen sich um nichts kümmern.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
-Füllt eine Zeichenkette bis zu einer bestimmten Länge mit einer anderen Zeichenkette von links auf.
+Füllt eine Zeichenkette auf eine bestimmte Länge mit einer anderen Zeichenkette von links auf.
 
 ```latte
-{='hello'|padLeft: 10, '123'}  {* gibt '12312hello' *}
+{='hello'|padLeft: 10, '123'}  {* gibt '12312hello' aus *}
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
-Füllt eine Zeichenfolge auf eine bestimmte Länge mit einer anderen Zeichenfolge von rechts.
+Füllt eine Zeichenkette auf eine bestimmte Länge mit einer anderen Zeichenkette von rechts auf.
 
 ```latte
-{='hello'|padRight: 10, '123'}  {* gibt 'hello12312' *}
+{='hello'|padRight: 10, '123'}  {* gibt 'hello12312' aus *}
 ```
 
 
-query  .[filter]
-----------------
-Erzeugt dynamisch eine Abfragezeichenfolge in der URL:
+query .[filter]
+---------------
+Generiert dynamisch einen Query-String in einer URL:
 
 ```latte
-<a href="http://example.com/?{[name: 'John Doe', age: 43]|query}">click</a>
-<a href="http://example.com/?search={$search|query}">search</a>
+<a href="http://example.com/?{[name: 'John Doe', age: 43]|query}">klicken</a>
+<a href="http://example.com/?search={$search|query}">suchen</a>
 ```
 
-Druckt:
+Gibt aus:
 
 ```latte
-<a href="http://example.com/?name=John+Doe&amp;age=43">click</a>
-<a href="http://example.com/?search=Foo+Bar">search</a>
+<a href="http://example.com/?name=John+Doe&amp;age=43">klicken</a>
+<a href="http://example.com/?search=Foo+Bar">suchen</a>
 ```
 
-Tasten mit einem Wert von `null` werden ausgelassen.
+Schlüssel mit dem Wert `null` werden weggelassen.
 
-Siehe auch [escapeUrl |#escapeUrl].
+Siehe auch [#escapeUrl].
 
 
 random .[filter]
 ----------------
-Gibt ein zufälliges Element eines Arrays oder ein Zeichen einer Zeichenkette zurück:
+Gibt ein zufälliges Element eines Arrays oder ein zufälliges Zeichen einer Zeichenkette zurück:
 
 ```latte
-{=[1, 2, 3, 4]|random}    {* example output: 3 *}
-{='abcd'|random}          {* example output: 'b' *}
+{=[1, 2, 3, 4]|random}    {* gibt z.B.: 3 aus *}
+{='abcd'|random}          {* gibt z.B.: 'b' aus *}
 ```
 
-Siehe auch [first |#first], [last |#last].
+Siehe auch [#first], [#last].
 
 
-repeat(int count) .[filter]
----------------------------
-Wiederholt die Zeichenkette x-mal.
+repeat(int $count) .[filter]
+----------------------------
+Wiederholt eine Zeichenkette x-mal.
 
 ```latte
-{='hello'|repeat: 3}  {* gibt 'hellohellohello' *}
+{='hello'|repeat: 3}  {* gibt 'hellohellohello' aus *}
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
-Ersetzt alle Vorkommen der Suchzeichenfolge durch die Ersatzzeichenfolge.
+Ersetzt alle Vorkommen der Suchzeichenkette durch die Ersatzzeichenkette.
 
 ```latte
-{='hello world'|replace: 'world', 'friend'}  {* gibt 'hello friend' *}
+{='hello world'|replace: 'world', 'friend'}  {* gibt 'hello friend' aus *}
 ```
 
-Es können mehrere Ersetzungen auf einmal vorgenommen werden:
+Es können auch mehrere Ersetzungen auf einmal durchgeführt werden:
 
 ```latte
-{='hello world'|replace: [h => l, l => h]}  {* gibt 'lehho worhd' *}
+{='hello world'|replace: [h => l, l => h]}  {* gibt 'lehho worhd' aus *}
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
-Ersetzt alle Vorkommen entsprechend dem regulären Ausdruck.
+Führt eine Suche und Ersetzung mit regulären Ausdrücken durch.
 
 ```latte
-{='hello world'|replaceRE: '/l.*/', 'l'}  {* gibt 'hel' *}
+{='hello world'|replaceRE: '/l.*/', 'l'}  {* gibt 'hel' aus *}
 ```
 
 
 reverse .[filter]
 -----------------
-Kehrt eine gegebene Zeichenkette oder ein gegebenes Array um.
+Kehrt die gegebene Zeichenkette oder das Array um.
 
 ```latte
 {var $s = 'Nette'}
-{$s|reverse}    {* gibt 'etteN' *}
+{$s|reverse}    {* gibt 'etteN' aus *}
 {var $a = ['N', 'e', 't', 't', 'e']}
-{$a|reverse}    {* liefert ['e', 't', 't', 'e', 'N'] *}
+{$a|reverse}    {* gibt ['e', 't', 't', 'e', 'N'] zurück *}
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
-Rundet eine Zahl auf eine bestimmte Genauigkeit.
+round(int $precision=0) .[filter]
+---------------------------------
+Rundet eine Zahl auf die angegebene Genauigkeit.
 
 ```latte
-{=3.4|round}        {* gibt 3      *}
-{=3.5|round}        {* gibt 4      *}
-{=135.79|round:1}   {* gibt 135.8  *}
-{=135.79|round:3}   {* gibt 135.79 *}
+{=3.4|round}        {* gibt 3      aus *}
+{=3.5|round}        {* gibt 4      aus *}
+{=135.79|round:1}   {* gibt 135.8  aus *}
+{=135.79|round:3}   {* gibt 135.79 aus *}
 ```
 
-Siehe auch [ceil |#ceil], [floor |#floor].
+Siehe auch [#ceil], [#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
-Extrahiert einen Ausschnitt aus einem Array oder einer Zeichenkette.
+Extrahiert einen Teil eines Arrays oder einer Zeichenkette.
 
 ```latte
-{='hello'|slice: 1, 2}           {* gibt 'el' *}
-{=['a', 'b', 'c']|slice: 1, 2}   {* gibt ['b', 'c'] *}
+{='hello'|slice: 1, 2}           {* gibt 'el' aus *}
+{=['a', 'b', 'c']|slice: 1, 2}   {* gibt ['b', 'c'] aus *}
 ```
 
-Der Slice-Filter funktioniert wie die PHP-Funktion `array_slice` für Arrays und `mb_substr` für Strings mit einem Fallback auf `iconv_substr` im UTF-8-Modus.
+Der Filter funktioniert wie die PHP-Funktion `array_slice` für Arrays oder `mb_substr` für Zeichenketten mit Fallback auf die Funktion `iconv_substr` im UTF-8-Modus.
 
-Wenn start nicht negativ ist, beginnt die Sequenz an diesem Anfang in der Variablen. Wenn start negativ ist, beginnt die Sequenz so weit vom Ende der Variablen entfernt.
+Wenn start positiv ist, beginnt die Sequenz um diese Anzahl vom Anfang des Arrays/der Zeichenkette verschoben. Wenn es negativ ist, beginnt die Sequenz um diese Anzahl vom Ende verschoben.
 
-Wenn length angegeben wird und positiv ist, wird die Sequenz bis zu dieser Anzahl von Elementen enthalten. Wenn die Variable kürzer als die Länge ist, werden nur die verfügbaren Elemente der Variablen angezeigt. Wenn length angegeben wird und negativ ist, endet die Sequenz so viele Elemente vor dem Ende der Variablen. Wird sie weggelassen, enthält die Sequenz alle Elemente vom Offset bis zum Ende der Variablen.
+Wenn der Parameter length angegeben und positiv ist, enthält die Sequenz so viele Elemente. Wenn ein negativer length-Parameter an diese Funktion übergeben wird, enthält die Sequenz alle Elemente des ursprünglichen Arrays, beginnend an der Position start und endend an der Position, die um length Elemente vom Ende des Arrays entfernt ist. Wenn Sie diesen Parameter weglassen, enthält die Sequenz alle Elemente des ursprünglichen Arrays, beginnend an der Position start.
 
-Filter ordnet die Schlüssel des Integer-Arrays standardmäßig neu an und setzt sie zurück. Dieses Verhalten kann geändert werden, indem preserveKeys auf true gesetzt wird. String-Schlüssel werden immer beibehalten, unabhängig von diesem Parameter.
+Standardmäßig ändert der Filter die Reihenfolge und setzt die ganzzahligen Schlüssel des Arrays zurück. Dieses Verhalten kann geändert werden, indem preserveKeys auf true gesetzt wird. String-Schlüssel werden immer beibehalten, unabhängig von diesem Parameter.
 
 
-sort  .[filter]
----------------
-Filter, der ein Array sortiert und die Indexzuordnung beibehält.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Der Filter sortiert die Elemente eines Arrays oder Iterators und behält ihre assoziativen Schlüssel bei. Bei gesetzten [Ländereinstellungen |develop#locale] folgt die Sortierung deren Regeln, wenn keine eigene Vergleichsfunktion angegeben ist.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -601,7 +735,7 @@ Filter, der ein Array sortiert und die Indexzuordnung beibehält.
 {/foreach}
 ```
 
-Array in umgekehrter Reihenfolge sortiert.
+Sortiertes Array in umgekehrter Reihenfolge:
 
 ```latte
 {foreach ($names|sort|reverse) as $name}
@@ -609,16 +743,42 @@ Array in umgekehrter Reihenfolge sortiert.
 {/foreach}
 ```
 
-Sie können Ihre eigene Vergleichsfunktion als Parameter übergeben:
+Sie können eine eigene Vergleichsfunktion für die Sortierung angeben (das Beispiel zeigt, wie die Sortierung von größter zu kleinster umgekehrt wird):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Der Filter `|sort` ermöglicht auch die Sortierung von Elementen nach Schlüsseln:
 
-spaceless  .[filter]
---------------------
-Entfernt unnötige Leerzeichen aus der Ausgabe. Sie können auch den Alias `strip` verwenden.
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Wenn Sie eine Tabelle nach einer bestimmten Spalte sortieren müssen, können Sie den Parameter `by` verwenden. Der Wert `'name'` im Beispiel gibt an, dass nach `$item->name` oder `$item['name']` sortiert wird, je nachdem, ob `$item` ein Array oder ein Objekt ist:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Sie können auch eine Callback-Funktion definieren, die den Wert bestimmt, nach dem sortiert werden soll:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Der Parameter `byKey` kann auf die gleiche Weise verwendet werden.
+
+
+spaceless .[filter]
+-------------------
+Entfernt überflüssige Leerzeichen aus der Ausgabe. Sie können auch den Alias `strip` verwenden.
 
 ```latte
 {block |spaceless}
@@ -628,7 +788,7 @@ Entfernt unnötige Leerzeichen aus der Ausgabe. Sie können auch den Alias `stri
 {/block}
 ```
 
-Druckt:
+Gibt aus:
 
 ```latte
 <ul> <li>Hello</li> </ul>
@@ -637,77 +797,77 @@ Druckt:
 
 stripHtml .[filter]
 -------------------
-Konvertiert HTML in einfachen Text. Das heißt, es werden HTML-Tags entfernt und HTML-Elemente in Text umgewandelt.
+Konvertiert HTML in reinen Text. Das heißt, es entfernt HTML-Tags und konvertiert HTML-Entities in Text.
 
 ```latte
-{='<p>one &lt; two</p>'|stripHtml}  {* gibt 'one < two' *}
+{='<p>one &lt; two</p>'|stripHtml}  {* gibt 'one < two' aus *}
 ```
 
-Der resultierende reine Text kann natürlich Zeichen enthalten, die HTML-Tags darstellen, zum Beispiel wird `'&lt;p&gt;'|stripHtml` in `<p>`. Geben Sie den resultierenden Text niemals mit `|noescape` aus, da dies zu einer Sicherheitslücke führen kann.
+Der resultierende reine Text kann natürlich Zeichen enthalten, die HTML-Tags darstellen, zum Beispiel wird `'&lt;p&gt;'|stripHtml` zu `<p>` konvertiert. Geben Sie den so erzeugten Text auf keinen Fall mit `|noescape` aus, da dies zu einer Sicherheitslücke führen kann.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
-Extrahiert einen Ausschnitt aus einer Zeichenkette. Dieser Filter wurde durch einen [Slice-Filter |#slice] ersetzt.
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
+Extrahiert einen Teil einer Zeichenkette. Dieser Filter wurde durch den Filter [#slice] ersetzt.
 
 ```latte
 {$string|substr: 1, 2}
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
-Er übersetzt Ausdrücke in andere Sprachen. Um den Filter verfügbar zu machen, müssen Sie den [Übersetzer ein richten|develop#TranslatorExtension]. Sie können auch die [Tags für die Übersetzung |tags#Translation] verwenden.
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
+Übersetzt Ausdrücke in andere Sprachen. Damit der Filter verfügbar ist, muss ein [Übersetzer eingerichtet |develop#TranslatorExtension] sein. Sie können auch [Tags für Übersetzungen |tags#Translation] verwenden.
 
 ```latte
-<a href="basket">{='Baskter'|translate}</a>
+<a href="basket">{='Cart'|translate}</a>
 <span>{$item|translate}</span>
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
-Entfernen Sie führende und nachgestellte Zeichen, standardmäßig Leerzeichen.
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
+Entfernt Leerzeichen (oder andere Zeichen) vom Anfang und Ende einer Zeichenkette.
 
 ```latte
-{='  I like Latte.  '|trim}    {* gibt 'I like Latte.' *}
-{='  I like Latte.'|trim: '.'} {* gibt '  I like Latte' *}
+{='  I like Latte.  '|trim}    {* gibt 'I like Latte.' aus *}
+{='  I like Latte.'|trim: '.'}  {* gibt '  I like Latte' aus *}
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
-Kürzt eine Zeichenkette auf die maximal angegebene Länge, versucht aber, ganze Wörter zu erhalten. Wenn die Zeichenkette abgeschnitten ist, wird am Ende ein Auslassungszeichen hinzugefügt (dies kann durch den zweiten Parameter geändert werden).
+Kürzt eine Zeichenkette auf die angegebene maximale Länge, wobei versucht wird, ganze Wörter zu erhalten. Wenn die Zeichenkette gekürzt wird, wird am Ende ein Auslassungszeichen hinzugefügt (kann mit dem zweiten Parameter geändert werden).
 
 ```latte
 {var $title = 'Hello, how are you?'}
-{$title|truncate:5}  {* Hell…                *}
-{$title|truncate:17} {* Hello, how are…      *}
-{$title|truncate:30} {* Hello, how are you?  *}
+{$title|truncate:5}   {* Hell… *}
+{$title|truncate:17}  {* Hello, how are… *}
+{$title|truncate:30}  {* Hello, how are you? *}
 ```
 
 
 upper .[filter]
 ---------------
-Konvertiert einen Wert in Großbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
+Konvertiert eine Zeichenkette in Großbuchstaben. Erfordert die PHP-Erweiterung `mbstring`.
 
 ```latte
-{='latte'|upper}  {* gibt 'LATTE' *}
+{='latte'|upper}  {* gibt 'LATTE' aus *}
 ```
 
-Siehe auch [capitalize |#capitalize], [firstUpper |#firstUpper], [lower |#lower].
+Siehe auch [#capitalize], [#firstUpper], [#lower].
 
 
 webalize .[filter]
 ------------------
-Konvertiert nach ASCII.
+Konvertiert eine UTF-8-Zeichenkette in die in URLs verwendete Form.
 
-Konvertiert Leerzeichen in Bindestriche. Entfernt Zeichen, die keine alphanumerischen Zeichen, Unterstriche oder Bindestriche sind. Konvertiert in Kleinbuchstaben. Entfernt auch führende und nachfolgende Leerzeichen.
+Es wird in ASCII konvertiert. Konvertiert Leerzeichen in Bindestriche. Entfernt Zeichen, die nicht alphanumerisch, Unterstriche oder Bindestriche sind. Konvertiert in Kleinbuchstaben. Entfernt auch führende und abschließende Leerzeichen.
 
 ```latte
-{var $s = 'Our 10. product'}
-{$s|webalize}    {* gibt 'our-10-product' *}
+{var $s = 'Unser 10. Produkt'}
+{$s|webalize}   {* gibt 'unser-10-produkt' aus *}
 ```
 
 .[caution]
-Erfordert das Paket [nette/utils |utils:].
+Erfordert die Bibliothek [nette/utils |utils:].
diff --git a/latte/de/functions.texy b/latte/de/functions.texy
index a60ad676db..721695b45d 100644
--- a/latte/de/functions.texy
+++ b/latte/de/functions.texy
@@ -9,6 +9,8 @@ Zusätzlich zu den üblichen PHP-Funktionen können Sie diese auch in Vorlagen v
 | `divisibleBy`| [prüft ob eine Variable durch eine Zahl teilbar ist |#divisibleBy]
 | `even` | [prüft ob die angegebene Zahl gerade ist |#even]
 | `first` | [gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück |#first]
+| `group` | [gruppiert Daten nach verschiedenen Kriterien |#group]
+| `hasBlock` | [erkennt das Vorhandensein eines Blocks |#hasBlock]
 | `last` | [gibt das letzte Element eines Arrays oder ein Zeichen einer Zeichenkette zurück |#last]
 | `odd` | [prüft ob die angegebene Zahl ungerade ist |#odd]
 | `slice` | [extrahiert einen Ausschnitt aus einem Array oder einer Zeichenkette|#slice]
@@ -73,8 +75,8 @@ Prüft, ob die angegebene Zahl gerade ist.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück:
 
 ```latte
@@ -85,6 +87,36 @@ Gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück:
 Siehe auch [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Diese Funktion gruppiert Daten nach verschiedenen Kriterien.
+
+In diesem Beispiel werden die Zeilen in der Tabelle nach der Spalte `categoryId` gruppiert. Die Ausgabe ist ein Array von Feldern, wobei der Schlüssel der Wert in der Spalte `categoryId` ist. Lesen Sie die [ausführliche Anleitung |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Siehe auch [Filtergruppe |filters#group].
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Prüft, ob der Block mit dem angegebenen Namen existiert:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Siehe auch [Blockexistenzprüfung |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Gibt das letzte Element eines Arrays oder ein Zeichen einer Zeichenkette zurück:
@@ -106,8 +138,8 @@ Prüft, ob die angegebene Zahl ungerade ist.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Extrahiert einen Ausschnitt aus einem Array oder einer Zeichenkette.
 
 ```latte
diff --git a/latte/de/recipes.texy b/latte/de/recipes.texy
index 174f5a0254..625f7dc132 100644
--- a/latte/de/recipes.texy
+++ b/latte/de/recipes.texy
@@ -9,7 +9,7 @@ Schreiben Sie Vorlagen in einem Editor oder einer IDE, die Latte unterstützt. E
 
 - NetBeans IDE hat integrierte Unterstützung
 - PhpStorm: Installieren Sie das [Latte-Plugin |https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace`
-- VS Code: Suchen Sie auf markerplace nach dem "Nette Latte + Neon" Plugin
+- VS Code: suche markerplace für [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] oder [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
 - Sublime Text 3: in der Paketverwaltung das Paket `Nette` suchen und installieren und Latte in auswählen `View > Syntax`
 - in alten Editoren Smarty-Hervorhebung für .latte-Dateien verwenden
 
diff --git a/latte/de/safety-first.texy b/latte/de/safety-first.texy
index ef699fd12a..6529d9848c 100644
--- a/latte/de/safety-first.texy
+++ b/latte/de/safety-first.texy
@@ -351,7 +351,7 @@ Latte prüft automatisch, ob die in den Attributen `src` oder `href` verwendete
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Schreibt:
diff --git a/latte/de/syntax.texy b/latte/de/syntax.texy
index d86f0c4f5e..b6f6482c5b 100644
--- a/latte/de/syntax.texy
+++ b/latte/de/syntax.texy
@@ -98,7 +98,7 @@ Druckt:
 Oder durch die Verwendung des Präfixes `tag-` wird die Funktionalität nur auf die HTML-Tags angewendet:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Je nach dem Wert der Variable `$url` wird dies gedruckt:
@@ -155,6 +155,20 @@ Oder direkt beim Wert (in Kombination mit [`{=expr}` | https://latte.nette.org/d
 ```
 
 
+Dynamische HTML-Tags .[#toc-dynamic-html-tags]
+==============================================
+
+Latte unterstützt dynamische HTML-Tags, die nützlich sind, wenn Sie Flexibilität bei den Tag-Namen benötigen:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Der obige Code kann zum Beispiel Folgendes erzeugen `<h1>Heading</h1>` oder `<h2>Heading</h2>` erzeugen, je nach dem Wert der Variablen `$level`. Dynamische HTML-Tags in Latte müssen immer gepaart sein. Ihre Alternative ist der [n:tag |tags#n:tag].
+
+Da Latte ein sicheres Schablonensystem ist, prüft es, ob der resultierende Tag-Name gültig ist und keine unerwünschten oder bösartigen Werte enthält. Es stellt auch sicher, dass der Name des End-Tags immer mit dem Namen des Anfangs-Tags übereinstimmt.
+
+
 Kommentare .[#toc-comments]
 ===========================
 
diff --git a/latte/de/tags.texy b/latte/de/tags.texy
index e067725f42..0fbefed3f3 100644
--- a/latte/de/tags.texy
+++ b/latte/de/tags.texy
@@ -2,169 +2,167 @@ Latte Tags
 **********
 
 .[perex]
-Zusammenfassung und Beschreibung aller in Latte integrierten Tags.
+Eine Übersicht und Beschreibung aller Latte-Template-System-Tags, die standardmäßig zur Verfügung stehen.
 
 .[table-latte-tags language-latte]
-|## Drucken
-| `{$var}`, `{...}` oder `{=...}` | [druckt eine Variable oder einen Ausdruck mit Escapezeichen |#printing]
-| `{$var\|filter}` | [druckt mit Filtern |#filters]
-| `{l}` oder `{r}` | druckt `{` or `}` Zeichen
+|## Ausgabe
+| `{$var}`, `{...}` oder `{=...}`  | [gibt eine escaped Variable oder einen Ausdruck aus|#Ausgabe]
+| `{$var\|filter}`                 | [gibt mit Verwendung von Filtern aus|#Filter]
+| `{l}` oder `{r}`                 | gibt das Zeichen `{` oder `}` aus
 
 .[table-latte-tags language-latte]
 |## Bedingungen
-| `{if}`... `{elseif}`... `{else}`... `{/if}` | [Bedingung if |#if-elseif-else]
-| `{ifset}`... `{elseifset}`... `{/ifset}` | [Bedingung ifset |#ifset-elseifset]
-| `{ifchanged}`... `{/ifchanged}` | [Test, ob eine Änderung stattgefunden hat |#ifchanged]
-| `{switch}` `{case}` `{default}` `{/switch}` | [Bedingung switch |#switch-case-default]
+| `{if}` … `{elseif}` … `{else}` … `{/if}`    | [if-Bedingung|#if-elseif-else]
+| `{ifset}` … `{elseifset}` … `{/ifset}`      | [ifset-Bedingung|#ifset-elseifset]
+| `{ifchanged}` … `{/ifchanged}`              | [Test, ob eine Änderung aufgetreten ist|#ifchanged]
+| `{switch}` `{case}` `{default}` `{/switch}` | [switch-Bedingung|#switch-case-default]
+| `n:else`                                    | [alternativer Inhalt für Bedingungen|#n:else]
 
 .[table-latte-tags language-latte]
 |## Schleifen
-| `{foreach}`... `{/foreach}` | [foreach |#foreach]
-| `{for}`... `{/for}` | [for |#for]
-| `{while}`... `{/while}` | [while |#while]
-| `{continueIf $cond}` | [weiter zur nächsten Iteration |#continueif-skipif-breakif]
-| `{skipIf $cond}` | [überspringt die aktuelle Schleifeniteration |#continueif-skipif-breakif]
-| `{breakIf $cond}` | [bricht Schleife ab |#continueif-skipif-breakif]
-| `{exitIf $cond}` | [vorzeitiges Beenden |#exitif]
-| `{first}`... `{/first}` | [ist dies die erste Iteration? |#first-last-sep]
-| `{last}`... `{/last}` | [ist es die letzte Iteration? |#first-last-sep]
-| `{sep}`... `{/sep}` | [wird die nächste Iteration folgen? |#first-last-sep]
-| `{iterateWhile}`... `{/iterateWhile}` | [strukturiert foreach |#iterateWhile]
-| `$iterator` | [Spezielle Variable innerhalb der foreach-Schleife |#$iterator]
+| `{foreach}` … `{/foreach}`     | [#foreach]
+| `{for}` … `{/for}`             | [#for]
+| `{while}` … `{/while}`         | [#while]
+| `{continueIf $cond}`           | [mit der nächsten Iteration fortfahren|#continueif-skipif-breakif]
+| `{skipIf $cond}`               | [Iteration überspringen|#continueif-skipif-breakif]
+| `{breakIf $cond}`              | [Schleife abbrechen|#continueif-skipif-breakif]
+| `{exitIf $cond}`               | [vorzeitige Beendigung|#exitif]
+| `{first}` … `{/first}`         | [ist es der erste Durchlauf?|#first-last-sep]
+| `{last}` … `{/last}`           | [ist es der letzte Durchlauf?|#first-last-sep]
+| `{sep}` … `{/sep}`             | [wird noch ein Durchlauf folgen?|#first-last-sep]
+| `{iterateWhile}` … `{/iterateWhile}` | [strukturiertes foreach|#iterateWhile]
+| `$iterator`                    | [spezielle Variable innerhalb von foreach|#$iterator]
 
 .[table-latte-tags language-latte]
-|## Einbindung anderer Vorlagen
-| `{include 'file.latte'}` | [schließt eine Vorlage aus einer anderen Datei ein |#include]
-| `{sandbox 'file.latte'}` | [Einfügen einer Vorlage im Sandbox-Modus |#sandbox]
+|## Einbindung weiterer Templates
+| `{include 'file.latte'}`       | [lädt ein Template aus einer anderen Datei|#include]
+| `{sandbox 'file.latte'}`       | [lädt ein Template im Sandbox-Modus|#sandbox]
 
 .[table-latte-tags language-latte]
-|## Blöcke, Layouts, Vererbung von Vorlagen
-| `{block}` | [anonymer Block |#block]
-| `{block blockname}` | [Blockdefinition |template-inheritance#blocks]
-| `{define blockname}` | [Blockdefinition für zukünftige Verwendung |template-inheritance#definitions]
-| `{include blockname}` | [druckt Block |template-inheritance#printing-blocks]
-| `{include blockname from 'file.latte'}` | [druckt einen Block aus einer Datei |template-inheritance#printing-blocks]
-| `{import 'file.latte'}` | [lädt Blöcke aus einer anderen Vorlage |template-inheritance#horizontal-reuse]
-| `{layout 'file.latte'}` / `{extends}` | [gibt eine Layout-Datei an |template-inheritance#layout-inheritance]
-| `{embed}`... `{/embed}` | [lädt die Vorlage oder den Block und ermöglicht das Überschreiben der Blöcke |template-inheritance#unit-inheritance]
-| `{ifset blockname}`... `{/ifset}` | [Bedingung, wenn Block definiert ist |template-inheritance#checking-block-existence]
+|## Blöcke, Layouts, Template-Vererbung
+| `{block}`                      | [anonymer Block|#block]
+| `{block blockname}`            | [definiert einen Block|template-inheritance#blocks]
+| `{define blockname}`           | [definiert einen Block zur späteren Verwendung|template-inheritance#definitions]
+| `{include blockname}`          | [Darstellung eines Blocks|template-inheritance#printing-blocks]
+| `{include blockname from 'file.latte'}` | [stellt einen Block aus einer Datei dar|template-inheritance#printing-blocks]
+| `{import 'file.latte'}`        | [lädt Blöcke aus einem Template|template-inheritance#horizontal-reuse]
+| `{layout 'file.latte'}` / `{extends}` | [bestimmt die Layout-Datei|template-inheritance#layout-inheritance]
+| `{embed}` … `{/embed}`         | [lädt ein Template oder einen Block und ermöglicht das Überschreiben von Blöcken|template-inheritance#unit-inheritance]
+| `{ifset blockname}` … `{/ifset}`   | [Bedingung, ob ein Block existiert|template-inheritance#checking-block-existence]
 
 .[table-latte-tags language-latte]
 |## Ausnahmebehandlung
-| `{try}`... `{else}`... `{/try}` | [Abfangen von Ausnahmen |#try]
-| `{rollback}` | [verwirft try-Block |#rollback]
+| `{try}` … `{else}` … `{/try}`  | [Abfangen von Ausnahmen|#try]
+| `{rollback}`                   | [Verwerfen eines try-Blocks|#rollback]
 
 .[table-latte-tags language-latte]
 |## Variablen
-| `{var $foo = value}` | [Erstellung von Variablen |#var-default]
-| `{default $foo = value}` | [Standardwert, wenn Variable nicht deklariert ist |#var-default]
-| `{parameters}` | [deklariert Variablen, gibt einen Standardwert ein |#parameters]
-| `{capture}`... `{/capture}` | [erfasst einen Abschnitt in einer Variablen |#capture]
+| `{var $foo = value}`           | [erstellt eine Variable|#var-default]
+| `{default $foo = value}`       | [erstellt eine Variable, wenn sie nicht existiert|#var-default]
+| `{parameters}`                 | [deklariert Variablen, Typen und Standardwerte|#parameters]
+| `{capture}` … `{/capture}`     | [erfasst einen Block in eine Variable|#capture]
 
 .[table-latte-tags language-latte]
 |## Typen
-| `{varType}` | [deklariert den Typ einer Variablen |type-system#varType]
-| `{varPrint}` | [schlägt Variablentypen vor |type-system#varPrint]
-| `{templateType}` | [deklariert Variablentypen mittels Klasse |type-system#templateType]
-| `{templatePrint}` | [erzeugt Klasse mit Eigenschaften |type-system#templatePrint]
+| `{varType}`                    | [deklariert den Typ einer Variable|type-system#varType]
+| `{varPrint}`                   | [schlägt Typen für Variablen vor|type-system#varPrint]
+| `{templateType}`               | [deklariert Variablentypen basierend auf einer Klasse|type-system#templateType]
+| `{templatePrint}`              | [schlägt eine Klasse mit Variablentypen vor|type-system#templatePrint]
 
 .[table-latte-tags language-latte]
-|## Übersetzung
-| `{_string}` | [druckt übersetzt |#Translation]
-| `{translate}`... `{/translate}` | [übersetzt den Inhalt |#Translation]
+|## Übersetzungen
+| `{_...}`                       | [gibt eine Übersetzung aus|#übersetzungen]
+| `{translate}` … `{/translate}` | [übersetzt den Inhalt|#übersetzungen]
 
 .[table-latte-tags language-latte]
-|## Andere
-| `{contentType}` | [schaltet den Escaping-Modus um und sendet HTTP-Header |#contenttype]
-| `{debugbreak}` | [setzt einen Haltepunkt im Code |#debugbreak]
-| `{do}` | [wertet einen Ausdruck aus, ohne ihn zu drucken |#do]
-| `{dump}` | [gibt Variablen in die Tracy Bar aus |#dump]
-| `{php}` | [führt beliebigen PHP-Code aus |#php]
-| `{spaceless}`... `{/spaceless}` | [entfernt unnötige Leerzeichen |#spaceless]
-| `{syntax}` | [schaltet die Syntax während der Laufzeit um |#syntax]
-| `{trace}` | [zeigt Stack-Trace |#trace]
+|## Sonstiges
+| `{contentType}`                | [schaltet das Escaping um und sendet einen HTTP-Header|#contenttype]
+| `{debugbreak}`                 | [platziert einen Breakpoint im Code|#debugbreak]
+| `{do}`                         | [führt Code aus, gibt aber nichts aus|#do]
+| `{dump}`                       | [dumpt Variablen in die Tracy Bar|#dump]
+| `{php}`                        | [führt beliebigen PHP-Code aus|#php]
+| `{spaceless}` … `{/spaceless}` | [entfernt überflüssige Leerzeichen|#spaceless]
+| `{syntax}`                     | [Änderung der Syntax zur Laufzeit|#syntax]
+| `{trace}`                      | [zeigt den Stack-Trace an|#trace]
 
 .[table-latte-tags language-latte]
-|## HTML-Tag-Helfer
-| `n:class` | [intelligentes Klassenattribut |#n:class]
-| `n:attr` | [intelligente HTML-Attribute |#n:attr]
-| `n:tag` | [Dynamischer Name des HTML-Elements |#n:tag]
-| `n:ifcontent` | [Leeren HTML-Tag auslassen |#n:ifcontent]
+|## Helfer für HTML-Codierer
+| `n:class`                      | [dynamische Schreibweise des HTML-Attributs class|#n:class]
+| `n:attr`                       | [dynamische Schreibweise beliebiger HTML-Attribute|#n:attr]
+| `n:tag`                        | [dynamische Schreibweise des HTML-Element-Namens|#n:tag]
+| `n:ifcontent`                  | [lässt einen leeren HTML-Tag aus|#n:ifcontent]
 
 .[table-latte-tags language-latte]
-|## Nur in Nette Framework verfügbar
-| `n:href` | [Link in `<a>` HTML-Elementen |application:creating-links#In the Presenter Template]
-| `{link}` | [gibt einen Link aus |application:creating-links#In the Presenter Template]
-| `{plink}` | [druckt einen Link zu einem Presenter |application:creating-links#In the Presenter Template]
-| `{control}` | [druckt eine Komponente |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [ein Template-Snippet, das per AJAX gesendet werden kann |application:ajax#tag-snippet]
-| `{snippetArea}` | Schnipsel Umschlag
-| `{cache}`... `{/cache}` | [zwischenspeichert einen Vorlagenabschnitt |caching:#caching-in-latte]
+|## Nur im Nette Framework verfügbar
+| `n:href`                       | [Link, der in HTML-Elementen `<a>` verwendet wird|application:creating-links#In the Presenter Template]
+| `{link}`                       | [gibt einen Link aus|application:creating-links#In the Presenter Template]
+| `{plink}`                      | [gibt einen Link zu einem Presenter aus|application:creating-links#In the Presenter Template]
+| `{control}`                    | [rendert eine Komponente|application:components#Rendering]
+| `{snippet}` … `{/snippet}`     | [ein Snippet, das per AJAX gesendet werden kann|application:ajax#snippets-in-latte]
+| `{snippetArea}`                | [Wrapper für Snippets|application:ajax#snippet-areas]
+| `{cache}` … `{/cache}`         | [cached einen Teil des Templates|caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
 |## Nur mit Nette Forms verfügbar
-| `{form}`... `{/form}` | [druckt ein Formularelement |forms:rendering#form]
-| `{label}`... `{/label}` | [druckt eine Formulareingabebezeichnung |forms:rendering#label-input]
-| `{input}` | [druckt ein Formulareingabeelement |forms:rendering#label-input]
-| `{inputError}` | [gibt eine Fehlermeldung für ein Formulareingabeelement aus |forms:rendering#inputError]
-| `n:name` | [aktiviert ein HTML-Eingabeelement |forms:rendering#n:name]
-| `{formPrint}` | [erzeugt einen Latte-Formular-Blaupause |forms:rendering#formPrint]
-| `{formPrintClass}` | [gibt PHP-Klasse für Formulardaten aus |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [Teilweise Formularwiedergabe |forms:rendering#special-cases]
-| `{formContainer}`... `{/formContainer}` | [Darstellung des Formular-Containers |forms:rendering#special-cases]
-
-
-Drucken .[#toc-printing]
+| `{form}` … `{/form}`           | [rendert Formular-Tags|forms:rendering#form]
+| `{label}` … `{/label}`         | [rendert ein Label für ein Formularelement|forms:rendering#label-input]
+| `{input}`                      | [rendert ein Formularelement|forms:rendering#label-input]
+| `{inputError}`                 | [gibt eine Fehlermeldung für ein Formularelement aus|forms:rendering#inputError]
+| `n:name`                       | [aktiviert ein Formularelement|forms:rendering#n:name]
+| `{formContainer}` … `{/formContainer}` | [Zeichnen eines Formular-Containers|forms:rendering#special-cases]
+
+
+Ausgabe .[#toc-printing]
 ========================
 
 
 `{$var}` `{...}` `{=...}`
 -------------------------
 
-Latte verwendet das Tag `{=...}`, um einen beliebigen Ausdruck in der Ausgabe auszugeben. Wenn der Ausdruck mit einer Variablen oder einem Funktionsaufruf beginnt, ist es nicht nötig, ein Gleichheitszeichen zu schreiben. Das bedeutet in der Praxis, dass es fast nie geschrieben werden muss:
+In Latte wird das Tag `{=...}` verwendet, um einen beliebigen Ausdruck auszugeben. Latte legt Wert auf Ihren Komfort, daher ist es nicht nötig, das Gleichheitszeichen zu schreiben, wenn der Ausdruck mit einer Variable oder einem Funktionsaufruf beginnt. Das bedeutet in der Praxis, dass es fast nie notwendig ist, es zu schreiben:
 
 ```latte
 Name: {$name} {$surname}<br>
-Age: {date('Y') - $birth}<br>
+Alter: {date('Y') - $birth}<br>
 ```
 
-Sie können alles, was Sie aus PHP kennen, als Ausdruck schreiben. Sie müssen nur keine neue Sprache lernen. Zum Beispiel:
+Als Ausdruck können Sie alles schreiben, was Sie aus PHP kennen. Sie müssen einfach keine neue Sprache lernen. Zum Beispiel:
 
 
 ```latte
 {='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}
 ```
 
-Bitte suchen Sie nicht nach einer Bedeutung in dem vorherigen Beispiel, aber wenn Sie eine finden, schreiben Sie uns :-)
+Bitte suchen Sie in dem vorherigen Beispiel keinen Sinn, aber wenn Sie einen finden sollten, schreiben Sie uns :-)
 
 
-Ausweichende Ausgabe .[#toc-escaping-output]
---------------------------------------------
+Ausgabe escapen .[#toc-escaping-output]
+---------------------------------------
 
-Was ist die wichtigste Aufgabe eines Template-Systems? Sicherheitslücken zu vermeiden. Und genau das tut Latte, wenn Sie etwas in die Ausgabe drucken. Es entschlüsselt automatisch alles:
+Was ist die wichtigste Aufgabe eines Template-Systems? Sicherheitslücken zu verhindern. Und genau das macht Latte immer, wenn Sie etwas ausgeben. Es escaped es automatisch:
 
 ```latte
-<p>{='one < two'}</p>   {* prints: '<p>one &lt; two</p>' *}
+<p>{='one < two'}</p>   {* gibt aus: '<p>one &lt; two</p>' *}
 ```
 
-Um genau zu sein, verwendet Latte kontextabhängiges Escaping, eine so wichtige und einzigartige Funktion dass wir ihr [ein eigenes Kapitel |safety-first#context-aware-escaping] gewidmet haben.
+Um genau zu sein, verwendet Latte kontextsensitives Escaping, was so wichtig und einzigartig ist, dass wir ihm [ein eigenes Kapitel|safety-first#context-aware-escaping] gewidmet haben.
 
-Und wenn Sie HTML-codierte Inhalte aus einer vertrauenswürdigen Quelle drucken? Dann können Sie das Escaping einfach abschalten:
+Und was ist, wenn Sie HTML-codierten Inhalt aus einer vertrauenswürdigen Quelle ausgeben? Dann kann das Escaping einfach deaktiviert werden:
 
 ```latte
 {$trustedHtmlString|noescape}
 ```
 
 .[warning]
-Der Missbrauch des `noescape`-Filters kann zu einer XSS-Schwachstelle führen! Verwenden Sie ihn nur, wenn Sie **absolut sicher** sind, was Sie tun und dass die Zeichenfolge, die Sie ausgeben, aus einer vertrauenswürdigen Quelle stammt.
+Eine falsche Verwendung des `noescape`-Filters kann zu einer XSS-Schwachstelle führen! Verwenden Sie ihn niemals, wenn Sie sich nicht **absolut sicher** sind, was Sie tun, und dass die ausgegebene Zeichenkette aus einer vertrauenswürdigen Quelle stammt.
 
 
-Drucken in JavaScript .[#toc-printing-in-javascript]
+Ausgabe in JavaScript .[#toc-printing-in-javascript]
 ----------------------------------------------------
 
-Dank der kontextsensitiven Escape-Funktion ist es wunderbar einfach, Variablen innerhalb von JavaScript zu drucken, und Latte wird sie korrekt escapen.
+Dank des kontextsensitiven Escapings ist es wunderbar einfach, Variablen innerhalb von JavaScript auszugeben, und Latte kümmert sich um das korrekte Escaping.
 
-Die Variable muss keine Zeichenkette sein, es wird jeder Datentyp unterstützt, der dann als JSON kodiert wird:
+Die Variable muss nicht unbedingt ein String sein, es wird jeder Datentyp unterstützt, der dann als JSON kodiert wird:
 
 ```latte
 {var $foo = ['hello', true, 1]}
@@ -181,7 +179,7 @@ Erzeugt:
 </script>
 ```
 
-Dies ist auch der Grund, warum **Variablen nicht in Anführungszeichen** gesetzt werden sollten: Latte fügt sie um Strings herum ein. Und wenn Sie eine String-Variable in einen anderen String einfügen wollen, verketten Sie sie einfach:
+Das ist auch der Grund, warum **keine Anführungszeichen** um die Variable geschrieben werden: Latte fügt sie bei Strings selbst hinzu. Und wenn Sie eine String-Variable in einen anderen String einfügen möchten, verbinden Sie sie einfach:
 
 ```latte
 <script>
@@ -189,7 +187,7 @@ Dies ist auch der Grund, warum **Variablen nicht in Anführungszeichen** gesetzt
 
 	alert({="Hello $name!"});         // OK
 
-	alert('Hello {$name} !');         // ERROR!
+	alert('Hello {$name} !');         // FEHLER!
 </script>
 ```
 
@@ -197,13 +195,13 @@ Dies ist auch der Grund, warum **Variablen nicht in Anführungszeichen** gesetzt
 Filter .[#toc-filters]
 ----------------------
 
-Der gedruckte Ausdruck kann [durch Filter |syntax#filters] verändert werden. In diesem Beispiel wird die Zeichenkette beispielsweise in Großbuchstaben umgewandelt und auf maximal 30 Zeichen gekürzt:
+Der ausgegebene Ausdruck kann durch einen [Filter|syntax#filters] modifiziert werden. So können wir zum Beispiel eine Zeichenkette in Großbuchstaben umwandeln und auf maximal 30 Zeichen kürzen:
 
 ```latte
 {$string|upper|truncate:30}
 ```
 
-Sie können auch Filter auf Teile eines Ausdrucks anwenden, wie folgt:
+Filter können auch auf Teile eines Ausdrucks auf folgende Weise angewendet werden:
 
 ```latte
 {$left . ($middle|upper) . $right}
@@ -217,46 +215,60 @@ Bedingungen .[#toc-conditions]
 `{if}` `{elseif}` `{else}`
 --------------------------
 
-Bedingungen verhalten sich genauso wie die entsprechenden PHP-Ausdrücke. Sie können die gleichen Ausdrücke verwenden, die Sie aus PHP kennen, Sie müssen keine neue Sprache lernen.
+Bedingungen verhalten sich genauso wie ihre Pendants in PHP. Sie können in ihnen die gleichen Ausdrücke verwenden, die Sie aus PHP kennen, Sie müssen keine neue Sprache lernen.
 
 ```latte
 {if $product->inStock > Stock::Minimum}
-	In stock
+	Auf Lager
 {elseif $product->isOnWay()}
-	On the way
+	Unterwegs
 {else}
-	Not available
+	Nicht verfügbar
 {/if}
 ```
 
-Wie jedes Paar-Tag kann ein Paar von `{if} ... {/ if}` zum Beispiel als [n:attribute |syntax#n:attributes] geschrieben werden:
+Wie jedes Paar-Tag kann auch das Paar `{if} ... {/if}` in Form eines [n:Attributs|syntax#n:attributes] geschrieben werden, zum Beispiel:
 
 ```latte
-<p n:if="$count > 0">In stock {$count} items</p>
+<p n:if="$count > 0">{$count} Artikel auf Lager</p>
 ```
 
-Wussten Sie, dass Sie das Präfix `tag-` zu n:Attributen hinzufügen können? Dann wirkt sich die Bedingung nur auf die HTML-Tags aus und der Inhalt zwischen ihnen wird immer gedruckt:
+Wussten Sie, dass Sie n:Attribute mit dem Präfix `tag-` versehen können? Dann bezieht sich die Bedingung nur auf die Ausgabe der HTML-Tags, und der Inhalt dazwischen wird immer ausgegeben:
 
 ```latte
 <a href="..." n:tag-if="$clickable">Hello</a>
 
-{* prints 'Hello' when $clickable is falsey *}
-{* prints '<a href="...">Hello</a>' when $clickable is truthy *}
+{* gibt 'Hello' aus, wenn $clickable falsch ist *}
+{* gibt '<a href="...">Hello</a>' aus, wenn $clickable wahr ist *}
+```
+
+Göttlich.
+
+
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Wenn Sie die Bedingung `{if} ... {/if}` in Form eines [n:Attributs|syntax#n:attributes] schreiben, haben Sie die Möglichkeit, eine alternative Verzweigung mit `n:else` anzugeben:
+
+```latte
+<strong n:if="$count > 0">{$count} Artikel auf Lager</strong>
+
+<em n:else>nicht verfügbar</em>
 ```
 
-Schön.
+Das Attribut `n:else` kann auch in Kombination mit [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent] und [`n:ifchanged` |#ifchanged] verwendet werden.
 
 
 `{/if $cond}`
 -------------
 
-Sie werden vielleicht überrascht sein, dass der Ausdruck in der Bedingung `{if}` auch im End-Tag angegeben werden kann. Dies ist in Situationen nützlich, in denen wir den Wert der Bedingung noch nicht kennen, wenn das Tag geöffnet wird. Nennen wir es eine aufgeschobene Entscheidung.
+Es mag Sie überraschen, dass der Ausdruck in der Bedingung `{if}` auch im schließenden Tag angegeben werden kann. Dies ist nützlich in Situationen, in denen wir beim Öffnen der Bedingung ihren Wert noch nicht kennen. Nennen wir es eine verzögerte Entscheidung.
 
-Wir beginnen z. B. mit der Auflistung einer Tabelle mit Datensätzen aus der Datenbank und stellen erst nach Fertigstellung des Berichts fest, dass kein Datensatz in der Datenbank vorhanden war. Also setzen wir die Bedingung in das End-Tag `{/if}`, und wenn es keinen Datensatz gibt, wird nichts davon gedruckt:
+Zum Beispiel beginnen wir mit der Ausgabe einer Tabelle mit Datensätzen aus der Datenbank und erst nach Abschluss der Ausgabe stellen wir fest, dass kein Datensatz in der Datenbank vorhanden war. Also setzen wir eine Bedingung in das schließende `{/if}`-Tag, und wenn kein Datensatz vorhanden ist, wird nichts davon ausgegeben:
 
 ```latte
 {if}
-	<h1>Printing rows from the database</h1>
+	<h1>Ausgabe von Zeilen aus der Datenbank</h1>
 
 	<table>
 	{foreach $resultSet as $row}
@@ -266,9 +278,9 @@ Wir beginnen z. B. mit der Auflistung einer Tabelle mit Datensätzen aus der Dat
 {/if isset($row)}
 ```
 
-Praktisch, nicht wahr?
+Clever, nicht wahr?
 
-Sie können auch `{else}` in der aufgeschobenen Bedingung verwenden, aber nicht `{elseif}`.
+In einer verzögerten Bedingung kann auch `{else}` verwendet werden, aber nicht `{elseif}`.
 
 
 `{ifset}` `{elseifset}`
@@ -277,19 +289,19 @@ Sie können auch `{else}` in der aufgeschobenen Bedingung verwenden, aber nicht
 .[note]
 Siehe auch [`{ifset block}` |template-inheritance#checking-block-existence]
 
-Verwenden Sie die `{ifset $var}` Bedingung, um festzustellen, ob eine Variable (oder mehrere Variablen) existiert und einen Nicht-Null-Wert hat. Es ist eigentlich das Gleiche wie `if (isset($var))` in PHP. Wie jedes Paar-Tag kann es in der Form von [n:attribute |syntax#n:attributes] geschrieben werden, also zeigen wir es in einem Beispiel:
+Mit der Bedingung `{ifset $var}` können wir überprüfen, ob eine Variable (oder mehrere Variablen) existiert und einen nicht-null-Wert hat. Es ist im Grunde dasselbe wie `if (isset($var))` in PHP. Wie jedes Paar-Tag kann es auch in Form eines [n:Attributs|syntax#n:attributes] geschrieben werden, also zeigen wir es als Beispiel:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
 `{ifchanged}`
 -------------
 
-`{ifchanged}` prüft, ob sich der Wert einer Variablen seit der letzten Iteration in der Schleife (foreach, for oder while) geändert hat.
+`{ifchanged}` überprüft, ob sich der Wert einer Variable seit der letzten Iteration in einer Schleife (foreach, for oder while) geändert hat.
 
-Wenn wir eine oder mehrere Variablen im Tag angeben, wird geprüft, ob sich eine von ihnen geändert hat, und der Inhalt wird entsprechend ausgegeben. Im folgenden Beispiel wird beispielsweise bei der Auflistung von Namen jedes Mal der erste Buchstabe eines Namens als Überschrift ausgegeben, wenn er sich ändert:
+Wenn wir eine oder mehrere Variablen im Tag angeben, wird überprüft, ob sich eine von ihnen geändert hat, und dementsprechend wird der Inhalt ausgegeben. Das folgende Beispiel gibt den ersten Buchstaben des Namens als Überschrift aus, jedes Mal wenn er sich bei der Ausgabe der Namen ändert:
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -299,7 +311,7 @@ Wenn wir eine oder mehrere Variablen im Tag angeben, wird geprüft, ob sich eine
 {/foreach}
 ```
 
-Wenn jedoch kein Argument angegeben wird, wird der gerenderte Inhalt selbst mit seinem vorherigen Zustand verglichen. Das bedeutet, dass wir im vorherigen Beispiel das Argument im Tag getrost weglassen können. Und natürlich können wir auch [n:attribute |syntax#n:attributes] verwenden:
+Wenn wir jedoch kein Argument angeben, wird der gerenderte Inhalt im Vergleich zu seinem vorherigen Zustand überprüft. Das bedeutet, dass wir im vorherigen Beispiel das Argument im Tag weglassen können. Und natürlich können wir auch ein [n:Attribut|syntax#n:attributes] verwenden:
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -309,35 +321,35 @@ Wenn jedoch kein Argument angegeben wird, wird der gerenderte Inhalt selbst mit
 {/foreach}
 ```
 
-Sie können auch eine `{else}` Klausel innerhalb der `{ifchanged}` einfügen.
+Innerhalb von `{ifchanged}` kann auch eine `{else}`-Klausel verwendet werden.
 
 
 `{switch}` `{case}` `{default}`
 -------------------------------
-Vergleicht den Wert mit mehreren Optionen. Dies ist ähnlich wie die `switch` Struktur, die Sie aus PHP kennen. Latte verbessert sie jedoch:
+Vergleicht einen Wert mit mehreren Möglichkeiten. Es ist ähnlich wie die bedingte Anweisung `switch`, die Sie aus PHP kennen. Latte verbessert sie jedoch:
 
-- verwendet einen strengen Vergleich (`===`)
-- braucht kein `break`
+- es verwendet einen strikten Vergleich (`===`)
+- es benötigt kein `break`
 
-Es ist also das exakte Äquivalent der `match` Struktur, die PHP 8.0 mitbringt.
+Es ist also das genaue Äquivalent zur `match`-Struktur, die mit PHP 8.0 eingeführt wurde.
 
 ```latte
 {switch $transport}
 	{case train}
-		By train
+		Mit dem Zug
 	{case plane}
-		By plane
+		Mit dem Flugzeug
 	{default}
-		Differently
+		Anderweitig
 {/switch}
 ```
 
-Die Klausel `{case}` kann mehrere durch Kommas getrennte Werte enthalten:
+Die `{case}`-Klausel kann mehrere durch Kommas getrennte Werte enthalten:
 
 ```latte
 {switch $status}
-{case $status::New}<b>new item</b>
-{case $status::Sold, $status::Unknown}<i>not available</i>
+{case $status::New}<b>neuer Artikel</b>
+{case $status::Sold, $status::Unknown}<i>nicht verfügbar</i>
 {/switch}
 ```
 
@@ -345,13 +357,13 @@ Die Klausel `{case}` kann mehrere durch Kommas getrennte Werte enthalten:
 Schleifen .[#toc-loops]
 =======================
 
-In Latte stehen Ihnen alle Schleifen, die Sie aus PHP kennen, zur Verfügung: foreach, for und while.
+In Latte finden Sie alle Schleifen, die Sie aus PHP kennen: foreach, for und while.
 
 
 `{foreach}`
 -----------
 
-Sie schreiben den Zyklus genau so wie in PHP:
+Wir schreiben die Schleife genauso wie in PHP:
 
 ```latte
 {foreach $langs as $code => $lang}
@@ -359,11 +371,11 @@ Sie schreiben den Zyklus genau so wie in PHP:
 {/foreach}
 ```
 
-Darüber hinaus hat er einige praktische Verbesserungen, über die wir jetzt sprechen werden.
+Zusätzlich hat sie einige nützliche Funktionen, über die wir jetzt sprechen werden.
 
-So stellt Latte zum Beispiel sicher, dass erstellte Variablen nicht versehentlich gleichnamige globale Variablen überschreiben. Das hilft Ihnen, wenn Sie davon ausgehen, dass `$lang` die aktuelle Sprache der Seite ist, und Sie nicht merken, dass `foreach $langs as $lang` diese Variable überschrieben hat.
+Latte überprüft zum Beispiel, ob erstellte Variablen versehentlich globale Variablen mit demselben Namen überschreiben. Das rettet Situationen, in denen Sie davon ausgehen, dass `$lang` die aktuelle Sprache der Seite ist, und nicht bemerken, dass `foreach $langs as $lang` diese Variable überschrieben hat.
 
-Die foreach-Schleife kann auch sehr elegant und sparsam mit [n:attribute |syntax#n:attributes] geschrieben werden:
+Die foreach-Schleife kann auch sehr elegant und kompakt als [n:Attribut|syntax#n:attributes] geschrieben werden:
 
 ```latte
 <ul>
@@ -371,7 +383,7 @@ Die foreach-Schleife kann auch sehr elegant und sparsam mit [n:attribute |syntax
 </ul>
 ```
 
-Wussten Sie, dass Sie n:attributes das Präfix `inner-` voranstellen können? Dann wird in der Schleife nur noch der innere Teil des Elements wiederholt:
+Wussten Sie, dass Sie n:Attribute mit dem Präfix `inner-` versehen können? Dann wird nur der Inhalt des Elements in der Schleife wiederholt:
 
 ```latte
 <div n:inner-foreach="$items as $item">
@@ -380,7 +392,7 @@ Wussten Sie, dass Sie n:attributes das Präfix `inner-` voranstellen können? Da
 </div>
 ```
 
-Es wird also etwas gedruckt wie:
+Dies wird also etwas wie folgendes ausgeben:
 
 ```latte
 <div>
@@ -395,14 +407,14 @@ Es wird also etwas gedruckt wie:
 `{else}` .{toc: foreach-else}
 -----------------------------
 
-Die Schleife `foreach` kann eine optionale Klausel `{else}` enthalten, deren Text angezeigt wird, wenn das angegebene Feld leer ist:
+Innerhalb einer `foreach`-Schleife kann eine `{else}`-Klausel angegeben werden, deren Inhalt angezeigt wird, wenn die Schleife leer ist:
 
 ```latte
 <ul>
 	{foreach $people as $person}
 		<li>{$person->name}</li>
 	{else}
-		<li><em>Sorry, no users in this list</em></li>
+		<li><em>Leider sind in dieser Liste keine Benutzer</em></li>
 	{/foreach}
 </ul>
 ```
@@ -411,17 +423,17 @@ Die Schleife `foreach` kann eine optionale Klausel `{else}` enthalten, deren Tex
 `$iterator`
 -----------
 
-Innerhalb der Schleife `foreach` wird die Variable `$iterator` initialisiert. Sie enthält wichtige Informationen über die aktuelle Schleife.
+Innerhalb einer `foreach`-Schleife erstellt Latte eine Variable `$iterator`, mit der wir nützliche Informationen über die laufende Schleife abrufen können:
 
-- `$iterator->first` - ist dies die erste Iteration?
-- `$iterator->last` - ist dies die letzte Iteration?
-- `$iterator->counter` - Iterationszähler, beginnt bei 1
-- `$iterator->counter0` - Iterationszähler, beginnt bei 0
-- `$iterator->odd` - Ist diese Iteration ungerade?
-- `$iterator->even` - ist diese Iteration gerade?
-- `$iterator->parent` - der Iterator, der den aktuellen Iterator umgibt
-- `$iterator->nextValue` - das nächste Element in der Schleife
-- `$iterator->nextKey` - der Schlüssel des nächsten Elements in der Schleife
+- `$iterator->first` - ist dies der erste Durchlauf?
+- `$iterator->last` - ist dies der letzte Durchlauf?
+- `$iterator->counter` - der wievielte Durchlauf ist es, gezählt ab eins?
+- `$iterator->counter0` - der wievielte Durchlauf ist es, gezählt ab null?
+- `$iterator->odd` - ist dies ein ungerader Durchlauf?
+- `$iterator->even` - ist dies ein gerader Durchlauf?
+- `$iterator->parent` - der Iterator, der den aktuellen umgibt
+- `$iterator->nextValue` - der nächste Eintrag in der Schleife
+- `$iterator->nextKey` - der Schlüssel des nächsten Eintrags in der Schleife
 
 
 ```latte
@@ -437,20 +449,20 @@ Innerhalb der Schleife `foreach` wird die Variable `$iterator` initialisiert. Si
 {/foreach}
 ```
 
-Die Latte ist schlau und `$iterator->last` funktioniert nicht nur für Arrays, sondern auch, wenn die Schleife über einen allgemeinen Iterator läuft, bei dem die Anzahl der Elemente nicht im Voraus bekannt ist.
+Latte ist schlau und `$iterator->last` funktioniert nicht nur bei Arrays, sondern auch wenn die Schleife über einen allgemeinen Iterator läuft, bei dem die Anzahl der Elemente nicht im Voraus bekannt ist.
 
 
 `{first}` `{last}` `{sep}`
 --------------------------
 
-Diese Tags können innerhalb der Schleife `{foreach}` verwendet werden. Der Inhalt von `{first}` wird beim ersten Durchlauf gerendert.
-Der Inhalt von `{last}` wird gerendert ... können Sie es erraten? Ja, für den letzten Durchlauf. Dies sind eigentlich Abkürzungen für `{if $iterator->first}` und `{if $iterator->last}`.
+Diese Tags können innerhalb einer `{foreach}`-Schleife verwendet werden. Der Inhalt von `{first}` wird gerendert, wenn es sich um den ersten Durchlauf handelt.
+Der Inhalt von `{last}` wird gerendert ... können Sie es erraten? Ja, wenn es sich um den letzten Durchlauf handelt. Es handelt sich eigentlich um Abkürzungen für `{if $iterator->first}` und `{if $iterator->last}`.
 
-Die Tags können auch als [n:attributes |syntax#n:attributes] geschrieben werden:
+Die Tags können auch elegant als [n:Attribute|syntax#n:attributes] verwendet werden:
 
 ```latte
 {foreach $rows as $row}
-	{first}<h1>List of names</h1>{/first}
+	{first}<h1>Liste der Namen</h1>{/first}
 
 	<p>{$row->name}</p>
 
@@ -458,21 +470,21 @@ Die Tags können auch als [n:attributes |syntax#n:attributes] geschrieben werden
 {/foreach}
 ```
 
-Der Inhalt von `{sep}` wird wiedergegeben, wenn es sich nicht um die letzte Iteration handelt, und eignet sich daher für die Ausgabe von Begrenzungszeichen, wie z. B. Kommas zwischen aufgelisteten Elementen:
+Der Inhalt des `{sep}`-Tags wird gerendert, wenn der Durchlauf nicht der letzte ist. Es eignet sich also zum Rendern von Trennzeichen, zum Beispiel Kommas zwischen ausgegebenen Elementen:
 
 ```latte
 {foreach $items as $item} {$item} {sep}, {/sep} {/foreach}
 ```
 
-Das ist doch ziemlich praktisch, oder?
+Das ist ziemlich praktisch, nicht wahr?
 
 
 `{iterateWhile}`
 ----------------
 
-Sie vereinfacht die Gruppierung von linearen Daten während der Iteration in einer foreach-Schleife, indem sie die Iteration in einer verschachtelten Schleife durchführt, solange die Bedingung erfüllt ist. [Lesen Sie die Anweisungen im Kochbuch |cookbook/iteratewhile].
+Vereinfacht die Gruppierung linearer Daten während der Iteration in einer foreach-Schleife, indem die Iteration in einer verschachtelten Schleife durchgeführt wird, solange eine Bedingung erfüllt ist. [Lesen Sie die detaillierte Anleitung|cookbook/grouping].
 
-Sie kann auch `{first}` und `{last}` im obigen Beispiel elegant ersetzen:
+Es kann auch elegant `{first}` und `{last}` im obigen Beispiel ersetzen:
 
 ```latte
 {foreach $rows as $row}
@@ -489,19 +501,21 @@ Sie kann auch `{first}` und `{last}` im obigen Beispiel elegant ersetzen:
 {/foreach}
 ```
 
+Siehe auch die Filter [batch|filters#batch] und [group|filters#group].
+
 
 `{for}`
 -------
 
-Wir schreiben den Zyklus genau so wie in PHP:
+Wir schreiben die Schleife genauso wie in PHP:
 
 ```latte
 {for $i = 0; $i < 10; $i++}
-	<span>Item #{$i}</span>
+	<span>Element {$i}</span>
 {/for}
 ```
 
-Das Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden:
+Das Tag kann auch als [n:Attribut|syntax#n:attributes] verwendet werden:
 
 ```latte
 <h1 n:for="$i = 0; $i < 10; $i++">{$i}</h1>
@@ -511,7 +525,7 @@ Das Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden:
 `{while}`
 ---------
 
-Auch hier schreiben wir den Zyklus genau so, wie in PHP:
+Wir schreiben die Schleife wieder genauso wie in PHP:
 
 ```latte
 {while $row = $result->fetch()}
@@ -519,7 +533,7 @@ Auch hier schreiben wir den Zyklus genau so, wie in PHP:
 {/while}
 ```
 
-Oder als [n:Attribut |syntax#n:attributes]:
+Oder als [n:Attribut|syntax#n:attributes]:
 
 ```latte
 <span n:while="$row = $result->fetch()">
@@ -527,7 +541,7 @@ Oder als [n:Attribut |syntax#n:attributes]:
 </span>
 ```
 
-Eine Variante mit einer Bedingung im End-Tag entspricht der do-while-Schleife in PHP:
+Eine Variante mit der Bedingung im schließenden Tag ist ebenfalls möglich, die der do-while-Schleife in PHP entspricht:
 
 ```latte
 {while}
@@ -539,7 +553,7 @@ Eine Variante mit einer Bedingung im End-Tag entspricht der do-while-Schleife in
 `{continueIf}` `{skipIf}` `{breakIf}`
 -------------------------------------
 
-Es gibt spezielle Tags, die Sie zur Steuerung jeder Schleife verwenden können - `{continueIf ?}` und `{breakIf ?}`, die zur nächsten Iteration springen bzw. die Schleife beenden, wenn die Bedingungen erfüllt sind:
+Zur Steuerung jeder Schleife können die Tags `{continueIf ?}` und `{breakIf ?}` verwendet werden, die zum nächsten Element übergehen bzw. die Schleife beenden, wenn eine Bedingung erfüllt ist:
 
 ```latte
 {foreach $rows as $row}
@@ -550,7 +564,7 @@ Es gibt spezielle Tags, die Sie zur Steuerung jeder Schleife verwenden können -
 ```
 
 
-Das Tag `{skipIf}` ist dem Tag `{continueIf}` sehr ähnlich, erhöht aber den Zähler nicht. So gibt es keine Löcher in der Nummerierung, wenn Sie `$iterator->counter` ausdrucken und einige Elemente überspringen. Auch die {else}-Klausel wird wiedergegeben, wenn Sie alle Elemente überspringen.
+Das `{skipIf}`-Tag ist sehr ähnlich wie `{continueIf}`, erhöht aber nicht den Zähler `$iterator->counter`, so dass, wenn wir ihn ausgeben und gleichzeitig einige Elemente überspringen, keine Lücken in der Nummerierung entstehen. Außerdem wird die `{else}`-Klausel gerendert, wenn wir alle Elemente überspringen.
 
 ```latte
 <ul>
@@ -558,7 +572,7 @@ Das Tag `{skipIf}` ist dem Tag `{continueIf}` sehr ähnlich, erhöht aber den Z
 		{skipIf $person->age < 18}
 		<li>{$iterator->counter}. {$person->name}</li>
 	{else}
-		<li><em>Sorry, no adult users in this list</em></li>
+		<li><em>Leider gibt es keine Erwachsenen in dieser Liste</em></li>
 	{/foreach}
 </ul>
 ```
@@ -567,20 +581,20 @@ Das Tag `{skipIf}` ist dem Tag `{continueIf}` sehr ähnlich, erhöht aber den Z
 `{exitIf}` .{data-version:3.0.5}
 --------------------------------
 
-Beendet das Rendering einer Vorlage oder eines Blocks, wenn eine Bedingung erfüllt ist (d. h. "early exit").
+Beendet das Rendern des Templates oder Blocks, wenn eine Bedingung erfüllt ist (sogenannter "early exit").
 
 ```latte
 {exitIf !$messages}
 
-<h1>Messages</h1>
+<h1>Nachrichten</h1>
 <div n:foreach="$messages as $message">
    {$message}
 </div>
 ```
 
 
-Schablonen einbeziehen .[#toc-including-templates]
-==================================================
+Einbindung von Templates .[#toc-including-templates]
+====================================================
 
 
 `{include 'file.latte'}` .{toc: include}
@@ -589,46 +603,46 @@ Schablonen einbeziehen .[#toc-including-templates]
 .[note]
 Siehe auch [`{include block}` |template-inheritance#printing-blocks]
 
-Der `{include}` Tag lädt und rendert die angegebene Vorlage. In unserer Lieblingssprache PHP sieht das so aus:
+Das `{include}`-Tag lädt und rendert das angegebene Template. Wenn wir in der Sprache unserer Lieblingssprache PHP sprechen würden, wäre es so etwas wie:
 
 ```php
 <?php include 'header.phtml'; ?>
 ```
 
-Eingebundene Templates haben keinen Zugriff auf die Variablen des aktiven Kontexts, aber sie haben Zugriff auf die globalen Variablen.
+Eingebundene Templates haben keinen Zugriff auf die Variablen des aktiven Kontexts, sie haben nur Zugriff auf globale Variablen.
 
-Sie können der eingefügten Vorlage auf folgende Weise Variablen übergeben:
+Variablen können auf diese Weise an das eingebundene Template übergeben werden:
 
 ```latte
 {include 'template.latte', foo: 'bar', id: 123}
 ```
 
-Der Name der Vorlage kann ein beliebiger PHP-Ausdruck sein:
+Der Name des Templates kann ein beliebiger PHP-Ausdruck sein:
 
 ```latte
 {include $someVar}
 {include $ajax ? 'ajax.latte' : 'not-ajax.latte'}
 ```
 
-Der eingefügte Inhalt kann durch [Filter |syntax#filters] verändert werden. Im folgenden Beispiel werden alle HTML-Elemente entfernt und die Groß- und Kleinschreibung angepasst:
+Der eingebundene Inhalt kann mit [Filtern|syntax#Filters] modifiziert werden. Das folgende Beispiel entfernt das gesamte HTML und passt die Groß-/Kleinschreibung an:
 
 ```latte
 <title>{include 'heading.latte' |stripHtml|capitalize}</title>
 ```
 
-Die [Vorlagenvererbung |template inheritance] ist standardmäßig **nicht** daran beteiligt. Sie können zwar Block-Tags zu eingebundenen Vorlagen hinzufügen, diese ersetzen jedoch nicht die passenden Blöcke in der Vorlage, in die sie eingebunden sind. Betrachten Sie Includes als unabhängige und abgeschirmte Teile von Seiten oder Modulen. Dieses Verhalten kann mit dem Modifikator `with blocks` geändert werden:
+Standardmäßig spielt die [Template-Vererbung|template-inheritance] in diesem Fall keine Rolle. Auch wenn wir in dem eingebundenen Template Blöcke verwenden können, werden die entsprechenden Blöcke in dem Template, in das eingebunden wird, nicht ersetzt. Denken Sie an eingebundene Templates als separate, abgeschirmte Teile von Seiten oder Modulen. Dieses Verhalten kann mit dem Modifikator `with blocks` geändert werden:
 
 ```latte
 {include 'template.latte' with blocks}
 ```
 
-Die Beziehung zwischen dem im Tag angegebenen Dateinamen und der Datei auf der Festplatte ist eine Sache des [Loaders |extending-latte#Loaders].
+Die Beziehung zwischen dem im Tag angegebenen Dateinamen und der Datei auf der Festplatte ist eine Angelegenheit des [Loaders|extending-latte#Loaders].
 
 
 `{sandbox}`
 -----------
 
-Wenn Sie eine von einem Endbenutzer erstellte Vorlage einbinden, sollten Sie eine Sandbox verwenden (weitere Informationen finden Sie in der [Sandbox-Dokumentation |sandbox]):
+Bei der Einbindung eines vom Endbenutzer erstellten Templates sollten Sie den Sandbox-Modus in Betracht ziehen (weitere Informationen finden Sie in der [Sandbox-Dokumentation |sandbox]):
 
 ```latte
 {sandbox 'untrusted.latte', level: 3, data: $menu}
@@ -641,7 +655,7 @@ Wenn Sie eine von einem Endbenutzer erstellte Vorlage einbinden, sollten Sie ein
 .[note]
 Siehe auch [`{block name}` |template-inheritance#blocks]
 
-Blöcke ohne Namen dienen dazu, [Filter |syntax#filters] auf einen Teil der Vorlage anzuwenden. Sie können zum Beispiel einen [Streifenfilter |filters#strip] anwenden, um überflüssige Leerzeichen zu entfernen:
+Namenlose Blöcke dienen als Möglichkeit, [Filter|syntax#Filters] auf einen Teil des Templates anzuwenden. Zum Beispiel kann auf diese Weise der [strip|filters#strip]-Filter angewendet werden, der überflüssige Leerzeichen entfernt:
 
 ```latte
 {block|strip}
@@ -652,16 +666,16 @@ Blöcke ohne Namen dienen dazu, [Filter |syntax#filters] auf einen Teil der Vorl
 ```
 
 
-Behandlung von Ausnahmen .[#toc-exception-handling]
-===================================================
+Ausnahmebehandlung .[#toc-exception-handling]
+=============================================
 
 
 `{try}`
 -------
 
-Diese Tags machen es extrem einfach, robuste Vorlagen zu erstellen.
+Dank dieses Tags ist es extrem einfach, robuste Templates zu erstellen.
 
-Wenn beim Rendern des `{try}` -Blocks eine Ausnahme auftritt, wird der gesamte Block verworfen und das Rendern danach fortgesetzt:
+Wenn während des Renderns eines `{try}`-Blocks eine Ausnahme auftritt, wird der gesamte Block verworfen und das Rendering wird danach fortgesetzt:
 
 ```latte
 {try}
@@ -673,7 +687,7 @@ Wenn beim Rendern des `{try}` -Blocks eine Ausnahme auftritt, wird der gesamte B
 {/try}
 ```
 
-Der Inhalt der optionalen Klausel `{else}` wird nur gerendert, wenn eine Ausnahme auftritt:
+Der Inhalt in der optionalen `{else}`-Klausel wird nur gerendert, wenn eine Ausnahme auftritt:
 
 ```latte
 {try}
@@ -683,11 +697,11 @@ Der Inhalt der optionalen Klausel `{else}` wird nur gerendert, wenn eine Ausnahm
 		{/foreach}
 	</ul>
 	{else}
-	<p>Sorry, the tweets could not be loaded.</p>
+	<p>Es tut uns leid, die Tweets konnten nicht geladen werden.</p>
 {/try}
 ```
 
-Der Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden:
+Das Tag kann auch als [n:Attribut|syntax#n:attributes] verwendet werden:
 
 ```latte
 <ul n:try>
@@ -695,13 +709,13 @@ Der Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden:
 </ul>
 ```
 
-Es ist auch möglich, [einen eigenen Exception-Handler |develop#exception handler] für z.B. die Protokollierung zu definieren:
+Es ist auch möglich, einen eigenen [Handler für Ausnahmen|develop#exception handler] zu definieren, zum Beispiel für Logging-Zwecke.
 
 
 `{rollback}`
 ------------
 
-Der Block `{try}` kann auch manuell mit `{rollback}` angehalten und übersprungen werden. So müssen Sie nicht alle Eingabedaten im Voraus prüfen und können erst während des Renderings entscheiden, ob es sinnvoll ist, das Objekt zu rendern.
+Ein `{try}`-Block kann auch manuell mit `{rollback}` gestoppt und übersprungen werden. Dadurch müssen Sie nicht alle Eingabedaten im Voraus überprüfen und können während des Renderings entscheiden, dass Sie das Objekt überhaupt nicht rendern möchten:
 
 ```latte
 {try}
@@ -724,23 +738,23 @@ Variablen .[#toc-variables]
 `{var}` `{default}`
 -------------------
 
-Wir werden neue Variablen in der Vorlage mit dem Tag `{var}` erstellen:
+Neue Variablen werden im Template mit dem Tag `{var}` erstellt:
 
 ```latte
 {var $name = 'John Smith'}
 {var $age = 27}
 
-{* Mehrfache Deklaration *}
+{* Mehrfachdeklaration *}
 {var $name = 'John Smith', $age = 27}
 ```
 
-Das Tag `{default}` funktioniert ähnlich, mit dem Unterschied, dass es Variablen nur dann anlegt, wenn sie nicht existieren:
+Das Tag `{default}` funktioniert ähnlich, mit dem Unterschied, dass es Variablen nur dann erstellt, wenn sie nicht existieren:
 
 ```latte
 {default $lang = 'cs'}
 ```
 
-Sie können auch [Typen von Variablen |type-system] angeben. Im Moment sind sie informativ und Latte prüft sie nicht.
+Sie können auch [Variablentypen|type-system] angeben. Diese sind derzeit informativ und werden von Latte nicht überprüft.
 
 ```latte
 {var string $name = $article->getTitle()}
@@ -751,7 +765,7 @@ Sie können auch [Typen von Variablen |type-system] angeben. Im Moment sind sie
 `{parameters}`
 --------------
 
-So wie eine Funktion ihre Parameter deklariert, kann eine Vorlage ihre Variablen am Anfang deklarieren:
+So wie eine Funktion ihre Parameter deklariert, kann auch ein Template am Anfang seine Variablen deklarieren:
 
 ```latte
 {parameters
@@ -761,15 +775,15 @@ So wie eine Funktion ihre Parameter deklariert, kann eine Vorlage ihre Variablen
 }
 ```
 
-Die Variablen `$a` und `$b` ohne Standardwert haben automatisch den Standardwert `null`. Die deklarierten Typen sind immer noch informativ, und Latte überprüft sie nicht.
+Variablen `$a` und `$b` ohne angegebenen Standardwert haben automatisch den Standardwert `null`. Die deklarierten Typen sind derzeit informativ und werden von Latte nicht überprüft.
 
-Andere als die deklarierten Variablen werden nicht an die Vorlage übergeben. Dies ist ein Unterschied zum Tag `{default}`.
+Andere als die deklarierten Variablen werden nicht in das Template übertragen. Dies unterscheidet es vom Tag `{default}`.
 
 
 `{capture}`
 -----------
 
-Mit dem Tag `{capture}` können Sie die Ausgabe in einer Variablen erfassen:
+Erfasst die Ausgabe in eine Variable:
 
 ```latte
 {capture $var}
@@ -778,10 +792,10 @@ Mit dem Tag `{capture}` können Sie die Ausgabe in einer Variablen erfassen:
 </ul>
 {/capture}
 
-<p>Captured: {$var}</p>
+<p>Erfasst: {$var}</p>
 ```
 
-Der Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden, wie jeder paarweise Tag:
+Das Tag kann, wie jedes Paar-Tag, auch als [n:Attribut|syntax#n:Attribute] geschrieben werden:
 
 ```latte
 <ul n:capture="$var">
@@ -789,17 +803,17 @@ Der Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden, wie
 </ul>
 ```
 
-Die HTML-Ausgabe wird in der Variablen `$var` als `Latte\Runtime\Html` -Objekt gespeichert, um [unerwünschtes Escaping |develop#disabling-auto-escaping-of-variable] beim Drucken [zu vermeiden |develop#disabling-auto-escaping-of-variable].
+Die HTML-Ausgabe wird in der Variable `$var` als `Latte\Runtime\Html`-Objekt gespeichert, um [unerwünschtes Escaping |develop#disabling-auto-escaping-of-variable] beim Ausgeben zu verhindern.
 
 
-Andere .[#toc-others]
-=====================
+Sonstiges .[#toc-others]
+========================
 
 
 `{contentType}`
 ---------------
 
-Verwenden Sie das Tag, um anzugeben, welche Art von Inhalt die Vorlage darstellt. Die Optionen sind:
+Mit diesem Tag geben Sie an, welchen Inhaltstyp das Template darstellt. Die Optionen sind:
 
 - `html` (Standardtyp)
 - `xml`
@@ -808,16 +822,16 @@ Verwenden Sie das Tag, um anzugeben, welche Art von Inhalt die Vorlage darstellt
 - `calendar` (iCal)
 - `text`
 
-Die Verwendung dieses Befehls ist wichtig, weil er die [kontextabhängige Escape-Funktion |safety-first#context-aware-escaping] einstellt und nur dann kann Latte korrekt escapen. Zum Beispiel schaltet `{contentType xml}` in den XML-Modus, `{contentType text}` schaltet das Escapen komplett ab.
+Seine Verwendung ist wichtig, da es das [kontextsensitive Escaping |safety-first#context-aware-escaping] festlegt und nur so richtig escapen kann. Zum Beispiel schaltet `{contentType xml}` in den XML-Modus um, `{contentType text}` schaltet das Escaping komplett aus.
 
-Handelt es sich bei dem Parameter um einen MIME-Typ mit vollem Funktionsumfang, wie z. B. `application/xml`, so wird auch ein HTTP-Header `Content-Type` an den Browser gesendet:
+Wenn der Parameter ein vollständiger MIME-Typ ist, wie zum Beispiel `application/xml`, wird zusätzlich der HTTP-Header `Content-Type` an den Browser gesendet:
 
 ```latte
 {contentType application/xml}
 <?xml version="1.0"?>
 <rss version="2.0">
 	<channel>
-		<title>RSS feed</title>
+		<title>RSS-Feed</title>
 		<item>
 			...
 		</item>
@@ -829,19 +843,19 @@ Handelt es sich bei dem Parameter um einen MIME-Typ mit vollem Funktionsumfang,
 `{debugbreak}`
 --------------
 
-Gibt die Stelle an, an der die Codeausführung unterbrochen wird. Sie wird zu Debugging-Zwecken verwendet, damit der Programmierer die Laufzeitumgebung überprüfen und sicherstellen kann, dass der Code wie erwartet ausgeführt wird. Er unterstützt [Xdebug |https://xdebug.org]. Zusätzlich können Sie eine Bedingung angeben, unter der der Code unterbrochen werden soll.
+Markiert eine Stelle, an der die Programmausführung angehalten und der Debugger gestartet wird, damit der Programmierer die Laufzeitumgebung inspizieren und überprüfen kann, ob das Programm wie erwartet funktioniert. Es unterstützt [Xdebug |https://xdebug.org/]. Eine Bedingung kann hinzugefügt werden, die bestimmt, wann das Programm angehalten werden soll.
 
 ```latte
-{debugbreak}                {* bricht das Programm *}
+{debugbreak}                {* hält das Programm an *}
 
-{debugbreak $counter == 1}  {* bricht das Programm ab, wenn die Bedingung erfüllt ist *}
+{debugbreak $counter == 1}  {* hält das Programm an, wenn die Bedingung erfüllt ist *}
 ```
 
 
 `{do}`
 ------
 
-Führt den PHP-Code aus und gibt nichts aus. Wie bei allen anderen Tags ist der PHP-Code ein einzelner Ausdruck, siehe [PHP-Einschränkungen |syntax#PHP Limitations in Latte].
+Führt PHP-Code aus und gibt nichts aus. Wie bei allen anderen Tags mit PHP-Code handelt es sich um einen einzelnen Ausdruck, siehe [PHP-Einschränkungen |syntax#PHP Limitations in Latte].
 
 ```latte
 {do $num++}
@@ -854,80 +868,80 @@ Führt den PHP-Code aus und gibt nichts aus. Wie bei allen anderen Tags ist der
 Gibt eine Variable oder den aktuellen Kontext aus.
 
 ```latte
-{dump $name} {* gibt die Variable $name aus *}
+{dump $name} {* Gibt die Variable $name aus *}
 
-{dump}       {* gibt alle definierten Variablen aus *}
+{dump}       {* Gibt alle aktuell definierten Variablen aus *}
 ```
 
 .[caution]
-Erfordert das Paket [Tracy |tracy:].
+Erfordert die [Tracy|tracy:]-Bibliothek.
 
 
 `{php}`
 -------
 
-Ermöglicht die Ausführung von beliebigem PHP-Code. Das Tag muss mit der Erweiterung [RawPhpExtension |develop#RawPhpExtension] aktiviert werden.
+Ermöglicht die Ausführung beliebigen PHP-Codes. Das Tag muss durch die [RawPhpExtension |develop#RawPhpExtension] aktiviert werden.
 
 
 `{spaceless}`
 -------------
 
-Entfernt unnötige Leerzeichen. Ähnlich wie der [raumlose |filters#spaceless] Filter.
+Entfernt überflüssige Leerzeichen aus der Ausgabe. Funktioniert ähnlich wie der Filter [spaceless|filters#spaceless].
 
 ```latte
 {spaceless}
 	<ul>
-		<li>Hello</li>
+		<li>Hallo</li>
 	</ul>
 {/spaceless}
 ```
 
-Ausgaben:
+Erzeugt
 
 ```latte
-<ul> <li>Hello</li> </ul>
+<ul> <li>Hallo</li> </ul>
 ```
 
-Der Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden:
+Das Tag kann auch als [n:Attribut|syntax#n:attributes] geschrieben werden.
 
 
 `{syntax}`
 ----------
 
-Latten-Tags müssen nicht nur in geschweifte Klammern eingeschlossen werden. Sie können ein anderes Trennzeichen wählen, auch zur Laufzeit. Dies geschieht durch `{syntax…}`, wobei der Parameter sein kann:
+Latte-Tags müssen nicht nur durch einfache geschweifte Klammern begrenzt sein. Wir können auch einen anderen Begrenzer wählen, sogar zur Laufzeit. Dafür wird `{syntax …}` verwendet, wobei als Parameter angegeben werden kann:
 
 - double: `{{...}}`
-- off: deaktiviert die Latte-Tags vollständig
+- off: schaltet die Verarbeitung von Latte-Tags komplett aus
 
-Mit der Notation n:attribute können wir Latte nur für einen JavaScript-Block deaktivieren:
+Mit Hilfe von n:Attributen kann Latte zum Beispiel nur für einen JavaScript-Block ausgeschaltet werden:
 
 ```latte
 <script n:syntax="off">
-	var obj = {var: 123}; // this isn't a tag any more
+	var obj = {var: 123}; // dies ist kein Tag mehr
 </script>
 ```
 
-Latte kann sehr bequem innerhalb von JavaScript verwendet werden, man sollte nur Konstrukte wie in diesem Beispiel vermeiden, bei denen der Buchstabe unmittelbar auf `{` folgt, siehe [Latte innerhalb von JavaScript oder CSS |recipes#Latte inside JavaScript or CSS].
+Latte kann sehr bequem auch innerhalb von JavaScript verwendet werden, man muss nur Konstruktionen wie in diesem Beispiel vermeiden, bei denen direkt nach `{` ein Buchstabe folgt, siehe [Latte innerhalb von JavaScript oder CSS|recipes#Latte inside JavaScript or CSS].
 
-Wenn Sie Latte mit dem `{syntax off}` (d.h. Tag, nicht das n:-Attribut) ausschalten, werden alle Tags bis zu `{/syntax}` strikt ignoriert.
+Wenn Sie Latte mit `{syntax off}` ausschalten (d.h. mit einem Tag, nicht mit einem n:Attribut), wird es konsequent alle Tags bis `{/syntax}` ignorieren.
 
 
 {trace}
 -------
 
-Wirft eine `Latte\RuntimeException` Exception, deren Stack-Trace im Sinne der Templates ist. Anstatt Funktionen und Methoden aufzurufen, werden also Blöcke aufgerufen und Vorlagen eingefügt. Wenn Sie ein Tool zur übersichtlichen Darstellung von geworfenen Ausnahmen wie [Tracy |tracy:] verwenden, sehen Sie deutlich den Aufrufstapel, einschließlich aller übergebenen Argumente.
+Wirft eine `Latte\RuntimeException`, deren Stack-Trace im Geiste der Templates ist. Anstelle von Funktions- und Methodenaufrufen enthält er also Blockaufrufe und Template-Einbindungen. Wenn Sie ein Tool zur übersichtlichen Anzeige von geworfenen Ausnahmen verwenden, wie zum Beispiel [Tracy|tracy:], wird Ihnen der Call Stack einschließlich aller übergebenen Argumente übersichtlich angezeigt.
 
 
-HTML-Tag-Hilfsmittel .[#toc-html-tag-helpers]
-=============================================
+Helfer für HTML-Codierer .[#toc-html-tag-helpers]
+=================================================
 
 
 n:class
 -------
 
-Dank `n:class` ist es sehr einfach, das HTML-Attribut `class` genau so zu generieren, wie Sie es brauchen.
+Dank `n:class` können Sie sehr einfach das HTML-Attribut `class` genau nach Ihren Vorstellungen generieren.
 
-Beispiel: Ich möchte, dass das aktive Element die Klasse `active` hat:
+Beispiel: Ich brauche, dass das aktive Element die Klasse `active` hat:
 
 ```latte
 {foreach $items as $item}
@@ -935,7 +949,7 @@ Beispiel: Ich möchte, dass das aktive Element die Klasse `active` hat:
 {/foreach}
 ```
 
-Außerdem muss das erste Element die Klassen `first` und `main` haben:
+Und weiter, dass das erste Element die Klassen `first` und `main` hat:
 
 ```latte
 {foreach $items as $item}
@@ -943,7 +957,7 @@ Außerdem muss das erste Element die Klassen `first` und `main` haben:
 {/foreach}
 ```
 
-Und alle Elemente sollten die Klasse `list-item` haben:
+Und alle Elemente sollen die Klasse `list-item` haben:
 
 ```latte
 {foreach $items as $item}
@@ -951,13 +965,13 @@ Und alle Elemente sollten die Klasse `list-item` haben:
 {/foreach}
 ```
 
-Verblüffend einfach, nicht wahr?
+Unglaublich einfach, nicht wahr?
 
 
 n:attr
 ------
 
-Das Attribut `n:attr` kann beliebige HTML-Attribute mit der gleichen Eleganz wie [n:class |#n:class] erzeugen.
+Das Attribut `n:attr` kann mit der gleichen Eleganz wie [n:class|#n:class] beliebige HTML-Attribute generieren.
 
 ```latte
 {foreach $data as $item}
@@ -965,7 +979,7 @@ Das Attribut `n:attr` kann beliebige HTML-Attribute mit der gleichen Eleganz wie
 {/foreach}
 ```
 
-Abhängig von den zurückgegebenen Werten zeigt es z. B:
+Abhängig von den zurückgegebenen Werten wird zum Beispiel Folgendes ausgegeben:
 
 ```latte
 <input type="checkbox">
@@ -979,23 +993,25 @@ Abhängig von den zurückgegebenen Werten zeigt es z. B:
 n:tag
 -----
 
-Das Attribut `n:tag` kann den Namen eines HTML-Elements dynamisch ändern.
+Das Attribut `n:tag` kann den Namen des HTML-Elements dynamisch ändern.
 
 ```latte
 <h1 n:tag="$heading" class="main">{$title}</h1>
 ```
 
-Wenn `$heading === null`, wird das `<h1>` Tag ohne Änderung gedruckt. Andernfalls wird der Elementname in den Wert der Variablen geändert, so dass für `$heading === 'h3'` geschrieben wird:
+Wenn `$heading === null` ist, wird der Tag `<h1>` unverändert ausgegeben. Andernfalls wird der Name des Elements auf den Wert der Variable geändert, so dass für `$heading === 'h3'` Folgendes ausgegeben wird:
 
 ```latte
 <h3 class="main">...</h3>
 ```
 
+Da Latte ein sicheres Template-System ist, überprüft es, ob der neue Tag-Name gültig ist und keine unerwünschten oder schädlichen Werte enthält.
+
 
 n:ifcontent
 -----------
 
-Verhindert, dass ein leeres HTML-Element gedruckt wird, d.h. ein Element, das nichts als Leerraum enthält.
+Verhindert, dass ein leeres HTML-Element ausgegeben wird, d.h. ein Element, das nichts außer Leerzeichen enthält.
 
 ```latte
 <div>
@@ -1003,7 +1019,7 @@ Verhindert, dass ein leeres HTML-Element gedruckt wird, d.h. ein Element, das ni
 </div>
 ```
 
-Abhängig von den Werten der Variablen `$error` wird dies gedruckt:
+Gibt abhängig vom Wert der Variable `$error` aus:
 
 ```latte
 {* $error = '' *}
@@ -1017,10 +1033,10 @@ Abhängig von den Werten der Variablen `$error` wird dies gedruckt:
 ```
 
 
-Übersetzung .[#toc-translation]
-===============================
+Übersetzungen .[#toc-translation]
+=================================
 
-Damit die Übersetzungs-Tags funktionieren, müssen Sie den [Übersetzer ein richten|develop#TranslatorExtension]. Sie können auch den [`translate` |filters#translate] Filter für die Übersetzung verwenden.
+Damit die Übersetzungs-Tags funktionieren, muss der [Übersetzer aktiviert werden|develop#TranslatorExtension]. Für Übersetzungen können Sie auch den Filter [`translate`|filters#translate] verwenden.
 
 
 `{_...}`
@@ -1029,30 +1045,30 @@ Damit die Übersetzungs-Tags funktionieren, müssen Sie den [Übersetzer ein ric
 Übersetzt Werte in andere Sprachen.
 
 ```latte
-<a href="basket">{_'Basket'}</a>
+<a href="basket">{_'Warenkorb'}</a>
 <span>{_$item}</span>
 ```
 
-Es können auch andere Parameter an den Übersetzer übergeben werden:
+Dem Übersetzer können auch weitere Parameter übergeben werden:
 
 ```latte
-<a href="basket">{_'Basket', domain: order}</a>
+<a href="basket">{_'Warenkorb', domain: order}</a>
 ```
 
 
 `{translate}`
 -------------
 
-Překládá části šablony:
+Übersetzt Teile des Templates:
 
 ```latte
-<h1>{translate}Order{/translate}</h1>
+<h1>{translate}Bestellung{/translate}</h1>
 
 {translate domain: order}Lorem ipsum ...{/translate}
 ```
 
-Der Tag kann auch als [n:attribute |syntax#n:attributes] geschrieben werden, um das Innere des Elements zu übersetzen:
+Das Tag kann auch als [n:Attribut|syntax#n:attributes] geschrieben werden, um den Inhalt des Elements zu übersetzen:
 
 ```latte
-<h1 n:translate>Order</h1>
+<h1 n:translate>Bestellung</h1>
 ```
diff --git a/latte/de/template-inheritance.texy b/latte/de/template-inheritance.texy
index 4e365c106f..5e9a307295 100644
--- a/latte/de/template-inheritance.texy
+++ b/latte/de/template-inheritance.texy
@@ -132,7 +132,7 @@ Hier finden Sie einige Tipps für die Arbeit mit Layoutvererbung:
 
 - Wenn Sie `{layout}` in einer Vorlage verwenden, muss es das erste Vorlagen-Tag in dieser Vorlage sein.
 
-- Das Layout kann [automatisch gesucht |develop#automatic-layout-lookup] werden (wie bei [Präsentationen |application:templates#search-for-templates]). In diesem Fall, wenn die Vorlage kein Layout haben sollte, wird dies mit dem Tag `{layout none}` angezeigt.
+- Das Layout kann [automatisch gesucht |develop#automatic-layout-lookup] werden (wie bei [Präsentationen |application:templates#Template Lookup]). In diesem Fall, wenn die Vorlage kein Layout haben sollte, wird dies mit dem Tag `{layout none}` angezeigt.
 
 - Das Tag `{layout}` hat den Alias `{extends}`.
 
@@ -396,6 +396,14 @@ Sie können eine Variable oder einen beliebigen Ausdruck in PHP als Blocknamen v
 {/ifset}
 ```
 
+Die Existenz von Blöcken wird auch von der Funktion [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Tipps .[#toc-tips]
 ------------------
@@ -415,7 +423,7 @@ Hier finden Sie einige Tipps für die Arbeit mit Blöcken:
 Horizontale Wiederverwendung `{import}` .{toc: Horizontal Reuse}
 ================================================================
 
-Die horizontale Wiederverwendung ist ein dritter Wiederverwendbarkeits- und Vererbungsmechanismus in Latte. Sie ermöglicht es Ihnen, Blöcke aus anderen Vorlagen zu laden. Es ist vergleichbar mit dem Erstellen einer PHP-Datei mit Hilfsfunktionen oder einem Trait.
+Die horizontale Wiederverwendung ist der dritte Mechanismus für Wiederverwendung und Vererbung in Latte. Er ermöglicht das Laden von Blöcken aus anderen Vorlagen. Dies ist vergleichbar mit der Erstellung einer Datei mit Hilfsfunktionen in PHP und dem anschließenden Laden mit `require`.
 
 Obwohl die Vererbung von Vorlagenlayouts eine der leistungsfähigsten Funktionen von Latte ist, ist sie auf einfache Vererbung beschränkt - eine Vorlage kann nur eine andere Vorlage erweitern. Die horizontale Wiederverwendung ist eine Möglichkeit, Mehrfachvererbung zu erreichen.
 
@@ -447,7 +455,7 @@ Das Tag `{import}` sollte das erste Template-Tag nach `{layout}` sein. Der Vorla
 
 Sie können so viele `{import}` Anweisungen in einer Vorlage verwenden, wie Sie wollen. Wenn zwei importierte Vorlagen denselben Block definieren, gewinnt die erste Vorlage. Die höchste Priorität wird jedoch der Hauptvorlage eingeräumt, die jeden importierten Block überschreiben kann.
 
-Alle überschriebenen Blöcke können nach und nach eingebunden werden, indem sie als [übergeordneter Block |#parent block] eingefügt werden:
+Der Inhalt von überschriebenen Blöcken kann beibehalten werden, indem der Block wie ein [übergeordneter Block |#parent block] eingefügt wird:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/el/@left-menu.texy b/latte/el/@left-menu.texy
index b0beae99e9..cf27571bdd 100644
--- a/latte/el/@left-menu.texy
+++ b/latte/el/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Ξεκινώντας |Guide]
 - [Γιατί να χρησιμοποιήσετε πρότυπα; |why-use]
-- Έννοιες
+- Έννοιες ⚗️
 	- [Πρώτα η ασφάλεια |Safety First]
 	- [Κληρονομικότητα προτύπων |Template Inheritance]
 	- [Σύστημα τύπων |Type System]
 	- [Sandbox |Sandbox]
 
-- Για σχεδιαστές
+- Για σχεδιαστές 🎨
 	- [Σύνταξη |Syntax]
 	- [Ετικέτες |Tags]
 	- [Φίλτρα |Filters]
 	- [Λειτουργίες |Functions]
 	- [Συμβουλές και κόλπα |recipes]
 
-- Για προγραμματιστές
+- Για προγραμματιστές 🧮
 	- [Πρακτικές για προγραμματιστές |develop]
 	- [Επέκταση του Latte |Extending Latte]
 	- [Δημιουργία μιας επέκτασης |creating-extension]
 
-- [Βιβλίο μαγειρικής |cookbook/@home]
+- [Βιβλίο μαγειρικής 💡|cookbook/@home]
 	- [Μετανάστευση από το Twig |cookbook/migration-from-twig]
 	- [... περισσότερα |cookbook/@home]
 
diff --git a/latte/el/cookbook/@home.texy b/latte/el/cookbook/@home.texy
index ef2031d915..47590e6971 100644
--- a/latte/el/cookbook/@home.texy
+++ b/latte/el/cookbook/@home.texy
@@ -4,7 +4,9 @@
 .[perex]
 Παραδείγματα κωδικών και συνταγών για την εκτέλεση κοινών εργασιών με το Latte.
 
-- [Όλα όσα πάντα θέλατε να ξέρετε για το {iterateWhile} |iteratewhile]
+- [Κατευθυντήριες γραμμές για τον προγραμματιστή |/develop]
+- [Μεταβίβαση μεταβλητών σε πρότυπα |passing-variables]
+- [Όλα όσα πάντα θέλατε να ξέρετε για την ομαδοποίηση |grouping]
 - [Πώς να γράψετε ερωτήματα SQL στο Latte? |how-to-write-sql-queries-in-latte]
 - [Μετανάστευση από PHP |migration-from-php]
 - [Μετανάστευση από το Twig |migration-from-twig]
diff --git a/latte/el/cookbook/grouping.texy b/latte/el/cookbook/grouping.texy
new file mode 100644
index 0000000000..5ab45998e7
--- /dev/null
+++ b/latte/el/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Όλα όσα πάντα θέλατε να ξέρετε για την ομαδοποίηση
+**************************************************
+
+.[perex]
+Όταν εργάζεστε με δεδομένα σε πρότυπα, συναντάτε συχνά την ανάγκη να τα ομαδοποιήσετε ή να τα εμφανίσετε συγκεκριμένα σύμφωνα με συγκεκριμένα κριτήρια. Για το σκοπό αυτό, το Latte προσφέρει αρκετά ισχυρά εργαλεία.
+
+Το φίλτρο και η λειτουργία `|group` επιτρέπουν την αποτελεσματική ομαδοποίηση δεδομένων βάσει καθορισμένων κριτηρίων, ενώ το φίλτρο `|batch` διευκολύνει τον διαχωρισμό των δεδομένων σε σταθερές παρτίδες και η ετικέτα `{iterateWhile}` παρέχει τη δυνατότητα πιο σύνθετου ελέγχου του κύκλου με συνθήκες.
+Κάθε μία από αυτές τις ετικέτες προσφέρει συγκεκριμένες επιλογές για την εργασία με δεδομένα, καθιστώντας τις απαραίτητα εργαλεία για τη δυναμική και δομημένη εμφάνιση πληροφοριών σε πρότυπα Latte.
+
+
+Φίλτρο και λειτουργία `group` .[#toc-filter-and-function-group]
+===============================================================
+
+Φανταστείτε έναν πίνακα βάσης δεδομένων `items` με στοιχεία χωρισμένα σε κατηγορίες:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Apple
+| 2 | 1 | Μπανάνα
+| 3 | 2 | PHP
+| 4 | 3 | Πράσινο
+| 5 | 3 | Κόκκινο
+| 6 | 3 | Μπλε
+
+Μια απλή λίστα με όλα τα στοιχεία χρησιμοποιώντας ένα πρότυπο Latte θα έμοιαζε ως εξής:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Ωστόσο, αν θέλαμε τα αντικείμενα να οργανωθούν σε ομάδες ανά κατηγορία, θα πρέπει να τα χωρίσουμε έτσι ώστε κάθε κατηγορία να έχει τη δική της λίστα. Το αποτέλεσμα θα έμοιαζε τότε ως εξής:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Η εργασία μπορεί να επιλυθεί εύκολα και κομψά με τη χρήση του `|group`. Καθορίζουμε το `categoryId` ως παράμετρο, που σημαίνει ότι τα στοιχεία θα χωριστούν σε μικρότερους πίνακες με βάση την τιμή `$item->categoryId` (αν το `$item` ήταν ένας πίνακας, θα χρησιμοποιούσαμε `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Το φίλτρο μπορεί επίσης να χρησιμοποιηθεί ως συνάρτηση στο Latte, δίνοντάς μας μια εναλλακτική σύνταξη: `{foreach group($items, categoryId) ...}`.
+
+Αν θέλετε να ομαδοποιήσετε στοιχεία σύμφωνα με πιο σύνθετα κριτήρια, μπορείτε να χρησιμοποιήσετε μια συνάρτηση στην παράμετρο φίλτρο. Για παράδειγμα, η ομαδοποίηση στοιχείων με βάση το μήκος του ονόματός τους θα έμοιαζε ως εξής:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Είναι σημαντικό να σημειωθεί ότι το `$categoryItems` δεν είναι ένας κανονικός πίνακας, αλλά ένα αντικείμενο που συμπεριφέρεται σαν ένας επαναλήπτης. Για να αποκτήσετε πρόσβαση στο πρώτο στοιχείο της ομάδας, μπορείτε να χρησιμοποιήσετε την εντολή [`first()` |latte:functions#first] συνάρτηση.
+
+Αυτή η ευελιξία στην ομαδοποίηση δεδομένων καθιστά το `group` ένα εξαιρετικά χρήσιμο εργαλείο για την παρουσίαση δεδομένων σε πρότυπα Latte.
+
+
+Ενσωματωμένοι βρόχοι .[#toc-nested-loops]
+-----------------------------------------
+
+Ας υποθέσουμε ότι έχουμε έναν πίνακα βάσης δεδομένων με μια άλλη στήλη `subcategoryId` που ορίζει υποκατηγορίες για κάθε στοιχείο. Θέλουμε να εμφανίσουμε κάθε κύρια κατηγορία σε μια ξεχωριστή `<ul>` λίστα και κάθε υποκατηγορία σε μια ξεχωριστή εμφωλευμένη `<ol>` λίστα:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Σύνδεση με τη βάση δεδομένων Nette .[#toc-connection-with-nette-database]
+-------------------------------------------------------------------------
+
+Ας δείξουμε πώς μπορείτε να χρησιμοποιήσετε αποτελεσματικά την ομαδοποίηση δεδομένων σε συνδυασμό με τη Nette Database. Ας υποθέσουμε ότι εργαζόμαστε με τον πίνακα `items` από το αρχικό παράδειγμα, ο οποίος συνδέεται μέσω της στήλης `categoryId` με αυτόν τον πίνακα `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Φρούτα |
+| 2 | Γλώσσες |
+| 3 | Χρώματα |
+
+Φορτώνουμε δεδομένα από τον πίνακα `items` χρησιμοποιώντας την εντολή `$items = $db->table('items')` του Nette Database Explorer. Κατά την επανάληψη αυτών των δεδομένων, έχουμε τη δυνατότητα όχι μόνο να έχουμε πρόσβαση σε χαρακτηριστικά όπως τα `$item->name` και `$item->categoryId`, αλλά χάρη στη σύνδεση με τον πίνακα `categories`, και στη σχετική γραμμή του πίνακα μέσω του `$item->category`. Αυτή η σύνδεση μπορεί να επιδείξει ενδιαφέρουσες χρήσεις:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Στην περίπτωση αυτή, χρησιμοποιούμε το φίλτρο `|group` για να ομαδοποιήσουμε με βάση τη συνδεδεμένη γραμμή `$item->category`, όχι μόνο με βάση τη στήλη `categoryId`. Αυτό μας δίνει το `ActiveRow` της συγκεκριμένης κατηγορίας στο κλειδί της μεταβλητής, επιτρέποντάς μας να εμφανίσουμε απευθείας το όνομά της χρησιμοποιώντας το `{$category->name}`. Αυτό είναι ένα πρακτικό παράδειγμα για το πώς η ομαδοποίηση μπορεί να απλοποιήσει τα πρότυπα και να διευκολύνει το χειρισμό των δεδομένων.
+
+
+Φίλτρο `|batch` .[#toc-filter-batch]
+====================================
+
+Το φίλτρο σας επιτρέπει να χωρίσετε μια λίστα στοιχείων σε ομάδες με προκαθορισμένο αριθμό στοιχείων. Αυτό το φίλτρο είναι ιδανικό για περιπτώσεις όπου θέλετε να παρουσιάσετε δεδομένα σε πολλές μικρότερες ομάδες, για παράδειγμα, για καλύτερη σαφήνεια ή οπτική οργάνωση στη σελίδα.
+
+Φανταστείτε ότι έχουμε μια λίστα με στοιχεία και θέλουμε να τα εμφανίσουμε σε λίστες, κάθε μία από τις οποίες θα περιέχει το πολύ τρία στοιχεία. Η χρήση του φίλτρου `|batch` είναι πολύ πρακτική σε μια τέτοια περίπτωση:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+Σε αυτό το παράδειγμα, η λίστα `$items` χωρίζεται σε μικρότερες ομάδες, με κάθε ομάδα (`$batch`) να περιέχει μέχρι τρία στοιχεία. Κάθε ομάδα εμφανίζεται στη συνέχεια σε ξεχωριστή `<ul>` λίστα.
+
+Εάν η τελευταία ομάδα δεν περιέχει αρκετά στοιχεία για να φτάσει τον επιθυμητό αριθμό, η δεύτερη παράμετρος του φίλτρου σας επιτρέπει να ορίσετε με τι θα συμπληρωθεί αυτή η ομάδα. Αυτό είναι ιδανικό για την αισθητική ευθυγράμμιση στοιχείων όπου μια ελλιπής σειρά μπορεί να φαίνεται ακατάστατη.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Ετικέτα `{iterateWhile}` .[#toc-tag-iteratewhile]
+=================================================
+
+Θα παρουσιάσουμε τις ίδιες εργασίες που αντιμετωπίσαμε με το φίλτρο `|group` χρησιμοποιώντας την ετικέτα `{iterateWhile}`. Η κύρια διαφορά μεταξύ των δύο προσεγγίσεων είναι ότι το `group` επεξεργάζεται και ομαδοποιεί πρώτα όλα τα δεδομένα εισόδου, ενώ το `{iterateWhile}` ελέγχει την πρόοδο των κύκλων με συνθήκες, οπότε η επανάληψη γίνεται διαδοχικά.
+
+Αρχικά, σχεδιάζουμε έναν πίνακα με κατηγορίες χρησιμοποιώντας το iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Ενώ η ετικέτα `{foreach}` σηματοδοτεί το εξωτερικό μέρος του κύκλου, δηλαδή τη σχεδίαση λιστών για κάθε κατηγορία, η ετικέτα `{iterateWhile}` σηματοδοτεί το εσωτερικό μέρος, δηλαδή τα μεμονωμένα στοιχεία.
+Η συνθήκη στην ετικέτα end λέει ότι η επανάληψη θα συνεχιστεί εφόσον το τρέχον και το επόμενο στοιχείο ανήκουν στην ίδια κατηγορία (`$iterator->nextValue` είναι το [επόμενο στοιχείο |/tags#$iterator]).
+
+Αν η συνθήκη πληρούταν πάντα, όλα τα στοιχεία θα σχεδιάζονταν στον εσωτερικό κύκλο:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Το αποτέλεσμα θα μοιάζει με αυτό:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Ποια είναι η χρήση του iterateWhile με αυτόν τον τρόπο; Όταν ο πίνακας είναι άδειος και δεν περιέχει στοιχεία, δεν υπάρχει κενό `<ul></ul>` εκτυπώνεται.
+
+Αν καθορίσουμε τη συνθήκη στην εναρκτήρια ετικέτα `{iterateWhile}`, η συμπεριφορά αλλάζει: η συνθήκη (και η μετάβαση στο επόμενο στοιχείο) εκτελείται στην αρχή του εσωτερικού κύκλου, όχι στο τέλος.
+Έτσι, ενώ εισάγετε πάντα το `{iterateWhile}` χωρίς συνθήκες, εισάγετε το `{iterateWhile $cond}` μόνο όταν ικανοποιείται η συνθήκη `$cond`. Και ταυτόχρονα, το επόμενο στοιχείο εγγράφεται στο `$item`.
+
+Αυτό είναι χρήσιμο, για παράδειγμα, σε μια κατάσταση όπου θέλουμε να αποδώσουμε το πρώτο στοιχείο σε κάθε κατηγορία με διαφορετικό τρόπο, ως εξής:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Τροποποιούμε τον αρχικό κώδικα έτσι ώστε να αποδίδουμε πρώτα το πρώτο στοιχείο και στη συνέχεια στον εσωτερικό κύκλο `{iterateWhile}` να αποδίδουμε τα υπόλοιπα στοιχεία της ίδιας κατηγορίας:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Μέσα σε έναν κύκλο, μπορούμε να δημιουργήσουμε πολλαπλούς εσωτερικούς βρόχους και μάλιστα να τους φωλιάσουμε. Με αυτόν τον τρόπο θα μπορούσαν να ομαδοποιηθούν, για παράδειγμα, υποκατηγορίες.
+
+Ας υποθέσουμε ότι ο πίνακας έχει άλλη μια στήλη `subcategoryId`, και εκτός από το ότι κάθε κατηγορία βρίσκεται σε ξεχωριστή `<ul>`, κάθε υποκατηγορία σε μια ξεχωριστή `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/el/cookbook/iteratewhile.texy b/latte/el/cookbook/iteratewhile.texy
deleted file mode 100644
index 034813fb73..0000000000
--- a/latte/el/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Όλα όσα πάντα θέλατε να ξέρετε για το {iterateWhile}
-****************************************************
-
-.[perex]
-Η ετικέτα `{iterateWhile}` είναι κατάλληλη για διάφορα τεχνάσματα σε κύκλους foreach.
-
-Ας υποθέσουμε ότι έχουμε τον ακόλουθο πίνακα της βάσης δεδομένων, όπου τα στοιχεία χωρίζονται σε κατηγορίες:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Φυσικά, η σχεδίαση στοιχείων σε έναν βρόχο foreach ως λίστα είναι εύκολη:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Τι να κάνετε όμως αν θέλετε να αποδώσετε κάθε κατηγορία σε ξεχωριστή λίστα; Με άλλα λόγια, πώς να λύσετε το έργο της ομαδοποίησης στοιχείων από μια γραμμική λίστα σε έναν κύκλο foreach. Η έξοδος θα πρέπει να μοιάζει κάπως έτσι:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Θα σας δείξουμε πόσο εύκολα και κομψά μπορεί να επιλυθεί το έργο με το iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Ενώ το `{foreach}` σηματοδοτεί το εξωτερικό μέρος του κύκλου, δηλαδή την κατάρτιση των λιστών για κάθε κατηγορία, οι ετικέτες `{iterateWhile}` υποδεικνύουν το εσωτερικό μέρος, δηλαδή τα μεμονωμένα στοιχεία.
-Η συνθήκη στην ετικέτα end λέει ότι η επανάληψη θα συνεχιστεί εφόσον το τρέχον και το επόμενο στοιχείο ανήκουν στην ίδια κατηγορία (`$iterator->nextValue` είναι το [επόμενο στοιχείο |/tags#$iterator]).
-
-Εάν η συνθήκη ικανοποιείται πάντα, τότε όλα τα στοιχεία σχεδιάζονται στον εσωτερικό κύκλο:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Το αποτέλεσμα θα μοιάζει με αυτό:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Σε τι χρησιμεύει μια τέτοια χρήση της iterateWhile; Σε τι διαφέρει από τη λύση που δείξαμε στην αρχή αυτού του σεμιναρίου; Η διαφορά είναι ότι αν ο πίνακας είναι άδειος και δεν περιέχει κανένα στοιχείο, δεν θα αποδώσει κενό `<ul></ul>`.
-
-
-Λύση χωρίς `{iterateWhile}` .[#toc-solution-without-iteratewhile]
------------------------------------------------------------------
-
-Αν λύναμε την ίδια εργασία με εντελώς βασικές κατασκευές συστημάτων προτύπων, για παράδειγμα σε Twig, Blade ή καθαρή PHP, η λύση θα έμοιαζε κάπως έτσι:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* η κατηγορία έχει αλλάξει *}
-
-		{* κλείνουμε το προηγούμενο <ul>, αν δεν είναι το πρώτο στοιχείο *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* θα ανοίξουμε μια νέα λίστα *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* κλείνουμε την προηγούμενη λίστα *}
-	</ul>
-{/if}
-```
-
-Ωστόσο, αυτός ο κώδικας είναι ακατανόητος και μη διαισθητικός. Η σύνδεση μεταξύ των ετικετών HTML που ανοίγουν και κλείνουν δεν είναι καθόλου σαφής. Δεν είναι σαφές με την πρώτη ματιά αν υπάρχει κάποιο λάθος. Και απαιτεί βοηθητικές μεταβλητές όπως το `$prevCatId`.
-
-Αντίθετα, η λύση με το `{iterateWhile}` είναι καθαρή, σαφής, δεν χρειάζεται βοηθητικές μεταβλητές και είναι αλάνθαστη.
-
-
-Προϋπόθεση στην ετικέτα κλεισίματος .[#toc-condition-in-the-closing-tag]
-------------------------------------------------------------------------
-
-Αν καθορίσουμε μια συνθήκη στην ετικέτα ανοίγματος `{iterateWhile}`, η συμπεριφορά αλλάζει: η συνθήκη (και η προώθηση στο επόμενο στοιχείο) εκτελείται στην αρχή του εσωτερικού κύκλου, όχι στο τέλος.
-Έτσι, ενώ το `{iterateWhile}` χωρίς συνθήκη εισάγεται πάντα, το `{iterateWhile $cond}` εισάγεται μόνο όταν ικανοποιείται η συνθήκη `$cond`. Ταυτόχρονα, το ακόλουθο στοιχείο εγγράφεται στο `$item`.
-
-Αυτό είναι χρήσιμο, για παράδειγμα, σε μια κατάσταση όπου θέλετε να αποδώσετε το πρώτο στοιχείο σε κάθε κατηγορία με διαφορετικό τρόπο, όπως π.χ:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Ας τροποποιήσουμε τον αρχικό κώδικα, σχεδιάζουμε το πρώτο στοιχείο και στη συνέχεια πρόσθετα στοιχεία από την ίδια κατηγορία στον εσωτερικό βρόχο `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Φωλιασμένοι βρόχοι .[#toc-nested-loops]
----------------------------------------
-
-Μπορούμε να δημιουργήσουμε πολλαπλούς εσωτερικούς βρόχους σε έναν κύκλο και μάλιστα να τους φωλιάσουμε. Με αυτόν τον τρόπο, για παράδειγμα, θα μπορούσαν να ομαδοποιηθούν οι υποκατηγορίες.
-
-Ας υποθέσουμε ότι υπάρχει μια άλλη στήλη στον πίνακα `subCatId` και εκτός από το ότι κάθε κατηγορία βρίσκεται σε ξεχωριστή `<ul>`, κάθε υποκατηγορία θα βρίσκεται σε μια ξεχωριστή `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Φίλτρο |batch .[#toc-filter-batch]
-----------------------------------
-
-Η ομαδοποίηση των γραμμικών στοιχείων παρέχεται επίσης από ένα φίλτρο `batch`, σε παρτίδες με σταθερό αριθμό στοιχείων:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Μπορεί να αντικατασταθεί με το iterateWhile ως εξής:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/el/cookbook/passing-variables.texy b/latte/el/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..381a209b1f
--- /dev/null
+++ b/latte/el/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Μεταβίβαση μεταβλητών μεταξύ προτύπων
+*************************************
+
+Αυτός ο οδηγός εξηγεί πώς μεταβιβάζονται μεταβλητές μεταξύ προτύπων στο Latte χρησιμοποιώντας διάφορες ετικέτες όπως `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` και άλλες. Θα μάθετε επίσης πώς να εργάζεστε με μεταβλητές στις ετικέτες `{block}` και `{define}`, καθώς και το σκοπό της ετικέτας `{parameters}`.
+
+
+Τύποι μεταβλητών .[#toc-types-of-variables]
+-------------------------------------------
+Οι μεταβλητές στο Latte μπορούν να χωριστούν σε τρεις κατηγορίες με βάση τον τρόπο και τον τόπο ορισμού τους:
+
+**Μεταβλητές εισόδου** είναι αυτές που περνούν στο πρότυπο από έξω, για παράδειγμα, από ένα PHP script ή χρησιμοποιώντας μια ετικέτα όπως το `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Περιβάλλουσες μεταβλητές** είναι οι μεταβλητές που υπάρχουν στη θέση μιας συγκεκριμένης ετικέτας. Σε αυτές περιλαμβάνονται όλες οι μεταβλητές εισόδου και άλλες μεταβλητές που δημιουργούνται με τη χρήση ετικετών όπως `{var}`, `{default}`, ή μέσα σε έναν βρόχο `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Εμφανείς μεταβλητές** είναι εκείνες που προσδιορίζονται απευθείας μέσα σε μια ετικέτα και αποστέλλονται στο πρότυπο-στόχο.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Η ετικέτα `{block}` χρησιμοποιείται για τον ορισμό επαναχρησιμοποιήσιμων μπλοκ κώδικα που μπορούν να προσαρμοστούν ή να επεκταθούν σε κληρονομημένα πρότυπα. Οι περιβάλλουσες μεταβλητές που ορίζονται πριν από το μπλοκ είναι διαθέσιμες μέσα στο μπλοκ, αλλά οποιεσδήποτε αλλαγές στις μεταβλητές αντικατοπτρίζονται μόνο μέσα σε αυτό το μπλοκ.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Η ετικέτα `{define}` χρησιμοποιείται για τη δημιουργία μπλοκ που εμφανίζονται μόνο όταν καλούνται με τη χρήση του `{include}`. Οι μεταβλητές που είναι διαθέσιμες μέσα σε αυτά τα μπλοκ εξαρτώνται από το αν έχουν καθοριστεί παράμετροι στον ορισμό. Εάν καθοριστούν παράμετροι, μόνο αυτές οι παράμετροι είναι προσβάσιμες. Εάν όχι, είναι προσβάσιμες όλες οι μεταβλητές εισόδου του προτύπου όπου ορίζονται τα μπλοκ.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Η ετικέτα `{parameters}` χρησιμοποιείται για τη ρητή δήλωση των αναμενόμενων μεταβλητών εισόδου στην αρχή του προτύπου. Με αυτόν τον τρόπο, μπορείτε εύκολα να τεκμηριώσετε τις αναμενόμενες μεταβλητές και τους τύπους δεδομένων τους. Είναι επίσης δυνατό να ορίσετε προεπιλεγμένες τιμές.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Η ετικέτα `{include file}` χρησιμοποιείται για την εισαγωγή ενός ολόκληρου προτύπου. Αυτό το πρότυπο περνάει τόσο τις μεταβλητές εισόδου του προτύπου όπου χρησιμοποιείται η ετικέτα όσο και ρητά καθορισμένες μεταβλητές. Ωστόσο, το πρότυπο-στόχος μπορεί να περιορίσει το πεδίο εφαρμογής χρησιμοποιώντας το `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Κατά την εισαγωγή ενός μπλοκ που ορίζεται στο ίδιο πρότυπο, όλες οι περιβάλλουσες και ρητά καθορισμένες μεταβλητές μεταβιβάζονται σε αυτό:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+Σε αυτό το παράδειγμα, οι μεταβλητές `$name` και `$age` μεταβιβάζονται στο μπλοκ `blockName`. Η ίδια συμπεριφορά ισχύει και για το `{include parent}`.
+
+Κατά την εισαγωγή ενός μπλοκ από άλλο πρότυπο, μεταβιβάζονται μόνο οι μεταβλητές εισόδου και οι ρητά καθορισμένες μεταβλητές. Οι περιβάλλουσες μεταβλητές δεν είναι αυτόματα διαθέσιμες.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` ή `{extends}`
+------------------------
+Αυτές οι ετικέτες ορίζουν μια διάταξη στην οποία μεταβιβάζονται οι μεταβλητές εισόδου του παιδικού προτύπου και οι μεταβλητές που δημιουργούνται στον κώδικα πριν από τα μπλοκ:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Πρότυπο `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Η ετικέτα `{embed}` είναι παρόμοια με την ετικέτα `{include}`, αλλά επιτρέπει την ενσωμάτωση μπλοκ στο πρότυπο. Σε αντίθεση με το `{include}`, μεταβιβάζονται μόνο ρητά δηλωμένες μεταβλητές:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+Σε αυτό το παράδειγμα, το πρότυπο `menu.latte` έχει πρόσβαση μόνο στη μεταβλητή `$items`.
+
+Αντίθετα, τα μπλοκ μέσα στο `{embed}` έχουν πρόσβαση σε όλες τις περιβάλλουσες μεταβλητές:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Η ετικέτα `{import}` χρησιμοποιείται για τη φόρτωση μπλοκ από άλλα πρότυπα. Στα εισαγόμενα μπλοκ μεταβιβάζονται τόσο οι μεταβλητές εισόδου όσο και οι ρητά δηλωμένες μεταβλητές.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Η ετικέτα `{sandbox}` απομονώνει το πρότυπο για ασφαλή επεξεργασία. Οι μεταβλητές μεταβιβάζονται αποκλειστικά ρητά.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/el/creating-extension.texy b/latte/el/creating-extension.texy
index 2c38209526..b26c254ea3 100644
--- a/latte/el/creating-extension.texy
+++ b/latte/el/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// μια συνάρτηση ανάλυσης που απλά δημιουργεί έναν κόμβο προς το παρόν
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Εάν δημιουργείτε μια νέα ετικέτα για το Latte, είναι σκόπιμο να δημιουργήσετε μια ειδική κλάση κόμβου για αυτήν, η οποία θα την αντιπροσωπεύει στο δέντρο AST (βλέπε την κλάση `ForeachNode` στο παραπάνω παράδειγμα). Σε ορισμένες περιπτώσεις, μπορεί να βρείτε χρήσιμη την τετριμμένη βοηθητική κλάση κόμβου [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], η οποία σας επιτρέπει να περάσετε το σώμα της μεθόδου `print()` και τη λίστα των κόμβων που γίνονται προσβάσιμοι από τη μέθοδο `getIterator()` ως παραμέτρους του κατασκευαστή:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Μεταγλωττιστής περνάει .[#toc-compiler-passes]
 ==============================================
 
diff --git a/latte/el/develop.texy b/latte/el/develop.texy
index 5d380b79ba..c0e671a9be 100644
--- a/latte/el/develop.texy
+++ b/latte/el/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Τοπική τοποθεσία .[#toc-locale]{data-version:3.0.18}
+====================================================
+
+Το Latte σας επιτρέπει να ορίσετε την τοπική γλώσσα, η οποία επηρεάζει τη μορφοποίηση των αριθμών, των ημερομηνιών και την ταξινόμηση. Ορίζεται χρησιμοποιώντας τη μέθοδο `setLocale()`. Το αναγνωριστικό locale ακολουθεί το πρότυπο ετικέτας γλώσσας IETF, το οποίο χρησιμοποιεί την επέκταση PHP `intl`. Αποτελείται από έναν κωδικό γλώσσας και ενδεχομένως έναν κωδικό χώρας, για παράδειγμα, `en_US` για τα αγγλικά στις Ηνωμένες Πολιτείες, `de_DE` για τα γερμανικά στη Γερμανία, κ.λπ.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Η ρύθμιση locale επηρεάζει τα φίλτρα [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] και [bytes |filters#bytes].
+
+.[note]
+Απαιτεί την επέκταση PHP `intl`. Η ρύθμιση στο Latte δεν επηρεάζει την παγκόσμια ρύθμιση τοπικής γλώσσας στην PHP.
+
+
 Αυστηρή λειτουργία .[#toc-strict-mode]{data-version:3.0.8}
 ==========================================================
 
@@ -274,16 +290,25 @@ vendor/bin/latte-lint <path>
 // εισάγετε την πραγματική διαδρομή προς το αρχείο autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// προσθέστε μεμονωμένες επεκτάσεις εδώ
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// προσθέστε τις μεμονωμένες επεκτάσεις σας εδώ
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Εναλλακτικά, μπορείτε να περάσετε το δικό σας αντικείμενο `Latte\Engine` στον Linter:
+
+```php
+$latte = new Latte\Engine;
+// εδώ ρυθμίζουμε το αντικείμενο $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Φόρτωση προτύπων από μια συμβολοσειρά .[#toc-loading-templates-from-a-string]
 =============================================================================
diff --git a/latte/el/extending-latte.texy b/latte/el/extending-latte.texy
index 8a663c4b09..e6170a3abe 100644
--- a/latte/el/extending-latte.texy
+++ b/latte/el/extending-latte.texy
@@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 
 Φυσικά, η συνάρτηση που αναπαριστά το φίλτρο μπορεί να δεχτεί οποιονδήποτε αριθμό παραμέτρων, ενώ υποστηρίζονται και μεταβλητές παράμετροι.
 
+Αν το φίλτρο επιστρέφει ένα αλφαριθμητικό σε HTML, μπορείτε να το επισημάνετε έτσι ώστε το Latte να μην το αποφεύγει αυτόματα (και επομένως διπλά). Με αυτόν τον τρόπο αποφεύγεται η ανάγκη προσδιορισμού του `|noescape` στο πρότυπο.
+Ο ευκολότερος τρόπος είναι να τυλίξετε τη συμβολοσειρά σε ένα αντικείμενο `Latte\Runtime\Html`, ο άλλος τρόπος είναι τα [φίλτρα πλαισίου |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+Στην περίπτωση αυτή, το φίλτρο πρέπει να διασφαλίζει τη σωστή διαφυγή των δεδομένων.
+
 
 Φίλτρα που χρησιμοποιούν την κλάση .[#toc-filters-using-the-class]
 ------------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// αλλάζουμε τον τύπο περιεχομένου σε HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/el/filters.texy b/latte/el/filters.texy
index ac76626627..65900b85eb 100644
--- a/latte/el/filters.texy
+++ b/latte/el/filters.texy
@@ -11,14 +11,16 @@
 | `bytes` | [μορφοποιεί το μέγεθος σε bytes |#bytes]
 | `clamp` | [συγκρατεί την τιμή στο εύρος |#clamp]
 | `dataStream` | [Μετατροπή πρωτοκόλλου URI δεδομένων |#datastream]
-| `date` | [μορφοποίηση ημερομηνίας |#date]
+| `date` | [μορφοποιεί την ημερομηνία και την ώρα |#date]
 | `explode` | [Διαχωρίζει μια συμβολοσειρά με το δεδομένο διαχωριστικό |#explode]
 | `first` | [επιστρέφει το πρώτο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς |#first]
+| `group` | [ομαδοποιεί δεδομένα σύμφωνα με διάφορα κριτήρια |#group]
 | `implode` | [συνδέει έναν πίνακα με μια συμβολοσειρά |#implode]
 | `indent` | [εσοχή του κειμένου από αριστερά με αριθμό tabs |#indent]
 | `join` | [ενώνει έναν πίνακα σε μια συμβολοσειρά |#implode]
 | `last` | [επιστρέφει το τελευταίο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς |#last]
 | `length` | [επιστρέφει το μήκος μιας συμβολοσειράς ή ενός πίνακα |#length]
+| `localDate` | [μορφοποιεί την ημερομηνία και την ώρα σύμφωνα με την τοπική γλώσσα |#localDate]
 | `number` | [μορφοποίηση αριθμού |#number]
 | `padLeft` | [συμπληρώνει τη συμβολοσειρά στο συγκεκριμένο μήκος από αριστερά |#padLeft]
 | `padRight` | [συμπληρώνει τη συμβολοσειρά στο δεδομένο μήκος από τα δεξιά |#padRight]
@@ -118,8 +120,8 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Φίλτρο που απλοποιεί την καταχώριση γραμμικών δεδομένων με τη μορφή πίνακα. Επιστρέφει έναν πίνακα με τον δεδομένο αριθμό στοιχείων. Εάν δώσετε μια δεύτερη παράμετρο, αυτή χρησιμοποιείται για να συμπληρώσει τα στοιχεία που λείπουν στην τελευταία γραμμή.
 
 ```latte
@@ -152,6 +154,8 @@ batch(int length, mixed item): array .[filter]
 </table>
 ```
 
+Βλέπε επίσης [group |#group] και ετικέτα [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ breakLines .[filter]
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Διαμορφώνει ένα μέγεθος σε bytes σε μορφή αναγνώσιμη από τον άνθρωπο.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Διαμορφώνει το μέγεθος σε bytes σε μορφή αναγνώσιμη από τον άνθρωπο. Εάν έχει οριστεί η [τοπική γλώσσα |develop#locale], χρησιμοποιούνται τα αντίστοιχα διαχωριστικά δεκαδικών και χιλιάδων.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ bytes(int precision = 2) .[filter]
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Στρογγυλοποιεί έναν αριθμό με δεδομένη ακρίβεια.
 
 ```latte
@@ -203,8 +207,8 @@ checkUrl .[filter]
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Εκτυπώνει:
@@ -217,8 +221,8 @@ checkUrl .[filter]
 Βλέπε επίσης [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Επιστρέφει την τιμή που έχει περιοριστεί στο συνολικό εύρος των min και max.
 
 ```latte
@@ -228,14 +232,14 @@ clamp(int|float min, int|float max) .[filter]
 Υπάρχει επίσης ως [συνάρτηση |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Μετατρέπει το περιεχόμενο σε σχήμα URI δεδομένων. Μπορεί να χρησιμοποιηθεί για την εισαγωγή εικόνων σε HTML ή CSS χωρίς την ανάγκη σύνδεσης εξωτερικών αρχείων.
 
 Ας έχουμε μια εικόνα σε μια μεταβλητή `$img = Image::fromFile('obrazek.gif')`, τότε
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Εκτυπώνει για παράδειγμα:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Απαιτεί επέκταση PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Επιστρέφει μια ημερομηνία στη δεδομένη μορφή χρησιμοποιώντας τις επιλογές των συναρτήσεων PHP [php:strftime] ή [php:date]. Το φίλτρο λαμβάνει μια ημερομηνία ως χρονοσφραγίδα UNIX, συμβολοσειρά ή αντικείμενο τύπου `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Διαμορφώνει την ημερομηνία και την ώρα σύμφωνα με τη μάσκα που χρησιμοποιείται από τη συνάρτηση της PHP [php:date]. Το φίλτρο δέχεται την ημερομηνία σε μορφή χρονοσφραγίδας UNIX, ως συμβολοσειρά ή ως αντικείμενο `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Βλέπε επίσης [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ escapeUrl .[filter]
 Βλέπε επίσης [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Διαχωρίζει μια συμβολοσειρά με βάση το δεδομένο διαχωριστικό και επιστρέφει έναν πίνακα συμβολοσειρών. Ψευδώνυμο για το `split`.
 
 ```latte
@@ -306,8 +311,8 @@ first .[filter]
 Βλέπε επίσης [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Στρογγυλοποιεί έναν αριθμό με δεδομένη ακρίβεια.
 
 ```latte
@@ -330,8 +335,27 @@ firstUpper .[filter]
 Βλέπε επίσης [capitalize |#capitalize], [lower |#lower], [upper |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Το φίλτρο ομαδοποιεί τα δεδομένα σύμφωνα με διάφορα κριτήρια.
+
+Σε αυτό το παράδειγμα, οι γραμμές του πίνακα ομαδοποιούνται με βάση τη στήλη `categoryId`. Η έξοδος είναι ένας πίνακας πινάκων όπου το κλειδί είναι η τιμή στη στήλη `categoryId`. Διαβάστε τις [λεπτομερείς οδηγίες |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Δείτε επίσης [batch |#batch], τη συνάρτηση [group |functions#group] και την ετικέτα [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Επιστρέφει μια συμβολοσειρά που είναι η συνένωση των συμβολοσειρών του πίνακα. Ψευδώνυμο για το `join`.
 
 ```latte
@@ -346,8 +370,8 @@ implode(string glue = '') .[filter]
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Παρεμβάλλει ένα κείμενο από τα αριστερά κατά ένα δεδομένο αριθμό tabs ή άλλων χαρακτήρων που καθορίζουμε στο δεύτερο προαιρετικό όρισμα. Οι κενές γραμμές δεν εσοδεύονται.
 
 ```latte
@@ -396,6 +420,68 @@ length .[filter]
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Διαμορφώνει την ημερομηνία και την ώρα σύμφωνα με την [τοπική γλώσσα |develop#locale], εξασφαλίζοντας συνεπή και εντοπισμένη εμφάνιση των δεδομένων ώρας σε διάφορες γλώσσες και περιοχές. Το φίλτρο δέχεται την ημερομηνία ως χρονοσφραγίδα UNIX, συμβολοσειρά ή αντικείμενο `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Αν χρησιμοποιήσετε το φίλτρο χωρίς παραμέτρους, θα εξάγει την ημερομηνία σε επίπεδο μακράς μορφής, όπως εξηγείται παρακάτω.
+
+**α) Χρήση της μορφής**
+
+Η παράμετρος `format` περιγράφει ποια στοιχεία της ώρας θα πρέπει να εμφανίζονται. Χρησιμοποιεί κώδικες γραμμάτων, όπου ο αριθμός των επαναλήψεων επηρεάζει το πλάτος της εξόδου:
+
+| Έτος | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Μήνας | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `Αυγ` / `Αυγούστου`
+| Ημέρα | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `Κυρ` / `Κυριακή`
+| Ώρα | `j` / `H` / `h` | προτιμώμενη / 24ωρη / 12ωρη
+| Minute | `m` / `mm` | `5` / `05` <small>(2 ψηφία όταν συνδυάζεται με δευτερόλεπτα)</small>
+| Second | `s` / `ss` | `8` / `08` <small>(2 ψηφία όταν συνδυάζονται με λεπτά)</small>
+
+Η σειρά των κωδικών στη μορφή δεν έχει σημασία, καθώς η σειρά των στοιχείων θα εμφανίζεται σύμφωνα με τις συμβάσεις της τοπικής γλώσσας. Επομένως, η μορφή είναι ανεξάρτητη από την τοπική γλώσσα. Για παράδειγμα, η μορφή `yyyyMMMMd` στην τοπική γλώσσα `en_US` δίνει την ένδειξη `April 15, 2024`, ενώ στην τοπική γλώσσα `cs_CZ` δίνει την ένδειξη `15. dubna 2024`:
+
+| locale:  | el-GR | en_US
+|---
+| `format: 'dMy'` | 10/8/2024 | 8/10/2024
+| `format: 'yM'` | 8/2024 | 8/2024
+| `format: 'yyyyMMMM'` | Αύγουστος 2024 | August 2024
+| `format: 'MMMM'` | Αυγούστου | August
+| `format: 'jm'` | 5:54 μ.μ. | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 μ.μ. | 5:54 PM
+
+
+**β) Χρήση προκαθορισμένων στυλ**
+
+Οι παράμετροι `date` και `time` καθορίζουν το επίπεδο λεπτομέρειας για την εμφάνιση της ημερομηνίας και της ώρας. Μπορείτε να επιλέξετε ανάμεσα σε διάφορα επίπεδα: `full`, `long`, `medium`, `short`. Μπορείτε να εμφανίσετε μόνο την ημερομηνία, μόνο την ώρα ή και τα δύο:
+
+| locale:  | el-GR | en_US
+|---
+| `date: short` | 23/1/78 | 1/23/78
+| `date: medium` | 23 Ιαν 1978 | Jan 23, 1978
+| `date: long` | 23 Ιανουαρίου 1978 | January 23, 1978
+| `date: full` | Δευτέρα 23 Ιανουαρίου 1978 | Monday, January 23, 1978
+| `time: short` | 8:30 π.μ. | 8:30 AM
+| `time: medium` | 8:30:59 π.μ. | 8:30:59 AM
+| `time: long` | 8:30:59 π.μ. CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23/1/78, 8:30 π.μ. | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 Ιαν 1978, 8:30 π.μ. | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 Ιανουαρίου 1978 στις 8:30 π.μ. | January 23, 1978 at 8:30 AM
+
+Για την ημερομηνία, μπορείτε επίσης να χρησιμοποιήσετε το πρόθεμα `relative-` (π.χ. `relative-short`), το οποίο για ημερομηνίες κοντά στο παρόν θα εμφανίσει `yesterday`, `today` ή `tomorrow`, διαφορετικά, θα εμφανίσει με τον τυπικό τρόπο.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Βλέπε επίσης [ημερομηνία |#date].
+
+
 lower .[filter]
 ---------------
 Μετατρέπει μια τιμή σε πεζά γράμματα. Απαιτεί την επέκταση PHP `mbstring`.
@@ -416,8 +502,8 @@ nocheck .[filter]
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Εκτυπώσεις:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 Η κατάχρηση του φίλτρου `noescape` μπορεί να οδηγήσει σε ευπάθεια XSS! Ποτέ μην το χρησιμοποιείτε εκτός αν είστε **απολύτως σίγουροι** για το τι κάνετε και ότι η συμβολοσειρά που εκτυπώνετε προέρχεται από αξιόπιστη πηγή.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Διαμορφώνει έναν αριθμό σε δεδομένο αριθμό δεκαδικών ψηφίων. Μπορείτε επίσης να καθορίσετε έναν χαρακτήρα του δεκαδικού σημείου και του διαχωριστικού χιλιάδων.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Διαμορφώνει έναν αριθμό σε έναν καθορισμένο αριθμό δεκαδικών ψηφίων. Εάν έχει οριστεί η [τοπική γλώσσα |develop#locale], χρησιμοποιούνται τα αντίστοιχα διαχωριστικά δεκαδικών και χιλιάδων.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[fil
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Η παράμετρος `format` σας επιτρέπει να καθορίσετε την εμφάνιση των αριθμών ακριβώς σύμφωνα με τις ανάγκες σας. Απαιτεί μια καθορισμένη [τοπική γλώσσα |develop#locale]. Η μορφή αποτελείται από διάφορους ειδικούς χαρακτήρες, την πλήρη περιγραφή των οποίων μπορείτε να βρείτε στην τεκμηρίωση "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> υποχρεωτικό ψηφίο, εμφανίζεται πάντα, ακόμη και αν είναι μηδέν
+- `#` προαιρετικό ψηφίο, εμφανίζεται μόνο αν ο αριθμός έχει ψηφίο στη συγκεκριμένη θέση
+- `@` σημαντικό ψηφίο, βοηθά στην εμφάνιση του αριθμού με συγκεκριμένο αριθμό σημαντικών ψηφίων
+- `.` σηματοδοτεί τη θέση του δεκαδικού διαχωριστικού (κόμμα ή τελεία, ανάλογα με την τοπική γλώσσα)
+- `,` χρησιμοποιείται για το διαχωρισμό ομάδων ψηφίων, συνήθως χιλιάδων
+- `%` πολλαπλασιάζει τον αριθμό με το 100 και προσθέτει το σύμβολο του ποσοστού
+
+Ας δούμε μερικά παραδείγματα. Στο πρώτο παράδειγμα, τα δύο δεκαδικά ψηφία είναι υποχρεωτικά- στο δεύτερο, είναι προαιρετικά. Στο τρίτο παράδειγμα εμφανίζεται συμπλήρωση με μηδενικά και στις δύο πλευρές, ενώ στο τέταρτο εμφανίζονται μόνο τα υπάρχοντα ψηφία:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Τα σημαντικά ψηφία καθορίζουν πόσα ψηφία, ανεξάρτητα από το δεκαδικό σημείο, θα πρέπει να εμφανίζονται, στρογγυλοποιώντας τον αριθμό εάν είναι απαραίτητο:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Ένας εύκολος τρόπος για να εμφανίσετε έναν αριθμό ως ποσοστό. Ο αριθμός πολλαπλασιάζεται με το 100 και προστίθεται το σύμβολο `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Μπορούμε να ορίσουμε μια διαφορετική μορφή για θετικούς και αρνητικούς αριθμούς, οι οποίοι χωρίζονται με έναν χαρακτήρα `;`. Με αυτόν τον τρόπο, για παράδειγμα, οι θετικοί αριθμοί μπορούν να εμφανίζονται με το σύμβολο `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Να θυμάστε ότι η πραγματική εμφάνιση των αριθμών μπορεί να διαφέρει ανάλογα με τις ρυθμίσεις της τοπικής γλώσσας. Για παράδειγμα, σε ορισμένες χώρες χρησιμοποιείται κόμμα αντί για τελεία ως διαχωριστικό δεκαδικού ψηφίου. Αυτό το φίλτρο το λαμβάνει αυτόματα υπόψη, οπότε δεν χρειάζεται να ανησυχείτε γι' αυτό.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Συμπληρώνει μια συμβολοσειρά σε συγκεκριμένο μήκος με μια άλλη συμβολοσειρά από αριστερά.
 
@@ -472,7 +606,7 @@ padLeft(int length, string pad = ' ') .[filter]
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Γεμίζει μια συμβολοσειρά σε ένα συγκεκριμένο μήκος με μια άλλη συμβολοσειρά από δεξιά.
 
@@ -514,8 +648,8 @@ random .[filter]
 Βλέπε επίσης [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Επαναλαμβάνει τη συμβολοσειρά x φορές.
 
 ```latte
@@ -523,7 +657,7 @@ repeat(int count) .[filter]
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Αντικαθιστά όλες τις εμφανίσεις της συμβολοσειράς αναζήτησης με τη συμβολοσειρά αντικατάστασης.
 
@@ -538,7 +672,7 @@ replace(string|array search, string replace = '') .[filter]
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Αντικαθιστά όλες τις εμφανίσεις σύμφωνα με την κανονική έκφραση.
 
@@ -559,8 +693,8 @@ reverse .[filter]
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Στρογγυλοποιεί έναν αριθμό με δεδομένη ακρίβεια.
 
 ```latte
@@ -573,7 +707,7 @@ round(int precision = 0) .[filter]
 Βλέπε επίσης [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Εξάγει μια φέτα ενός πίνακα ή μιας συμβολοσειράς.
 
@@ -591,9 +725,9 @@ slice(int start, int length = null, bool preserveKeys = false) .[filter]
 Το φίλτρο θα αναδιατάξει και θα επαναφέρει τα κλειδιά του ακέραιου πίνακα από προεπιλογή. Αυτή η συμπεριφορά μπορεί να αλλάξει θέτοντας το preserveKeys σε true. Τα αλφαριθμητικά κλειδιά διατηρούνται πάντα, ανεξάρτητα από αυτήν την παράμετρο.
 
 
-sort  .[filter]
----------------
-Φίλτρο που ταξινομεί έναν πίνακα και διατηρεί τη συσχέτιση δεικτών.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Το φίλτρο ταξινομεί τα στοιχεία ενός πίνακα ή ενός επαναλήπτη διατηρώντας τα συσχετιστικά κλειδιά τους. Όταν έχει οριστεί μια [τοπική γλώσσα |develop#locale], η ταξινόμηση ακολουθεί τους κανόνες της, εκτός αν έχει καθοριστεί μια προσαρμοσμένη συνάρτηση σύγκρισης.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ sort  .[filter]
 {/foreach}
 ```
 
-Μπορείτε να περάσετε τη δική σας συνάρτηση σύγκρισης ως παράμετρο:
+Μπορείτε να καθορίσετε μια προσαρμοσμένη συνάρτηση σύγκρισης για την ταξινόμηση (το παράδειγμα δείχνει πώς να αντιστρέψετε την ταξινόμηση από το μεγαλύτερο στο μικρότερο):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Το φίλτρο `|sort` σας επιτρέπει επίσης να ταξινομείτε τα στοιχεία με βάση το κλειδί:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Εάν πρέπει να ταξινομήσετε έναν πίνακα με βάση μια συγκεκριμένη στήλη, μπορείτε να χρησιμοποιήσετε την παράμετρο `by`. Η τιμή `'name'` στο παράδειγμα καθορίζει ότι η ταξινόμηση θα γίνει με βάση τις παραμέτρους `$row->name` ή `$row['name']`, ανάλογα με το αν το `$row` είναι πίνακας ή αντικείμενο:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Μπορείτε επίσης να ορίσετε μια συνάρτηση επανάκλησης που καθορίζει την τιμή με βάση την οποία θα γίνει η ταξινόμηση:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Η παράμετρος `byKey` μπορεί να χρησιμοποιηθεί με τον ίδιο τρόπο.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ stripHtml .[filter]
 Το προκύπτον απλό κείμενο μπορεί φυσικά να περιέχει χαρακτήρες που αντιπροσωπεύουν ετικέτες HTML, για παράδειγμα το `'&lt;p&gt;'|stripHtml` μετατρέπεται σε `<p>`. Ποτέ μην εξάγετε το κείμενο που προκύπτει με `|noescape`, καθώς αυτό μπορεί να οδηγήσει σε ευπάθεια ασφαλείας.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Εξάγει μια φέτα μιας συμβολοσειράς. Αυτό το φίλτρο έχει αντικατασταθεί από ένα φίλτρο [φέτας |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ substr(int offset, int length = null) .[filter]
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Μεταφράζει εκφράσεις σε άλλες γλώσσες. Για να καταστήσετε το φίλτρο διαθέσιμο, πρέπει να [ρυθμίσετε τον μεταφραστή |develop#TranslatorExtension]. Μπορείτε επίσης να χρησιμοποιήσετε τις [ετικέτες για τη μετάφραση |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ translate(string message, ...args) .[filter]
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Απογύμνωση αρχικών και τελικών χαρακτήρων, από προεπιλογή κενό διάστημα.
 
 ```latte
@@ -675,7 +835,7 @@ trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Συντομεύει μια συμβολοσειρά στο μέγιστο δοσμένο μήκος, αλλά προσπαθεί να διατηρήσει ολόκληρες λέξεις. Αν η συμβολοσειρά είναι κομμένη, προσθέτει ελλειψογράμματα στο τέλος (αυτό μπορεί να αλλάξει με τη δεύτερη παράμετρο).
 
diff --git a/latte/el/functions.texy b/latte/el/functions.texy
index 3ff01d6318..b0465458b0 100644
--- a/latte/el/functions.texy
+++ b/latte/el/functions.texy
@@ -9,6 +9,8 @@
 | `divisibleBy`| [ελέγχει αν μια μεταβλητή διαιρείται με έναν αριθμό |#divisibleBy]
 | `even` | [ελέγχει αν ο δεδομένος αριθμός είναι ζυγός |#even]
 | `first` | [επιστρέφει το πρώτο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς |#first]
+| `group` | [ομαδοποιεί δεδομένα σύμφωνα με διάφορα κριτήρια |#group]
+| `hasBlock` | [ανιχνεύει την ύπαρξη ενός μπλοκ |#hasBlock]
 | `last` | [επιστρέφει το τελευταίο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς |#last]
 | `odd` | [ελέγχει αν ο δεδομένος αριθμός είναι περιττός |#odd]
 | `slice` | [εξάγει ένα τμήμα ενός πίνακα ή μιας συμβολοσειράς |#slice]
@@ -73,8 +75,8 @@ even(int $value): bool .[method]
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Επιστρέφει το πρώτο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς:
 
 ```latte
@@ -85,6 +87,36 @@ first(string|array $value): mixed .[method]
 Βλέπε επίσης [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Αυτή η λειτουργία ομαδοποιεί τα δεδομένα σύμφωνα με διάφορα κριτήρια.
+
+Σε αυτό το παράδειγμα, οι γραμμές του πίνακα ομαδοποιούνται με βάση τη στήλη `categoryId`. Η έξοδος είναι ένας πίνακας πεδίων όπου το κλειδί είναι η τιμή στη στήλη `categoryId`. Διαβάστε τις [λεπτομερείς οδηγίες |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Βλέπε επίσης [ομάδα |filters#group] φίλτρων.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Ελέγχει αν υπάρχει το μπλοκ με το καθορισμένο όνομα:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Δείτε επίσης τον [έλεγχο ύπαρξης μπλοκ |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Επιστρέφει το τελευταίο στοιχείο του πίνακα ή τον τελευταίο χαρακτήρα της συμβολοσειράς:
@@ -106,8 +138,8 @@ odd(int $value): bool .[method]
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Εξαγάγει μια φέτα ενός πίνακα ή μιας συμβολοσειράς.
 
 ```latte
diff --git a/latte/el/recipes.texy b/latte/el/recipes.texy
index 358bbc29bf..2dee1c0c48 100644
--- a/latte/el/recipes.texy
+++ b/latte/el/recipes.texy
@@ -9,7 +9,7 @@
 
 - Το NetBeans IDE έχει ενσωματωμένη υποστήριξη
 - PhpStorm: εγκαταστήστε το [πρόσθετο Latte |https://plugins.jetbrains.com/plugin/7457-latte] στο `Settings > Plugins > Marketplace`
-- VS Code: αναζητήστε το markerplace για το plugin "Nette Latte + Neon".
+- VS Code: αναζήτηση markerplace για [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ή [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
 - Sublime Text 3: στο Package Control βρείτε και εγκαταστήστε το πακέτο `Nette` και επιλέξτε Latte στο `View > Syntax`
 - σε παλιούς επεξεργαστές χρησιμοποιήστε την επισήμανση Smarty για τα αρχεία .latte
 
diff --git a/latte/el/safety-first.texy b/latte/el/safety-first.texy
index 10e6d61f4c..6322b713f0 100644
--- a/latte/el/safety-first.texy
+++ b/latte/el/safety-first.texy
@@ -351,7 +351,7 @@ Latte βλέπει το πρότυπο με τον ίδιο τρόπο που τ
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Γράφει:
diff --git a/latte/el/syntax.texy b/latte/el/syntax.texy
index 35288cdaf6..3ea9bf87ab 100644
--- a/latte/el/syntax.texy
+++ b/latte/el/syntax.texy
@@ -98,7 +98,7 @@ n:attributes .[#toc-n-attributes]
 Η με τη χρήση του προθέματος `tag-` η λειτουργικότητα εφαρμόζεται μόνο στις ετικέτες HTML:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Ανάλογα με την τιμή της μεταβλητής `$url` αυτό θα εκτυπωθεί:
@@ -155,6 +155,20 @@ n:attributes .[#toc-n-attributes]
 ```
 
 
+Δυναμικές ετικέτες HTML .[#toc-dynamic-html-tags]
+=================================================
+
+Το Latte υποστηρίζει δυναμικές ετικέτες HTML, οι οποίες είναι χρήσιμες όταν χρειάζεστε ευελιξία στα ονόματα των ετικετών:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Για παράδειγμα, ο παραπάνω κώδικας μπορεί να δημιουργήσει `<h1>Heading</h1>` ή `<h2>Heading</h2>` ανάλογα με την τιμή της μεταβλητής `$level`. Οι δυναμικές ετικέτες HTML στο Latte πρέπει πάντα να είναι ζευγαρωμένες. Η εναλλακτική τους είναι η [n:tag |tags#n:tag].
+
+Επειδή το Latte είναι ένα ασφαλές σύστημα διαμόρφωσης προτύπων, ελέγχει ότι το όνομα της ετικέτας που προκύπτει είναι έγκυρο και δεν περιέχει ανεπιθύμητες ή κακόβουλες τιμές. Εξασφαλίζει επίσης ότι το όνομα της τελικής ετικέτας είναι πάντα το ίδιο με το όνομα της ετικέτας έναρξης.
+
+
 Σχόλια .[#toc-comments]
 =======================
 
diff --git a/latte/el/tags.texy b/latte/el/tags.texy
index 05958f0e18..16e3cd663d 100644
--- a/latte/el/tags.texy
+++ b/latte/el/tags.texy
@@ -16,6 +16,7 @@
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [συνθήκη ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [test if there has been a change |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default]
+| `n:else` | [εναλλακτικό περιεχόμενο για τους όρους |#n:else]
 
 .[table-latte-tags language-latte]
 |## Βρόχοι
@@ -97,8 +98,8 @@
 | `{link}` | [εκτυπώνει έναν σύνδεσμο |application:creating-links#In the Presenter Template]
 | `{plink}` | [εκτυπώνει έναν σύνδεσμο προς έναν παρουσιαστή |application:creating-links#In the Presenter Template]
 | `{control}` | [εκτυπώνει ένα στοιχείο |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [ένα απόσπασμα προτύπου που μπορεί να σταλεί μέσω AJAX |application:ajax#tag-snippet]
-| `{snippetArea}` | φάκελος αποσπασμάτων
+| `{snippet}`... `{/snippet}` | [ένα απόσπασμα προτύπου που μπορεί να σταλεί μέσω AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [φάκελος αποσπασμάτων |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [προσωρινή αποθήκευση ενός τμήματος προτύπου |caching:en#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@
 | `{input}` | [εκτυπώνει ένα στοιχείο εισόδου φόρμας |forms:rendering#label-input]
 | `{inputError}` | [εκτυπώνει μήνυμα σφάλματος για το στοιχείο εισόδου φόρμας |forms:rendering#inputError]
 | `n:name` | [ενεργοποιεί ένα στοιχείο εισόδου HTML |forms:rendering#n:name]
-| `{formPrint}` | [δημιουργεί σχέδιο φόρμας Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [εκτυπώνει κλάση PHP για τα δεδομένα της φόρμας |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [μερική απόδοση φόρμας |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [απόδοση του δοχείου της φόρμας |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Age: {date('Y') - $birth}<br>
 Ωραία.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Αν γράψετε τη συνθήκη `{if} ... {/if}` με τη μορφή ενός [n:attribute |syntax#n:attributes], έχετε τη δυνατότητα να καθορίσετε μια εναλλακτική διακλάδωση χρησιμοποιώντας το `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Το χαρακτηριστικό `n:else` μπορεί επίσης να χρησιμοποιηθεί σε συνδυασμό με το [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], και [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Age: {date('Y') - $birth}<br>
 Χρησιμοποιήστε τη συνθήκη `{ifset $var}` για να προσδιορίσετε αν μια μεταβλητή (ή πολλαπλές μεταβλητές) υπάρχει και έχει μη μηδενική τιμή. Στην πραγματικότητα είναι το ίδιο με το `if (isset($var))` στην PHP. Όπως κάθε ετικέτα pair, μπορεί να γραφτεί με τη μορφή [n:attribute |syntax#n:attributes], οπότε ας το δείξουμε σε παράδειγμα:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Age: {date('Y') - $birth}<br>
 `{iterateWhile}`
 ----------------
 
-Απλοποιεί την ομαδοποίηση των γραμμικών δεδομένων κατά την επανάληψη σε έναν βρόχο foreach, εκτελώντας την επανάληψη σε έναν εμφωλευμένο βρόχο εφόσον ικανοποιείται η συνθήκη. [Διαβάστε τις οδηγίες στο βιβλίο μαγειρικής |cookbook/iteratewhile].
+Απλοποιεί την ομαδοποίηση των γραμμικών δεδομένων κατά την επανάληψη σε έναν βρόχο foreach με την επανάληψη σε έναν εμφωλευμένο βρόχο μέχρι να ικανοποιηθεί μια συνθήκη. [Διαβάστε τις λεπτομερείς οδηγίες |cookbook/grouping].
 
 Μπορεί επίσης να αντικαταστήσει κομψά τα `{first}` και `{last}` στο παραπάνω παράδειγμα:
 
@@ -489,6 +501,8 @@ Age: {date('Y') - $birth}<br>
 {/foreach}
 ```
 
+Βλέπε επίσης φίλτρα [παρτίδας |filters#batch] και [ομάδας |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ n:tag .[#toc-n-tag]
 <h3 class="main">...</h3>
 ```
 
+Επειδή το Latte είναι ένα ασφαλές σύστημα διαμόρφωσης προτύπων, ελέγχει ότι το όνομα της νέας ετικέτας είναι έγκυρο και δεν περιέχει ανεπιθύμητες ή κακόβουλες τιμές.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/el/template-inheritance.texy b/latte/el/template-inheritance.texy
index ce4a48716e..b80ad35c1b 100644
--- a/latte/el/template-inheritance.texy
+++ b/latte/el/template-inheritance.texy
@@ -132,7 +132,7 @@
 
 - Εάν χρησιμοποιείτε το `{layout}` σε ένα πρότυπο, πρέπει να είναι η πρώτη ετικέτα προτύπου σε αυτό το πρότυπο.
 
-- Η διάταξη μπορεί να [αναζητηθεί αυτόματα |develop#automatic-layout-lookup] (όπως στους [παρουσιαστές |application:templates#search-for-templates]). Σε αυτή την περίπτωση, αν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα `{layout none}`.
+- Η διάταξη μπορεί να [αναζητηθεί αυτόματα |develop#automatic-layout-lookup] (όπως στους [παρουσιαστές |application:templates#Template Lookup]). Σε αυτή την περίπτωση, αν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα `{layout none}`.
 
 - Η ετικέτα `{layout}` έχει ψευδώνυμο `{extends}`.
 
@@ -396,6 +396,14 @@ Hi, I am Mary.
 {/ifset}
 ```
 
+Η ύπαρξη μπλοκ επιστρέφεται επίσης από τη συνάρτηση [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Συμβουλές .[#toc-tips]
 ----------------------
@@ -415,7 +423,7 @@ Hi, I am Mary.
 Οριζόντια επαναχρησιμοποίηση `{import}` .{toc: Horizontal Reuse}
 ================================================================
 
-Η οριζόντια επαναχρησιμοποίηση είναι ένας τρίτος μηχανισμός επαναχρησιμοποίησης και κληρονομικότητας στο Latte. Σας επιτρέπει να φορτώνετε μπλοκ από άλλα πρότυπα. Είναι παρόμοιο με τη δημιουργία ενός αρχείου PHP με βοηθητικές συναρτήσεις ή ένα χαρακτηριστικό γνώρισμα.
+Η οριζόντια επαναχρησιμοποίηση είναι ο τρίτος μηχανισμός επαναχρησιμοποίησης και κληρονομικότητας στο Latte. Επιτρέπει τη φόρτωση μπλοκ από άλλα πρότυπα. Είναι παρόμοιο με τη δημιουργία ενός αρχείου με βοηθητικές συναρτήσεις στην PHP και στη συνέχεια τη φόρτωσή του χρησιμοποιώντας το `require`.
 
 Ενώ η κληρονομικότητα διάταξης προτύπου είναι ένα από τα πιο ισχυρά χαρακτηριστικά του Latte, περιορίζεται στην απλή κληρονομικότητα - ένα πρότυπο μπορεί να επεκτείνει μόνο ένα άλλο πρότυπο. Η οριζόντια επαναχρησιμοποίηση είναι ένας τρόπος για την επίτευξη πολλαπλής κληρονομικότητας.
 
@@ -447,7 +455,7 @@ Hi, I am Mary.
 
 Μπορείτε να χρησιμοποιήσετε όσες δηλώσεις `{import}` θέλετε σε οποιοδήποτε συγκεκριμένο πρότυπο. Αν δύο εισαγόμενα πρότυπα ορίζουν το ίδιο μπλοκ, το πρώτο κερδίζει. Ωστόσο, η υψηλότερη προτεραιότητα δίνεται στο κύριο πρότυπο, το οποίο μπορεί να αντικαταστήσει οποιοδήποτε εισαγόμενο μπλοκ.
 
-Όλα τα μπλοκ που αντικαθίστανται μπορούν να συμπεριληφθούν σταδιακά εισάγοντας τα ως [γονικό μπλοκ |#parent block]:
+Το περιεχόμενο των μπλοκ που έχουν αντικατασταθεί μπορεί να διατηρηθεί με την εισαγωγή του μπλοκ με τον ίδιο τρόπο όπως ένα [γονικό μπλοκ |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/en/@left-menu.texy b/latte/en/@left-menu.texy
index 3b1d3a0474..cfd235d1d7 100644
--- a/latte/en/@left-menu.texy
+++ b/latte/en/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Getting Started |Guide]
 - [Why Use Templates? |why-use]
-- Concepts
+- Concepts ⚗️
 	- [Safety First]
 	- [Template Inheritance]
 	- [Type System]
 	- [Sandbox]
 
-- For Designers
+- For Designers 🎨
 	- [Syntax]
 	- [Tags]
 	- [Filters]
 	- [Functions]
 	- [Tips and Tricks |recipes]
 
-- For Developers
+- For Developers 🧮
 	- [Practices for Developers |develop]
 	- [Extending Latte]
 	- [Creating an Extension |creating-extension]
 
-- [Cookbook |cookbook/@home]
+- [Cookbook 💡|cookbook/@home]
 	- [Migration from Twig |cookbook/migration-from-twig]
 	- [Migration from Latte 2 |cookbook/migration-from-latte2]
 	- [… more |cookbook/@home]
diff --git a/latte/en/cookbook/@home.texy b/latte/en/cookbook/@home.texy
index cea48d6e0f..d5407294bc 100644
--- a/latte/en/cookbook/@home.texy
+++ b/latte/en/cookbook/@home.texy
@@ -4,7 +4,9 @@ Cookbook
 .[perex]
 Example codes and recipes for accomplishing common tasks with Latte.
 
-- [Everything You Always Wanted to Know About {iterateWhile} |iteratewhile]
+- [Developer guidelines |/develop]
+- [Passing variables across templates |passing-variables]
+- [Everything you always wanted to know about grouping |grouping]
 - [How to write SQL queries in Latte? |how-to-write-sql-queries-in-latte]
 - [Migration from Latte 2 |migration-from-latte2]
 - [Migration from PHP |migration-from-php]
diff --git a/latte/en/cookbook/grouping.texy b/latte/en/cookbook/grouping.texy
new file mode 100644
index 0000000000..b0fef499fb
--- /dev/null
+++ b/latte/en/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Everything You Always Wanted to Know About Grouping
+***************************************************
+
+.[perex]
+When working with data in templates, you often encounter the need to group them or display them specifically according to certain criteria. For this purpose, Latte offers several powerful tools.
+
+The filter and function `|group` allow for efficient data grouping based on specified criteria, while the `|batch` filter facilitates splitting data into fixed batches and the `{iterateWhile}` tag provides the possibility of more complex cycle control with conditions.
+Each of these tags offers specific options for working with data, making them indispensable tools for dynamic and structured display of information in Latte templates.
+
+
+Filter and function `group` .{data-version:3.0.16}
+==================================================
+
+Imagine a database table `items` with items divided into categories:
+
+| id  | categoryId | name
+|------------------
+| 1   |      1  | Apple
+| 2   |      1  | Banana
+| 3   |      2  | PHP
+| 4   |      3  | Green
+| 5   |      3  | Red
+| 6   |      3  | Blue
+
+A simple list of all items using a Latte template would look like this:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+However, if we wanted the items to be organized into groups by category, we need to divide them so that each category has its own list. The result would then look like this:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+The task can be easily and elegantly solved using `|group`. We specify `categoryId` as the parameter, meaning that the items will be divided into smaller arrays based on the `$item->categoryId` value (if `$item` were an array, we would use `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+The filter can also be used as a function in Latte, giving us an alternative syntax: `{foreach group($items, categoryId) ...}`.
+
+If you want to group items according to more complex criteria, you can use a function in the filter parameter. For example, grouping items by the length of their name would look like this:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+It’s important to note that `$categoryItems` is not a regular array, but an object that behaves like an iterator. To access the first item in the group, you can use the [`first()`|latte:functions#first] function.
+
+This flexibility in data grouping makes `group` an exceptionally useful tool for presenting data in Latte templates.
+
+
+Nested Loops
+------------
+
+Let's say we have a database table with another column `subcategoryId` that defines subcategories for each item. We want to display each main category in a separate `<ul>` list and each subcategory in a separate nested `<ol>` list:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Connection with Nette Database
+------------------------------
+
+Let's show how to effectively use data grouping in combination with Nette Database. Suppose we are working with the `items` table from the initial example, which is connected through the `categoryId` column to this `categories` table:
+
+| categoryId | name       |
+|------------|------------|
+| 1          | Fruits     |
+| 2          | Languages  |
+| 3          | Colors     |
+
+We load data from the `items` table using the Nette Database Explorer command `$items = $db->table('items')`. During the iteration over these data, we have the opportunity not only to access attributes like `$item->name` and `$item->categoryId`, but thanks to the connection with the `categories` table, also to the related row in it via `$item->category`. This connection can demonstrate interesting uses:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+In this case, we use the `|group` filter to group by the connected row `$item->category`, not just by the `categoryId` column. This gives us the `ActiveRow` of the given category in the variable key, allowing us to directly display its name using `{$category->name}`. This is a practical example of how grouping can simplify templates and facilitate data handling.
+
+
+Filter `|batch`
+===============
+
+The filter allows you to split a list of elements into groups with a predetermined number of elements. This filter is ideal for situations where you want to present data in several smaller groups, for example, for better clarity or visual organization on the page.
+
+Imagine we have a list of items and want to display them in lists, each containing a maximum of three items. Using the `|batch` filter is very practical in such a case:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+In this example, the list `$items` is divided into smaller groups, each group (`$batch`) containing up to three items. Each group is then displayed in a separate `<ul>` list.
+
+If the last group does not contain enough elements to reach the desired number, the second parameter of the filter allows you to define what this group will be supplemented with. This is ideal for aesthetically aligning elements where an incomplete row might look disordered.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Tag `{iterateWhile}`
+====================
+
+We will demonstrate the same tasks we addressed with the `|group` filter using the `{iterateWhile}` tag. The main difference between the two approaches is that `group` first processes and groups all input data, while `{iterateWhile}` controls the progress of cycles with conditions, so the iteration occurs sequentially.
+
+First, we draw a table with categories using iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+While `{foreach}` marks the outer part of the cycle, i.e., drawing lists for each category, the `{iterateWhile}` tag marks the inner part, i.e., individual items.
+The condition in the end tag says that repetition will continue as long as the current and next element belong to the same category (`$iterator->nextValue` is [next item|/tags#$iterator]).
+
+If the condition were always met, all elements would be drawn in the inner cycle:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+The result will look like this:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+What is the use of iterateWhile in this way? When the table is empty and contains no elements, no empty `<ul></ul>` is printed.
+
+If we specify the condition in the opening `{iterateWhile}` tag, the behavior changes: the condition (and transition to the next element) is performed at the beginning of the inner cycle, not at the end.
+Thus, while you always enter `{iterateWhile}` without conditions, you enter `{iterateWhile $cond}` only when the condition `$cond` is met. And at the same time, the next element is written into `$item`.
+
+This is useful, for example, in a situation where we want to render the first element in each category differently, like this:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+We modify the original code so that we first render the first item and then in the inner cycle `{iterateWhile}` we render the other items from the same category:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Within one cycle, we can create multiple inner loops and even nest them. This way, subcategories could be grouped, for example.
+
+Suppose the table has another column `subcategoryId`, and besides each category being in a separate `<ul>`, each subcategory in a separate `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/en/cookbook/iteratewhile.texy b/latte/en/cookbook/iteratewhile.texy
deleted file mode 100644
index 695a0e1406..0000000000
--- a/latte/en/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Everything You Always Wanted to Know About {iterateWhile}
-*********************************************************
-
-.[perex]
-The tag `{iterateWhile}` is suitable for various tricks in foreach cycles.
-
-Suppose we have the following database table, where the items are divided into categories:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Of course, drawing items in a foreach loop as a list is easy:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-But what to do if you want render each category in a separate list? In other words, how to solve the task of grouping items from a linear list in a foreach cycle. The output should look like this:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-We will show you how easily and elegantly the task can be solved with iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-While `{foreach}` marks the outer part of the cycle, ie the drawing of lists for each category, the tags `{iterateWhile}` indicate the inner part, ie the individual items.
-The condition in the end tag says that the repetition will continue as long as the current and the next element belong to the same category (`$iterator->nextValue` is [next item |/tags#$iterator]).
-
-If the condition is always met, then all elements are drawn in the inner cycle:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-The result will look like this:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-What good is such an use of iterateWhile? How it differs from the solution we showed at the very beginning of this tutorial? The difference is that if the table is empty and does not contain any elements, it will not render empty `<ul></ul>`.
-
-
-Solution Without `{iterateWhile}`
----------------------------------
-
-If we solved the same task with completely basic constructions of template systems, for example in Twig, Blade, or pure PHP, the solution would look something like this:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-However, this code is incomprehensible and unintuitive. The connection between the opening and closing HTML tags is not clear at all. It is not clear at first glance if there is a mistake. And it requires auxiliary variables like `$prevCatId`.
-
-In contrast, the solution with `{iterateWhile}` is clean, clear, does not need auxiliary variables and is foolproof.
-
-
-Condition in the Closing Tag
-----------------------------
-
-If we specify a condition in the opening tag `{iterateWhile}`, the behavior changes: the condition (and the advance to the next element) is executed at the beginning of the inner cycle, not at the end.
-Thus, while `{iterateWhile}` without condition is always entered, `{iterateWhile $cond}` is entered only when condition `$cond` is met. At the same time, the following element is written to `$item`.
-
-This is useful, for example, in a situation where you want to render the first element in each category in a different way, such as:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Lets modify the original code, we draw first item and then additional items from the same category in the inner loop `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Nested Loops
-------------
-
-We can create multiple inner loops in one cycle and even nest them. In this way, for example, subcategories could be grouped.
-
-Suppose there is another column in the table `subCatId` and in addition to each category being in a separate `<ul>`, each subcategory will be in a separate `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filter |batch
--------------
-
-The grouping of linear items is also provided by a filter `batch`, into batches with a fixed number of elements:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-It can be replaced with iterateWhile as follows:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/en/cookbook/migration-from-latte2.texy b/latte/en/cookbook/migration-from-latte2.texy
index e563704572..8215f592ab 100644
--- a/latte/en/cookbook/migration-from-latte2.texy
+++ b/latte/en/cookbook/migration-from-latte2.texy
@@ -128,6 +128,26 @@ $latte->addExtension(new Nette\Bridges\CacheLatte\CacheExtension($cacheStorage))
 ```
 
 
+Tracy
+-----
+
+The panel for Tracy is now also activated as an extension.
+
+Old code for Latte 2:
+
+```php
+$latte = new Latte\Engine;
+Latte\Bridges\Tracy\LattePanel::initialize($latte);
+```
+
+New code for Latte 3:
+
+```php
+$latte = new Latte\Engine;
+$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
+```
+
+
 Translations
 ------------
 
@@ -157,7 +177,7 @@ In Latte 2 it was possible to register new tags using [config file |application:
 latte:
 	extensions:
 		- App\Templating\LatteExtension
-		- Latte\Essential\TranslatorExtension
+		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
 ```
 
 
diff --git a/latte/en/cookbook/passing-variables.texy b/latte/en/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..2db8289f61
--- /dev/null
+++ b/latte/en/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Passing Variables Across Templates
+**********************************
+
+This guide explains how variables are passed between templates in Latte using various tags such as `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}`, and others. You will also learn how to work with variables in the `{block}` and `{define}` tags, and the purpose of the `{parameters}` tag.
+
+
+Types of Variables
+------------------
+Variables in Latte can be divided into three categories based on how and where they are defined:
+
+**Input Variables** are those that are passed to the template from outside, for example, from a PHP script or using a tag like `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Surrounding Variables** are variables existing at the location of a specific tag. These include all input variables and other variables created using tags like `{var}`, `{default}`, or within a loop `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Explicit Variables** are those directly specified within a tag and sent to the target template.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+The `{block}` tag is used to define reusable code blocks that can be customized or extended in inherited templates. Surrounding variables defined before the block are available inside the block, but any changes to the variables are reflected only within that block.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+The `{define}` tag is used to create blocks that are rendered only when called using `{include}`. The variables available inside these blocks depend on whether parameters are specified in the definition. If parameters are specified, only those parameters are accessible. If not, all input variables of the template where the blocks are defined are accessible.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+The `{parameters}` tag is used to explicitly declare expected input variables at the beginning of the template. This way, you can easily document expected variables and their data types. It is also possible to define default values.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+The `{include file}` tag is used to insert an entire template. This template is passed both the input variables of the template where the tag is used and explicitly defined variables. However, the target template can limit the scope using `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+When inserting a block defined in the same template, all surrounding and explicitly defined variables are passed to it:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+In this example, the `$name` and `$age` variables are passed to the `blockName` block. The same behavior applies to `{include parent}`.
+
+When inserting a block from another template, only input variables and explicitly defined variables are passed. Surrounding variables are not automatically available.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` or `{extends}`
+-------------------------
+These tags define a layout to which input variables of the child template and variables created in the code before the blocks are passed:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Template `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+The `{embed}` tag is similar to the `{include}` tag but allows embedding blocks into the template. Unlike `{include}`, only explicitly declared variables are passed:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+In this example, the `menu.latte` template has access only to the `$items` variable.
+
+Conversely, blocks inside `{embed}` have access to all surrounding variables:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+The `{import}` tag is used to load blocks from other templates. Both input and explicitly declared variables are passed to the imported blocks.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+The `{sandbox}` tag isolates the template for safe processing. Variables are passed exclusively explicitly.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/en/creating-extension.texy b/latte/en/creating-extension.texy
index 2ab3a6d1d2..60b9bd3b4c 100644
--- a/latte/en/creating-extension.texy
+++ b/latte/en/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// a parsing function that just creates a node for now
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+If you are creating a new tag for Latte, it is advisable to create a dedicated node class for it, which will represent it in the AST tree (see the `ForeachNode` class in the example above). In some cases, you might find the trivial helper node class [AuxiliaryNode|api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] useful, which allows you to pass the body of the `print()` method and the list of nodes made accessible by the `getIterator()` method as constructor parameters:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Compiler Passes
 ===============
 
diff --git a/latte/en/develop.texy b/latte/en/develop.texy
index 87ecc92636..9a9a5ad437 100644
--- a/latte/en/develop.texy
+++ b/latte/en/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Locale .{data-version:3.0.18}
+=============================
+
+Latte allows you to set the locale, which affects the formatting of numbers, dates, and sorting. It is set using the `setLocale()` method. The locale identifier follows the IETF language tag standard, which uses the PHP `intl` extension. It consists of a language code and possibly a country code, for example, `en_US` for English in the United States, `de_DE` for German in Germany, etc.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+The locale setting affects the filters [localDate|filters#localDate], [sort|filters#sort], [number|filters#number], and [bytes|filters#bytes].
+
+.[note]
+Requires the PHP `intl` extension. The setting in Latte does not affect the global locale setting in PHP.
+
+
 Strict Mode .{data-version:3.0.8}
 =================================
 
@@ -274,16 +290,25 @@ If you use custom tags, also create your customized Linter, e.g. `custom-latte-l
 // enter the actual path to the autoload.php file
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// add individual extensions here
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// add your individual extensions here
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternatively, you can pass your own `Latte\Engine` object to the Linter:
+
+```php
+$latte = new Latte\Engine;
+// here we configure the $latte object
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Loading Templates from a String
 ===============================
diff --git a/latte/en/extending-latte.texy b/latte/en/extending-latte.texy
index 0e4178955a..0e5726200d 100644
--- a/latte/en/extending-latte.texy
+++ b/latte/en/extending-latte.texy
@@ -68,6 +68,16 @@ As you can see, the function receives the left side of the filter before the pip
 
 Of course, the function representing the filter can accept any number of parameters, and variadic parameters are also supported.
 
+If the filter returns a string in HTML, you can mark it so that Latte does not automatically (and therefore double) escaping it. This avoids the need to specify `|noescape` in the template.
+The easiest way is to wrap the string in a `Latte\Runtime\Html` object, the other way is [Contextual Filters|#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+In this case, the filter must ensure correct escaping of the data.
+
 
 Filters Using the Class
 -----------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// change content-type to HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/en/filters.texy b/latte/en/filters.texy
index 3eacff86a4..7b03a710aa 100644
--- a/latte/en/filters.texy
+++ b/latte/en/filters.texy
@@ -11,14 +11,16 @@ Filters are functions that change or format the data to a form we want. This is
 | `bytes`      | [formats size in bytes |#bytes]
 | `clamp`      | [clamps value to the range |#clamp]
 | `dataStream` | [Data URI protocol conversion |#datastream]
-| `date`       | [formats date |#date]
+| `date`       | [formats the date and time|#date]
 | `explode`    | [splits a string by the given delimiter |#explode]
 | `first`      | [returns first element of array or character of string |#first]
+| `group`      | [groups data according to various criteria |#group]
 | `implode`    | [joins an array to a string |#implode]
 | `indent`     | [indents the text from left with number of tabs |#indent]
 | `join`       | [joins an array to a string |#implode]
 | `last`       | [returns last element of array or character of string |#last]
 | `length`     | [returns length of a string or array |#length]
+| `localDate`  | [formats the date and time according to the locale|#localDate]
 | `number`     | [formats number |#number]
 | `padLeft`    | [completes the string to given length from left |#padLeft]
 | `padRight`   | [completes the string to given length from right |#padRight]
@@ -118,8 +120,8 @@ Filters
 =======
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filter that simplifies the listing of linear data in the form of a table. It returns an array of array with the given number of items. If you provide a second parameter this is used to fill up missing items on the last row.
 
 ```latte
@@ -152,6 +154,8 @@ Prints:
 </table>
 ```
 
+See also [group |#group] and [iterateWhile |tags#iterateWhile] tag.
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Inserts HTML line breaks before all newlines.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formats a size in bytes to human-readable form.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formats the size in bytes into a human-readable form. If the [locale |develop#locale] is set, the corresponding decimal and thousand separators are used.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formats a size in bytes to human-readable form.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Rounds a number up to a given precision.
 
 ```latte
@@ -203,8 +207,8 @@ Enforces URL sanitization. It checks if the variable contains a web URL (ie. HTT
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Prints:
@@ -217,8 +221,8 @@ Prints:
 See also [#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Returns value clamped to the inclusive range of min and max.
 
 ```latte
@@ -228,14 +232,14 @@ Returns value clamped to the inclusive range of min and max.
 Also exists as [function|functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Converts the content to data URI scheme. It can be used to insert images into HTML or CSS without the need to link external files.
 
 Lets have an image in a variable `$img = Image::fromFile('obrazek.gif')`, then
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Prints for example:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Requires PHP extension `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Returns a date in the given format using options of [php:strftime] or [php:date] PHP functions. Filter gets a date as a UNIX timestamp, a string or an object of `DateTime` type.
+date(string $format) .[filter]
+------------------------------
+Formats the date and time according to the mask used by the PHP function [php:date]. The filter accepts the date in UNIX timestamp format, as a string, or as a `DateTimeInterface` object.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+See also [#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Escapes a variable to be used as a parameter in URL.
 See also [#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Splits a string by the given delimiter and returns an array of strings. Alias for `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Returns the first element of array or character of string:
 See also [#last], [#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Rounds a number down to a given precision.
 
 ```latte
@@ -330,8 +335,27 @@ Converts a first letter of value to uppercase. Requires PHP extension `mbstring`
 See also [#capitalize], [#lower], [#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+The filter groups the data according to different criteria.
+
+In this example, the rows in the table are grouped by the column `categoryId`. The output is an array of arrays where the key is the value in the column `categoryId`. Read the [detailed instructions |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+See also [batch |#batch], the [group |functions#group] function, and the [iterateWhile |tags#iterateWhile] tag.
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Return a string which is the concatenation of the strings in the array. Alias for `join`.
 
 ```latte
@@ -346,8 +370,8 @@ You can also use an alias `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Indents a text from left by a given number of tabs or other characters which we specify in the second optional argument. Blank lines are not indented.
 
 ```latte
@@ -396,6 +420,68 @@ Returns length of a string or array.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formats date and time according to the [locale |develop#locale], ensuring consistent and localized display of time data across different languages and regions. The filter accepts the date as a UNIX timestamp, string, or `DateTimeInterface` object.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+If you use the filter without any parameters, it will output the date in the long format level, as explained further.
+
+**a) Using the format**
+
+The `format` parameter describes which time components should be displayed. It uses letter codes, where the number of repetitions affects the width of the output:
+
+| Year | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Month | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `Aug` / `August`
+| Day | `d` / `dd` / `E` / `EEEE` |  `1` / `01` / `Sun` / `Sunday`
+| Hour | `j` / `H` / `h` | preferred / 24-hour / 12-hour
+| Minute | `m` / `mm` | `5` / `05` <small>(2 digits when combined with seconds)</small>
+| Second | `s` / `ss` | `8` / `08` <small>(2 digits when combined with minutes)</small>
+
+The order of the codes in the format doesn’t matter, as the order of components will be displayed according to the locale's conventions. Therefore, the format is locale-independent. For example, the format `yyyyMMMMd` in the `en_US` locale outputs `April 15, 2024`, while in the `cs_CZ` locale it outputs `15. dubna 2024`:
+
+| locale: | cs_CZ | en_US
+|---
+| `format: 'dMy'` | 10. 8. 2024 | 8/10/2024
+| `format: 'yM'` | 8/2024 | 8/2024
+| `format: 'yyyyMMMM'` | srpen 2024 | August 2024
+| `format: 'MMMM'` | srpen | August
+| `format: 'jm'` | 17:22 | 5:22 PM
+| `format: 'Hm'` | 17:22 | 17:22
+| `format: 'hm'` | 5:22 odp. | 5:22 PM
+
+
+**b) Using preset styles**
+
+The `date` and `time` parameters determine the level of detail for the date and time display. You can choose from several levels: `full`, `long`, `medium`, `short`. You can display just the date, just the time, or both:
+
+| locale: | cs_CZ | en_US
+|---
+| `date: short` | 23.01.78 | 1/23/78
+| `date: medium` | 23. 1. 1978 | Jan 23, 1978
+| `date: long` | 23. ledna 1978 | January 23, 1978
+| `date: full` | pondělí 23. ledna 1978 | Monday, January 23, 1978
+| `time: short` | 8:30 | 8:30 AM
+| `time: medium` | 8:30:59 | 8:30:59 AM
+| `time: long` | 8:30:59 SEČ | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.78 8:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23. 1. 1978 8:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23. ledna 1978 v 8:30 | January 23, 1978 at 8:30 AM
+
+For the date, you can also use the prefix `relative-` (e.g., `relative-short`), which for dates close to the present will display `yesterday`, `today`, or `tomorrow`; otherwise, it will display in the standard way.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+See also [#date].
+
+
 lower .[filter]
 ---------------
 Converts a value to lowercase. Requires PHP extension `mbstring`.
@@ -416,8 +502,8 @@ If the link uses a different scheme, such as `javascript:` or `data:`, and you a
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Prints:
@@ -451,19 +537,67 @@ Unescaped: <b>hello</b>
 Misuse of the `noescape` filter can lead to an XSS vulnerability! Never use it unless you are **absolutely sure** what you are doing and that the string you are printing comes from a trusted source.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formats a number to given number of decimal places. You can also specify a character of the decimal point and thousands separator.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formats a number to a specified number of decimal places. If the [locale |develop#locale] is set, the corresponding decimal and thousand separators are used.
 
 ```latte
-{1234.20 |number}              1,234
-{1234.20 |number:1}            1,234.2
-{1234.20 |number:2}            1,234.20
-{1234.20 |number:2, ',', ' '}  1 234,20
+{1234.20|number}              1,234
+{1234.20|number:1}            1,234.2
+{1234.20|number:2}            1,234.20
+{1234.20|number:2, ',', ' '}  1 234,20
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+The `format` parameter allows you to define the appearance of numbers exactly according to your needs. It requires a set [locale |develop#locale]. The format consists of several special characters, the complete description of which can be found in the "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns documentation:
+
+- `0` mandatory digit, always displayed even if it's zero
+- `#` optional digit, displayed only if the number has a digit in that place
+- `@` significant digit, helps to display the number with a certain number of significant digits
+- `.` marks where the decimal separator should be (comma or dot, depending on the locale)
+- `,` used to separate groups of digits, usually thousands
+- `%` multiplies the number by 100 and adds the percent sign
+
+Let's look at some examples. In the first example, two decimal places are mandatory; in the second, they are optional. The third example shows padding with zeros on both sides, and the fourth displays only the existing digits:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Significant digits determine how many digits, regardless of the decimal point, should be displayed, rounding the number if necessary:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+An easy way to display a number as a percentage. The number is multiplied by 100 and the `%` sign is added:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+We can define a different format for positive and negative numbers, separated by a `;` character. This way, for example, positive numbers can be displayed with a `+` sign:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Remember that the actual appearance of numbers may vary depending on the locale settings. For example, in some countries, a comma is used instead of a dot as a decimal separator. This filter automatically accounts for this, so you don't need to worry about it.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Pads a string to a certain length with another string from left.
 
@@ -472,7 +606,7 @@ Pads a string to a certain length with another string from left.
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Pads a string to a certain length with another string from right.
 
@@ -514,8 +648,8 @@ Returns random element of array or character of string:
 See also [#first], [#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Repeats the string x-times.
 
 ```latte
@@ -523,7 +657,7 @@ Repeats the string x-times.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Replaces all occurrences of the search string with the replacement string.
 
@@ -538,7 +672,7 @@ Multiple replacements can be made at once:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Replaces all occurrences according to regular expression.
 
@@ -559,8 +693,8 @@ Reverses given string or array.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Rounds a number to a given precision.
 
 ```latte
@@ -573,7 +707,7 @@ Rounds a number to a given precision.
 See also [#ceil], [#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Extracts a slice of an array or a string.
 
@@ -591,9 +725,9 @@ If length is given and is positive, then the sequence will have up to that many
 Filter will reorder and reset the integer array keys by default. This behaviour can be changed by setting preserveKeys to true. String keys are always preserved, regardless of this parameter.
 
 
-sort  .[filter]
----------------
-Filter that sorts an array and maintain index association.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+The filter sorts elements of an array or iterator while preserving their associative keys. When a [locale |develop#locale] is set, the sorting follows its rules unless a custom comparison function is specified.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Array sorted in reverse order.
 {/foreach}
 ```
 
-You can pass your own comparison function as a parameter:
+You can specify a custom comparison function for sorting (the example shows how to reverse the sort from largest to smallest):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+The `|sort` filter also allows you to sort elements by key:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+If you need to sort a table by a specific column, you can use the `by` parameter. The value `'name'` in the example specifies that sorting will be done by `$row->name` or `$row['name']`, depending on whether `$row` is an array or an object:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+You can also define a callback function that determines the value to sort by:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+The `byKey` parameter can be used in the same way.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Converts HTML to plain text. That is, it removes HTML tags and converts HTML ent
 The resulting plain text can naturally contain characters that represent HTML tags, for example `'&lt;p&gt;'|stripHtml` is converted to `<p>`. Never output the resulting text with `|noescape`, as this may lead to a security vulnerability.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Extracts a slice of a string. This filter has been replaced by a [#slice] filter.
 
 ```latte
@@ -655,8 +815,8 @@ Extracts a slice of a string. This filter has been replaced by a [#slice] filter
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 It translates expressions into other languages. To make the filter available, you need [set up translator|develop#TranslatorExtension]. You can also use the [tags for translation|tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ It translates expressions into other languages. To make the filter available, yo
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Strip leading and trailing characters, by default whitespace.
 
 ```latte
@@ -675,7 +835,7 @@ Strip leading and trailing characters, by default whitespace.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Shortens a string to the maximum given length but tries to preserve whole words. If the string is truncated it adds ellipsis at the end (this can be changed by the second parameter).
 
diff --git a/latte/en/functions.texy b/latte/en/functions.texy
index 0e4708c341..03ed4a23c2 100644
--- a/latte/en/functions.texy
+++ b/latte/en/functions.texy
@@ -9,6 +9,8 @@ In addition to the common PHP functions, you can also use these in templates.
 | `divisibleBy`| [checks if a variable is divisible by a number |#divisibleBy]
 | `even`       | [checks if the given number is even |#even]
 | `first`      | [returns first element of array or character of string |#first]
+| `group`      | [groups data according to various criteria |#group]
+| `hasBlock`   | [detects the existence of a block |#hasBlock]
 | `last`       | [returns last element of array or character of string |#last]
 | `odd`        | [checks if the given number is odd |#odd]
 | `slice`      | [extracts a slice of an array or a string |#slice]
@@ -73,8 +75,8 @@ Checks if the given number is even.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Returns the first element of array or character of string:
 
 ```latte
@@ -85,6 +87,36 @@ Returns the first element of array or character of string:
 See also [#last], [filter first|filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+This function groups data according to different criteria.
+
+In this example, the rows in the table are grouped by the column `categoryId`. The output is an array of fields where the key is the value in the column `categoryId`. Read the [detailed instructions |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+See also filter [group |filters#group].
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Checks if the block of the specified name exists:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+See also [block existence check |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Returns the last element of array or character of string:
@@ -106,8 +138,8 @@ Checks if the given number is odd.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Extracts a slice of an array or a string.
 
 ```latte
diff --git a/latte/en/recipes.texy b/latte/en/recipes.texy
index c205005472..925e03ac70 100644
--- a/latte/en/recipes.texy
+++ b/latte/en/recipes.texy
@@ -9,7 +9,7 @@ Write templates in an editor or IDE that has support for Latte. It will be much
 
 - NetBeans IDE has built-in support
 - PhpStorm: install the [Latte plugin|https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace`
-- VS Code: search markerplace for "Nette Latte + Neon" plugin
+- VS Code: search markerplace for [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] or [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
 - Sublime Text 3: in Package Control find and install `Nette` package and select Latte in `View > Syntax`
 - in old editors use Smarty highlighting for .latte files
 
diff --git a/latte/en/safety-first.texy b/latte/en/safety-first.texy
index 83454d8ade..172c583ca6 100644
--- a/latte/en/safety-first.texy
+++ b/latte/en/safety-first.texy
@@ -351,7 +351,7 @@ Latte automatically checks whether the variable used in the `src` or `href` attr
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Writes:
diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy
index 7358007478..d5cb6a97e0 100644
--- a/latte/en/syntax.texy
+++ b/latte/en/syntax.texy
@@ -9,7 +9,7 @@ Below is a minimal template that illustrates a few basics elements: tags, n:attr
 
 ```latte
 {* this is a comment *}
-<ul n:if="$items">                {* n:if is n:atribut *}
+<ul n:if="$items">                {* n:if is n:attribute *}
 {foreach $items as $item}         {* tag representing foreach loop *}
 	<li>{$item|capitalize}</li>   {* tag that prints a variable with a filter *}
 {/foreach}                        {* end of cycle *}
@@ -98,7 +98,7 @@ Prints:
 Or by using `tag-` prefix the functionality is applied on the HTML tags only:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Depending on the value of `$url` variable this will print:
@@ -155,6 +155,20 @@ Or directly on value (in combination with [`{=expr}`| https://latte.nette.org/en
 ```
 
 
+Dynamic HTML Tags
+=================
+
+Latte supports dynamic HTML tags, which are useful when you need flexibility in tag names:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+For example, the code above can generate `<h1>Heading</h1>` or `<h2>Heading</h2>` depending on the value of the variable `$level`. Dynamic HTML tags in Latte must always be paired. Their alternative is the [n:tag |tags#n:tag].
+
+Because Latte is a secure templating system, it checks that the resulting tag name is valid and contains no unwanted or malicious values. It also ensures that the end tag name is always the same as the opening tag name.
+
+
 Comments
 ========
 
diff --git a/latte/en/tags.texy b/latte/en/tags.texy
index fcecb2a3c1..719bc79156 100644
--- a/latte/en/tags.texy
+++ b/latte/en/tags.texy
@@ -16,6 +16,7 @@ Summary and description of all Latte built-in tags.
 | `{ifset}` … `{elseifset}` … `{/ifset}`      | [condition ifset|#ifset-elseifset]
 | `{ifchanged}` … `{/ifchanged}`              | [test if there has been a change|#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch|#switch-case-default]
+| `n:else`                                    | [alternative content for conditions |#n:else]
 
 .[table-latte-tags language-latte]
 |## Loops
@@ -89,7 +90,7 @@ Summary and description of all Latte built-in tags.
 | `n:class`                      | [smart class attribute |#n:class]
 | `n:attr`                       | [smart HTML attributes |#n:attr]
 | `n:tag`                        | [dynamic name of HTML element |#n:tag]
-| `n:ifcontent`                  | [Omit empty HTML tag |#n:ifcontent]
+| `n:ifcontent`                  | [omit empty HTML tag |#n:ifcontent]
 
 .[table-latte-tags language-latte]
 |## Available only in Nette Framework
@@ -97,8 +98,8 @@ Summary and description of all Latte built-in tags.
 | `{link}`                       | [prints a link |application:creating-links#In the Presenter Template]
 | `{plink}`                      | [prints a link to a presenter |application:creating-links#In the Presenter Template]
 | `{control}`                    | [prints a component |application:components#Rendering]
-| `{snippet}` … `{/snippet}`     | [a template snippet that can be sent by AJAX |application:ajax#tag-snippet]
-| `{snippetArea}`                | snippets envelope
+| `{snippet}` … `{/snippet}`     | [a template snippet that can be sent by AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}`                | [snippets envelope |application:ajax#snippet-areas]
 | `{cache}` … `{/cache}`         | [caches a template section |caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Summary and description of all Latte built-in tags.
 | `{input}`                      | [prints a form input element |forms:rendering#label-input]
 | `{inputError}`                 | [prints error message for form input element|forms:rendering#inputError]
 | `n:name`                       | [activates an HTML input element |forms:rendering#n:name]
-| `{formPrint}`                  | [generates Latte form blueprint |forms:rendering#formPrint]
-| `{formPrintClass}`             | [prints PHP class for form data |forms:in-presenter#mapping-to-classes]
-| `{formContext}` … `{/formContext}` | [partial form rendering |forms:rendering#special-cases]
 | `{formContainer}` … `{/formContainer}` | [rendering the form container |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Do you know that you can add prefix `tag-` to n:attributes? Then the condition w
 Nice.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+If you write the `{if} ... {/if}` condition in the form of an [n:attribute|syntax#n:attributes], you have the option to specify an alternative branch using `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+The `n:else` attribute can also be used in conjunction with [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], and [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ See also [`{ifset block}` |template-inheritance#checking-block-existence]
 Use the `{ifset $var}` condition to determine if a variable (or multiple variables) exists and has a non-null value. It's actually the same as `if (isset($var))` in PHP. Like any pair tag, this can be written in the form of [n:attribute|syntax#n:attributes], so let's show it in example:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ That's pretty practical, isn't it?
 `{iterateWhile}`
 ----------------
 
-It simplifies the grouping of linear data during iteration in a foreach loop by performing the iteration in a nested loop as long as the condition is met. [Read instructions in cookbook|cookbook/iteratewhile].
+Simplifies the grouping of linear data during iteration in a foreach loop by iterating in a nested loop until a condition is satisfied. [Read the detailed instructions |cookbook/grouping].
 
 It can also elegantly replace `{first}` and `{last}` in the example above:
 
@@ -489,6 +501,8 @@ It can also elegantly replace `{first}` and `{last}` in the example above:
 {/foreach}
 ```
 
+See also [batch |filters#batch] and [group |filters#group] filters.
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ If `$heading === null`, the `<h1>` tag is printed without change. Otherwise, the
 <h3 class="main">...</h3>
 ```
 
+Because Latte is a secure templating system, it checks that the new tag name is valid and does not contain any unwanted or malicious values.
+
 
 n:ifcontent
 -----------
diff --git a/latte/en/template-inheritance.texy b/latte/en/template-inheritance.texy
index e9eeeaa226..a4518db3b7 100644
--- a/latte/en/template-inheritance.texy
+++ b/latte/en/template-inheritance.texy
@@ -2,7 +2,7 @@ Template Inheritance and Reusability
 ************************************
 
 .[perex]
-Template reusability and inheritance mechanisms are here to boosts your productivity because each template contains only its unique contents and the repeated elements and structures are reused. We introduce three concepts: [#layout inheritance], [#horizontal reuse] and [#unit inheritance].
+Template reusability and inheritance mechanisms are here to boost your productivity because each template contains only its unique contents and the repeated elements and structures are reused. We introduce three concepts: [#layout inheritance], [#horizontal reuse] and [#unit inheritance].
 
 The concept of Latte template inheritance is similar to PHP class inheritance. You define a **parent template** that other **child templates** can extend from and can override parts of the parent template. It works great when elements share a common structure. Sounds complicated? Don't worry, it's not.
 
@@ -30,7 +30,7 @@ Let’s look at layout template inheritance by starting with an example. This is
 </html>
 ```
 
-The `{block}` tags defines three blocks that child templates can fill in. All the block tag does is to tell the template engine that a child template may override those portions of the template by defining their own block of the same name.
+The `{block}` tags define three blocks that child templates can fill in. All the block tag does is tell the template engine that a child template may override those portions of the template by defining their own block of the same name.
 
 A child template might look like this:
 
@@ -46,7 +46,7 @@ A child template might look like this:
 
 The `{layout}` tag is the key here. It tells the template engine that this template “extends” another template. When Latte renderes this template, first it locates the parent – in this case, `layout.latte`.
 
-At that point, the template engine will notice the three block tags in `layout.latte` and replace those blocks with the contents of the child template. Note that since the child template didn’t define the *footer* block, the contents from the parent template is used instead. Content within a `{block}` tag in a parent template is always used as a fallback.
+At that point, the template engine will notice the three block tags in `layout.latte` and replace those blocks with the contents of the child template. Note that since the child template didn’t define the *footer* block, the content from the parent template is used instead. Content within a `{block}` tag in a parent template is always used as a fallback.
 
 The output might look like:
 
@@ -76,7 +76,7 @@ In a child template, blocks can only be located either at the top level or insid
 {/block}
 ```
 
-Also a block will always be created in regardless of whether the surrounding `{if}` condition is evaluated to be true or false. Contrary to what you might think, this template does define a block.
+Also a block will always be created regardless of whether the surrounding `{if}` condition is evaluated to be true or false. Contrary to what you might think, this template does define a block.
 
 ```latte
 {if false}
@@ -96,7 +96,7 @@ If you want the output inside block to be displayed conditionally, use the follo
 {/block}
 ```
 
-Data outside of a blocks in a child template are executed before the layout template is rendered, thus you can use it to define variables like `{var $foo = bar}` and propagate data to the whole inheritance chain:
+Data outside of blocks in a child template are executed before the layout template is rendered, thus you can use it to define variables like `{var $foo = bar}` and propagate data to the whole inheritance chain:
 
 ```latte
 {layout 'layout.latte'}
@@ -132,7 +132,7 @@ Here are some tips for working with layout inheritance:
 
 - If you use `{layout}` in a template, it must be the first template tag in that template.
 
-- Layout can be [searched automatically |develop#automatic-layout-lookup] (like in [presenters |application:templates#search-for-templates]). In this case, if the template should not have a layout, it will indicate this with the `{layout none}` tag.
+- Layout can be [searched automatically |develop#automatic-layout-lookup] (like in [presenters |application:templates#Template Lookup]). In this case, if the template should not have a layout, it will indicate this with the `{layout none}` tag.
 
 - Tag `{layout}` has alias `{extends}`.
 
@@ -213,7 +213,7 @@ The tag can also be written as [n:attribute|syntax#n:attributes]:
 Local Blocks
 ------------
 
-Every block overrides content of parent block of the same name. Except for local blocks. They are something like private methods in class. You can create a template without worrying that – due to coincidence of block names – they would be overwritten by second template.
+Every block overrides content of parent block of the same name. Except for local blocks. They are something like private methods in class. You can create a template without worrying that – due to coincidence of block names – they would be overwritten by a second template.
 
 ```latte
 {block local helper}
@@ -236,13 +236,13 @@ To print a block in a specific place, use the `{include blockname}` tag:
 <h1>{include title}</h1>
 ```
 
-You can also display block from another template:
+You can also display a block from another template:
 
 ```latte
 {include footer from 'main.latte'}
 ```
 
-Printed block have not access to the variables of the active context, except if the block is defined in the same file where it is included. However they have access to the global variables.
+Printed blocks do not have access to the variables of the active context, except if the block is defined in the same file where it is included. However they do have access to the global variables.
 
 You can pass variables to the block in the following way:
 
@@ -257,7 +257,7 @@ You can use a variable or any expression in PHP as the block name. In this case,
 {include block $name}
 ```
 
-Block can also be printed inside itself, which is useful, for example, when rendering a tree structure:
+A block can also be printed inside itself, which is useful, for example, when rendering a tree structure:
 
 ```latte
 {define menu, $items}
@@ -275,7 +275,7 @@ Block can also be printed inside itself, which is useful, for example, when rend
 {/define}
 ```
 
-Instead of `{include menu, ...}` we can also write `{include this, ...}` where `this` means current block.
+Instead of `{include menu, ...}` we can also write `{include this, ...}` where `this` means the current block.
 
 Printed content can be modified by [filters|syntax#filters]. The following example removes all HTML and title-cases it:
 
@@ -332,7 +332,7 @@ Imagine you have a helper template with a collection of definitions on how to dr
 {/define}
 ```
 
-Arguments of a definitions are always optional with default value `null`, unless default value is specified (here `'text'` is the default value for `$type`). Parameter types can also be declared: `{define input, string $name, ...}`.
+Arguments of a definition are always optional with default value `null`, unless default value is specified (here `'text'` is the default value for `$type`). Parameter types can also be declared: `{define input, string $name, ...}`.
 
 The template with the definitions is loaded using [`{import}` |#horizontal-reuse]. The definitions themselves are rendered [in the same way as the blocks |#Printing Blocks]:
 
@@ -396,12 +396,20 @@ You can use a variable or any expression in PHP as the block name. In this case,
 {/ifset}
 ```
 
+The existence of blocks is also returned by the function [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Tips
 ----
 Here are some tips for working with blocks:
 
-- The last top-level block does not need to have closing tag (block ends with the end of the document). This simplifies the writing of child templates, which one primary block.
+- The last top-level block does not need to have closing tag (block ends with the end of the document). This simplifies the writing of child templates with one primary block.
 
 - For extra readability, you can optionally give a name to your `{/block}` tag, for example `{/block footer}`. However, the name  must match the block name. In larger templates, this technique helps you see which block tags are being closed.
 
@@ -415,7 +423,7 @@ Here are some tips for working with blocks:
 Horizontal Reuse `{import}` .{toc: Horizontal Reuse}
 ====================================================
 
-The horizontal reuse is a third reusability and inheritance mechanism in Latte. It allows you to load blocks from other templates. It's similar to creating a PHP file with helper functions or a trait.
+Horizontal reuse is the third mechanism for reuse and inheritance in Latte. It allows loading blocks from other templates. It is similar to creating a file with helper functions in PHP and then loading it using `require`.
 
 While template layout inheritance is one of Latte's most powerful features, it is limited to simple inheritance - a template can only extend one other template. Horizontal reuse is a way to achieve multiple inheritance.
 
@@ -447,7 +455,7 @@ The `{import}` tag should be the first template tag after `{layout}`. The templa
 
 You can use as many `{import}` statements as you want in any given template. If two imported templates define the same block, the first one wins. However, the highest priority is given to the main template, which can overwrite any imported block.
 
-All overridden blocks can be included gradually by inserting them as [#parent block]:
+The content of overwritten blocks can be preserved by inserting the block in the same way as a [#parent block]:
 
 ```latte
 {layout 'layout.latte'}
@@ -472,7 +480,7 @@ The unit inheritance takes the idea of layout inheritance to the level of conten
 
 In unit inheritance the `{embed}` tag is the key. It combines the behavior of `{include}` and `{layout}`. It allows you to include another template’s or block's contents and optionally pass variables, just like `{include}` does. It also allows you to override any block defined inside the included template, like `{layout}` does.
 
-For example we are going to use the collapsible accordion element. Let’s take a look at the element skeleton in template `collapsible.latte`:
+For example, we are going to use the collapsible accordion element. Let’s take a look at the element skeleton in the template `collapsible.latte`:
 
 ```latte
 <section class="collapsible {$modifierClass}">
@@ -486,9 +494,9 @@ For example we are going to use the collapsible accordion element. Let’s take
 </section>
 ```
 
-The `{block}` tags defines two blocks that child templates can fill in. Yes, like in the case of parent template in the layout inheritance template. You also see `$modifierClass` variable.
+The `{block}` tags defines two blocks that child templates can fill in. Yes, like in the case of parent template in the layout inheritance template. You also see a `$modifierClass` variable.
 
-Let's use our element in template. This is where `{embed}` comes in. It’s a super powerful piece of kit that lets us do all the things: include element's template contents, add variables to it, and add blocks with custom HTML to it:
+Let's use our element in a template. This is where `{embed}` comes in. It’s a super powerful piece of kit that lets us do all the things: include an element's template contents, add variables to it, and add blocks with custom HTML to it:
 
 ```latte
 {embed 'collapsible.latte', modifierClass: my-style}
@@ -518,7 +526,7 @@ The output might look like:
 </section>
 ```
 
-Blocks inside embed tags form a separate layer independent of other blocks. Therefore, they can have the same name as the block outside the embed and are not affected in any way. Using the tag [include|#Printing Blocks] inside `{embed}` tags you can insert blocks here created, blocks from embedded template (which *are not* [local|#Local Blocks]), and also blocks from main template which *are* local. You can also [import blocks|#Horizontal Reuse] from other files:
+Blocks inside embed tags form a separate layer independent of other blocks. Therefore, they can have the same name as the block outside the embed and are not affected in any way. Using the tag [include|#Printing Blocks] inside `{embed}` tags you can insert blocks created here, blocks from an embedded template (which *are not* [local|#Local Blocks]), and also blocks from the main template which *are* local. You can also [import blocks|#Horizontal Reuse] from other files:
 
 ```latte
 {block outer}…{/block}
@@ -539,7 +547,7 @@ Blocks inside embed tags form a separate layer independent of other blocks. Ther
 {/embed}
 ```
 
-Embeded templates have not access to the variables of the active context, but they have access to the global variables.
+Embedded templates do not have access to the variables of the active context, but they do have access to the global variables.
 
 With `{embed}` you can insert not only templates but also other blocks, so the previous example could be written like this:
 
@@ -572,7 +580,7 @@ If we pass an expression to `{embed}` and it is not clear whether it is a block
 Use Cases
 =========
 
-There are various types of inheritance and code reuse in Latte. Let's summarize the main concepts for more clearance:
+There are various types of inheritance and code reuse in Latte. Let's summarize the main concepts for more clarity:
 
 
 `{include template}`
diff --git a/latte/es/@left-menu.texy b/latte/es/@left-menu.texy
index 9b1db0abb8..e461f2ccd6 100644
--- a/latte/es/@left-menu.texy
+++ b/latte/es/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Primeros pasos |Guide]
 - [¿Por qué utilizar plantillas? |why-use]
-- Conceptos
+- Conceptos ⚗️
 	- [La seguridad ante todo |Safety First]
 	- [Herencia de plantillas |Template Inheritance]
 	- [Sistema de tipos |Type System]
 	- [Sandbox]
 
-- Para diseñadores
+- Para diseñadores 🎨
 	- [Sintaxis |Syntax]
 	- [Tags]
 	- [Filtros |Filters]
 	- [Funciones |Functions]
 	- [Trucos y consejos |recipes]
 
-- Para desarrolladores
+- Para desarrolladores 🧮
 	- [Prácticas para desarrolladores |develop]
 	- [Ampliación de Latte |Extending Latte]
 	- [Creación de una extensión |creating-extension]
 
-- [Libro de recetas |cookbook/@home]
+- [Libro de recetas 💡|cookbook/@home]
 	- [Migración desde Twig |cookbook/migration-from-twig]
 	- [... más |cookbook/@home]
 
diff --git a/latte/es/cookbook/@home.texy b/latte/es/cookbook/@home.texy
index ca75fda004..cecc4bc667 100644
--- a/latte/es/cookbook/@home.texy
+++ b/latte/es/cookbook/@home.texy
@@ -4,7 +4,9 @@ Libro de cocina
 .[perex]
 Códigos de ejemplo y recetas para realizar tareas comunes con Latte.
 
-- [Todo lo que siempre quiso saber sobre {iterateWhile} |iteratewhile]
+- [Directrices para desarrolladores |/develop]
+- [Paso de variables entre plantillas |passing-variables]
+- [Todo lo que siempre quiso saber sobre la agrupación |grouping]
 - [¿Cómo escribir consultas SQL en Latte? |how-to-write-sql-queries-in-latte]
 - [Migración desde PHP |migration-from-php]
 - [Migración desde Twig |migration-from-twig]
diff --git a/latte/es/cookbook/grouping.texy b/latte/es/cookbook/grouping.texy
new file mode 100644
index 0000000000..883dd4e77e
--- /dev/null
+++ b/latte/es/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Todo lo que siempre quiso saber sobre la agrupación
+***************************************************
+
+.[perex]
+Al trabajar con datos en plantillas, a menudo se encuentra con la necesidad de agruparlos o mostrarlos específicamente según ciertos criterios. Para ello, Latte ofrece varias herramientas potentes.
+
+El filtro y la función `|group` permiten agrupar eficazmente los datos en función de criterios especificados, mientras que el filtro `|batch` facilita la división de los datos en lotes fijos y la etiqueta `{iterateWhile}` ofrece la posibilidad de un control de ciclos más complejo con condiciones.
+Cada una de estas etiquetas ofrece opciones específicas para trabajar con los datos, lo que las convierte en herramientas indispensables para la visualización dinámica y estructurada de la información en las plantillas Latte.
+
+
+Filtro y función `group` .[#toc-filter-and-function-group]
+==========================================================
+
+Imagine una tabla de base de datos `items` con artículos divididos en categorías:
+
+| id | categoryId | name
+|------------------
+| 1 Manzana
+| 2 1 Plátano
+| 3. 2. PHP
+| 4 3 Verde
+| 5. 3. Rojo
+| 6 3 Azul
+
+Una lista simple de todos los elementos utilizando una plantilla Latte tendría este aspecto:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Sin embargo, si quisiéramos que los artículos estuvieran organizados en grupos por categorías, tendríamos que dividirlos de forma que cada categoría tuviera su propia lista. El resultado sería el siguiente
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+La tarea puede resolverse fácil y elegantemente utilizando `|group`. Especificamos `categoryId` como parámetro, lo que significa que los elementos se dividirán en matrices más pequeñas en función del valor de `$item->categoryId` (si `$item` fuera una matriz, utilizaríamos `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+El filtro también se puede utilizar como una función en Latte, lo que nos da una sintaxis alternativa: `{foreach group($items, categoryId) ...}`.
+
+Si desea agrupar elementos según criterios más complejos, puede utilizar una función en el parámetro filtro. Por ejemplo, agrupar elementos por la longitud de su nombre tendría este aspecto:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Es importante tener en cuenta que `$categoryItems` no es una matriz normal, sino un objeto que se comporta como un iterador. Para acceder al primer elemento del grupo, puede utilizar la función [`first()` |latte:functions#first] para acceder al primer elemento del grupo.
+
+Esta flexibilidad en la agrupación de datos hace de `group` una herramienta excepcionalmente útil para presentar datos en plantillas Latte.
+
+
+Bucles anidados .[#toc-nested-loops]
+------------------------------------
+
+Supongamos que tenemos una tabla de base de datos con otra columna `subcategoryId` que define subcategorías para cada artículo. Queremos mostrar cada categoría principal en una lista `<ul>` y cada subcategoría en una lista anidada separada `<ol>` anidada:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Conexión con la base de datos Nette .[#toc-connection-with-nette-database]
+--------------------------------------------------------------------------
+
+Veamos cómo utilizar eficazmente la agrupación de datos en combinación con Nette Database. Supongamos que estamos trabajando con la tabla `items` del ejemplo inicial, que está conectada a través de la columna `categoryId` a esta tabla `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 Frutas
+| 2 Idiomas
+| 3 Colores
+
+Cargamos los datos de la tabla `items` utilizando el comando de Nette Database Explorer `$items = $db->table('items')`. Durante la iteración sobre estos datos, tenemos la oportunidad no sólo de acceder a atributos como `$item->name` y `$item->categoryId`, sino gracias a la conexión con la tabla `categories`, también a la fila relacionada en ella a través de `$item->category`. Esta conexión puede demostrar usos interesantes:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+En este caso, utilizamos el filtro `|group` para agrupar por la fila conectada `$item->category`, no sólo por la columna `categoryId`. Esto nos da la `ActiveRow` de la categoría dada en la clave variable, permitiéndonos mostrar directamente su nombre usando `{$category->name}`. Este es un ejemplo práctico de cómo la agrupación puede simplificar las plantillas y facilitar el manejo de los datos.
+
+
+Filtro `|batch` .[#toc-filter-batch]
+====================================
+
+El filtro permite dividir una lista de elementos en grupos con un número predeterminado de elementos. Este filtro es ideal para situaciones en las que desee presentar los datos en varios grupos más pequeños, por ejemplo, para una mayor claridad u organización visual en la página.
+
+Imaginemos que tenemos una lista de elementos y queremos mostrarlos en listas, cada una de las cuales contiene un máximo de tres elementos. Utilizar el filtro `|batch` es muy práctico en un caso así:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+En este ejemplo, la lista `$items` se divide en grupos más pequeños, cada uno de los cuales (`$batch`) contiene un máximo de tres elementos. Cada grupo se muestra en una lista `<ul>` separada.
+
+Si el último grupo no contiene suficientes elementos para alcanzar el número deseado, el segundo parámetro del filtro permite definir con qué se completará este grupo. Esto es ideal para alinear estéticamente elementos en los que una fila incompleta podría parecer desordenada.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Etiqueta `{iterateWhile}` .[#toc-tag-iteratewhile]
+==================================================
+
+Demostraremos las mismas tareas que abordamos con el filtro `|group` utilizando la etiqueta `{iterateWhile}`. La principal diferencia entre los dos enfoques es que `group` primero procesa y agrupa todos los datos de entrada, mientras que `{iterateWhile}` controla el progreso de los ciclos con condiciones, por lo que la iteración se produce secuencialmente.
+
+En primer lugar, dibujamos una tabla con categorías utilizando iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Mientras que `{foreach}` marca la parte exterior del ciclo, es decir, dibujar listas para cada categoría, la etiqueta `{iterateWhile}` marca la parte interior, es decir, los elementos individuales.
+La condición en la etiqueta final dice que la repetición continuará mientras el elemento actual y el siguiente pertenezcan a la misma categoría (`$iterator->nextValue` es [el siguiente elemento |/tags#$iterator]).
+
+Si la condición se cumpliera siempre, todos los elementos se dibujarían en el ciclo interior:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+El resultado tendrá este aspecto:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+¿Para qué sirve iterateWhile de esta manera? Cuando la tabla está vacía y no contiene elementos, no se imprime ningún empty `<ul></ul>` se imprime.
+
+Si especificamos la condición en la etiqueta de apertura `{iterateWhile}`, el comportamiento cambia: la condición (y la transición al siguiente elemento) se realiza al principio del ciclo interno, no al final.
+Así, mientras que siempre se entra en `{iterateWhile}` sin condiciones, sólo se entra en `{iterateWhile $cond}` cuando se cumple la condición `$cond`. Y al mismo tiempo, el siguiente elemento se escribe en `$item`.
+
+Esto es útil, por ejemplo, en una situación en la que queremos renderizar el primer elemento de cada categoría de forma diferente, así:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Modificamos el código original para que primero rendericemos el primer elemento y luego en el ciclo interno `{iterateWhile}` rendericemos los demás elementos de la misma categoría:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Dentro de un mismo ciclo, podemos crear varios bucles internos e incluso anidarlos. De esta forma, se podrían agrupar subcategorías, por ejemplo.
+
+Supongamos que la tabla tiene otra columna `subcategoryId`, y además de que cada categoría está en una separada `<ul>`cada subcategoría en un `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/es/cookbook/iteratewhile.texy b/latte/es/cookbook/iteratewhile.texy
deleted file mode 100644
index 80e27fc269..0000000000
--- a/latte/es/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Todo lo que siempre quiso saber sobre {iterateWhile}
-****************************************************
-
-.[perex]
-La etiqueta `{iterateWhile}` es adecuada para varios trucos en ciclos foreach.
-
-Supongamos que tenemos la siguiente tabla de base de datos, donde los elementos se dividen en categorías:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Por supuesto, dibujar elementos en un bucle foreach como una lista es fácil:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Pero, ¿qué hacer si se desea representar cada categoría en una lista separada? En otras palabras, cómo resolver la tarea de agrupar elementos de una lista lineal en un ciclo foreach. La salida debería tener este aspecto:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Le mostraremos con qué facilidad y elegancia se puede resolver la tarea con iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Mientras que `{foreach}` marca la parte externa del ciclo, es decir, el dibujo de las listas para cada categoría, las etiquetas `{iterateWhile}` indican la parte interna, es decir, los elementos individuales.
-La condición en la etiqueta final dice que la repetición continuará mientras el elemento actual y el siguiente pertenezcan a la misma categoría (`$iterator->nextValue` es [siguiente elemento |/tags#$iterator]).
-
-Si la condición se cumple siempre, todos los elementos se dibujan en el ciclo interior:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-El resultado tendrá este aspecto:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-¿Para qué sirve este uso de iterateWhile? ¿En qué se diferencia de la solución que mostramos al principio de este tutorial? La diferencia es que si la tabla está vacía y no contiene ningún elemento, no se mostrará vacía `<ul></ul>`.
-
-
-Solución sin `{iterateWhile}` .[#toc-solution-without-iteratewhile]
--------------------------------------------------------------------
-
-Si resolviéramos la misma tarea con construcciones completamente básicas de sistemas de plantillas, por ejemplo en Twig, Blade, o PHP puro, la solución sería algo así:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-Sin embargo, este código es incomprensible y poco intuitivo. La conexión entre las etiquetas HTML de apertura y cierre no está nada clara. No está claro a primera vista si hay un error. Y requiere variables auxiliares como `$prevCatId`.
-
-En cambio, la solución con `{iterateWhile}` es limpia, clara, no necesita variables auxiliares y es infalible.
-
-
-Condición en la etiqueta de cierre .[#toc-condition-in-the-closing-tag]
------------------------------------------------------------------------
-
-Si especificamos una condición en la etiqueta de apertura `{iterateWhile}`, el comportamiento cambia: la condición (y el avance al elemento siguiente) se ejecuta al principio del ciclo interno, no al final.
-Así, mientras que `{iterateWhile}` sin condición se introduce siempre, `{iterateWhile $cond}` se introduce sólo cuando se cumple la condición `$cond`. Al mismo tiempo, el siguiente elemento se escribe en `$item`.
-
-Esto es útil, por ejemplo, en una situación en la que se desea renderizar el primer elemento de cada categoría de una forma diferente, como:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Modifiquemos el código original, dibujamos el primer elemento y luego los elementos adicionales de la misma categoría en el bucle interno `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Bucles anidados .[#toc-nested-loops]
-------------------------------------
-
-Podemos crear varios bucles internos en un ciclo e incluso anidarlos. De esta forma, por ejemplo, se podrían agrupar subcategorías.
-
-Supongamos que hay otra columna en la tabla `subCatId` y además de que cada categoría esté en una separada `<ul>`, cada subcategoría estará en un `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtro |batch .[#toc-filter-batch]
-----------------------------------
-
-La agrupación de elementos lineales también se realiza mediante un filtro `batch`, en lotes con un número fijo de elementos:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Puede sustituirse por iterateWhile de la siguiente manera:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/es/cookbook/passing-variables.texy b/latte/es/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..be15f636a0
--- /dev/null
+++ b/latte/es/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Paso de variables entre plantillas
+**********************************
+
+Esta guía explica cómo se pasan variables entre plantillas en Latte usando varias etiquetas como `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}`, y otras. También aprenderá cómo trabajar con variables en las etiquetas `{block}` y `{define}`, y el propósito de la etiqueta `{parameters}`.
+
+
+Tipos de variables .[#toc-types-of-variables]
+---------------------------------------------
+Las variables en Latte pueden dividirse en tres categorías en función de cómo y dónde se definen:
+
+**Variables de entrada** son aquellas que se pasan a la plantilla desde fuera, por ejemplo, desde un script PHP o usando una etiqueta como `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Variables de entorno** son variables existentes en la ubicación de una etiqueta específica. Estas incluyen todas las variables de entrada y otras variables creadas usando etiquetas como `{var}`, `{default}`, o dentro de un bucle `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Variables explícitas** son las que se especifican directamente en una etiqueta y se envían a la plantilla de destino.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+La etiqueta `{block}` se utiliza para definir bloques de código reutilizables que pueden personalizarse o ampliarse en plantillas heredadas. Las variables circundantes definidas antes del bloque están disponibles dentro del bloque, pero cualquier cambio en las variables se refleja sólo dentro de ese bloque.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+La etiqueta `{define}` se utiliza para crear bloques que sólo se renderizan cuando se invocan mediante `{include}`. Las variables disponibles dentro de estos bloques dependen de si se especifican parámetros en la definición. Si se especifican parámetros, sólo se puede acceder a ellos. Si no, todas las variables de entrada de la plantilla en la que se definen los bloques son accesibles.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+La etiqueta `{parameters}` se utiliza para declarar explícitamente las variables de entrada esperadas al principio de la plantilla. De este modo, puede documentar fácilmente las variables esperadas y sus tipos de datos. También es posible definir valores por defecto.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+La etiqueta `{include file}` se utiliza para insertar una plantilla completa. A esta plantilla se le pasan tanto las variables de entrada de la plantilla en la que se utiliza la etiqueta como variables definidas explícitamente. Sin embargo, la plantilla de destino puede limitar el alcance utilizando `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Al insertar un bloque definido en la misma plantilla, se le pasan todas las variables circundantes y definidas explícitamente:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+En este ejemplo, las variables `$name` y `$age` se pasan al bloque `blockName`. El mismo comportamiento se aplica a `{include parent}`.
+
+Al insertar un bloque desde otra plantilla, sólo se pasan las variables de entrada y las definidas explícitamente. Las variables circundantes no están disponibles automáticamente.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` o `{extends}`
+------------------------
+Estas etiquetas definen un diseño al que se pasan las variables de entrada de la plantilla hija y las variables creadas en el código antes de los bloques:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Plantilla `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+La etiqueta `{embed}` es similar a la etiqueta `{include}` pero permite incrustar bloques en la plantilla. A diferencia de `{include}`, sólo se pasan variables declaradas explícitamente:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+En este ejemplo, la plantilla `menu.latte` sólo tiene acceso a la variable `$items`.
+
+Por el contrario, los bloques dentro de `{embed}` tienen acceso a todas las variables circundantes:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+La etiqueta `{import}` se utiliza para cargar bloques de otras plantillas. Tanto las variables de entrada como las declaradas explícitamente se pasan a los bloques importados.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+La etiqueta `{sandbox}` aísla la plantilla para un procesamiento seguro. Las variables se pasan exclusivamente de forma explícita.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/es/creating-extension.texy b/latte/es/creating-extension.texy
index 90f18eb08f..80efc46276 100644
--- a/latte/es/creating-extension.texy
+++ b/latte/es/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// a parsing function that just creates a node for now
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+NodoAuxiliar .[#toc-auxiliarynode]
+----------------------------------
+
+Si está creando una nueva etiqueta para Latte, es aconsejable crear una clase de nodo dedicada para ella, que la representará en el árbol AST (véase la clase `ForeachNode` en el ejemplo anterior). En algunos casos, puede resultarle útil la clase de nodo auxiliar [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], que le permite pasar el cuerpo del método `print()` y la lista de nodos accesibles por el método `getIterator()` como parámetros del constructor:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 El compilador pasa .[#toc-compiler-passes]
 ==========================================
 
diff --git a/latte/es/develop.texy b/latte/es/develop.texy
index 83802ea072..01b100ae14 100644
--- a/latte/es/develop.texy
+++ b/latte/es/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Localidad .[#toc-locale]{data-version:3.0.18}
+=============================================
+
+Latte le permite establecer la configuración regional, que afecta al formato de los números, las fechas y la ordenación. Se establece usando el método `setLocale()`. El identificador de configuración regional sigue el estándar de etiquetas de idioma IETF, que utiliza la extensión PHP `intl`. Consiste en un código de idioma y posiblemente un código de país, por ejemplo, `en_US` para inglés en los Estados Unidos, `de_DE` para alemán en Alemania, etc.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+La configuración regional afecta a los filtros [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] y [bytes |filters#bytes].
+
+.[note]
+Requiere la extensión PHP `intl`. La configuración de Latte no afecta a la configuración regional global de PHP.
+
+
 Modo estricto .[#toc-strict-mode]{data-version:3.0.8}
 =====================================================
 
@@ -274,16 +290,25 @@ Si utiliza etiquetas personalizadas, cree también su Linter personalizado, por
 // introduzca la ruta real al archivo autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// añada aquí las extensiones individuales
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// añada aquí sus extensiones individuales
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternativamente, puede pasar su propio objeto `Latte\Engine` al Linter:
+
+```php
+$latte = new Latte\Engine;
+// aquí configuramos el objeto $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Carga de plantillas desde una cadena .[#toc-loading-templates-from-a-string]
 ============================================================================
diff --git a/latte/es/extending-latte.texy b/latte/es/extending-latte.texy
index 9f475d670d..cb4897a733 100644
--- a/latte/es/extending-latte.texy
+++ b/latte/es/extending-latte.texy
@@ -68,6 +68,16 @@ Como puede ver, la función recibe la parte izquierda del filtro antes de la tub
 
 Por supuesto, la función que representa el filtro puede aceptar cualquier número de parámetros, y también se admiten parámetros variádicos.
 
+Si el filtro devuelve una cadena en HTML, puede marcarla para que Latte no la escape automáticamente (y por tanto por partida doble). Esto evita la necesidad de especificar `|noescape` en la plantilla.
+La forma más fácil es envolver la cadena en un objeto `Latte\Runtime\Html`, la otra forma es [Filtros contextuales |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+En este caso, el filtro debe garantizar el correcto escape de los datos.
+
 
 Filtros que utilizan la clase .[#toc-filters-using-the-class]
 -------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// change content-type to HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/es/filters.texy b/latte/es/filters.texy
index 81479c86c3..c3d1c9b925 100644
--- a/latte/es/filters.texy
+++ b/latte/es/filters.texy
@@ -11,14 +11,16 @@ Los filtros son funciones que cambian o formatean los datos de la forma que quer
 | `bytes` | [formatea el tamaño en bytes |#bytes]
 | `clamp` | [sujeta el valor al rango|#clamp]
 | `dataStream` | [Conversión de protocolo URI de datos|#datastream]
-| `date` | [Formatea la fecha |#date]
+| `date` | [formatea la fecha y la hora |#date]
 | `explode` | [divide una cadena por el delimitador dado |#explode]
 | `first` | [devuelve el primer elemento de una matriz o carácter de una cadena |#first]
+| `group` | [agrupa los datos según varios criterios |#group]
 | `implode` | [une una matriz a una cadena |#implode]
 | `indent` | [sangrar el texto desde la izquierda con un número de tabulaciones |#indent]
 | `join` | [une una matriz con una cadena|#implode]
 | `last` | [devuelve el último elemento de la matriz o carácter de la cadena |#last]
 | `length` | [devuelve la longitud de una cadena o matriz |#length]
+| `localDate` | [formatea la fecha y la hora según la configuración regional |#localDate]
 | `number` | [Formatea un número |#number]
 | `padLeft` | [completa la cadena a la longitud dada desde la izquierda |#padLeft]
 | `padRight` | [completa la cadena a la longitud dada desde la derecha|#padRight]
@@ -118,8 +120,8 @@ Filtros .[#toc-filters]
 =======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filtro que simplifica el listado de datos lineales en forma de tabla. Devuelve un array de array con el número de elementos dado. Si se proporciona un segundo parámetro, éste se utiliza para rellenar los elementos que faltan en la última fila.
 
 ```latte
@@ -152,6 +154,8 @@ Imprime:
 </table>
 ```
 
+Ver también [grupo |#group] y etiqueta [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Inserta saltos de línea HTML antes de todas las nuevas líneas.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formatea un tamaño en bytes a formato legible por humanos.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formatea el tamaño en bytes de forma legible. Si se establece la [configuración regional |develop#locale], se utilizan los separadores decimales y de miles correspondientes.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formatea un tamaño en bytes a formato legible por humanos.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Redondea un número hasta una precisión dada.
 
 ```latte
@@ -203,8 +207,8 @@ Aplica la limpieza de URL. Comprueba si la variable contiene una URL web (es dec
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Imprime:
@@ -217,8 +221,8 @@ Imprime:
 Véase también [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Devuelve el valor ajustado al rango inclusivo de mín y máx.
 
 ```latte
@@ -228,14 +232,14 @@ Devuelve el valor ajustado al rango inclusivo de mín y máx.
 También existe como [función |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Convierte el contenido en un esquema URI de datos. Puede utilizarse para insertar imágenes en HTML o CSS sin necesidad de enlazar archivos externos.
 
 Tengamos una imagen en una variable `$img = Image::fromFile('obrazek.gif')`, entonces
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Imprime por ejemplo
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Requiere extensión PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Devuelve una fecha en el formato dado usando las opciones de las funciones PHP [php:strftime] o [php:date]. Filter obtiene una fecha como una marca de tiempo UNIX, una cadena o un objeto de tipo `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formatea la fecha y la hora según la máscara utilizada por la función de PHP [php:date]. El filtro acepta la fecha en formato UNIX timestamp, como cadena o como objeto `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Véase también [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Escapa una variable para ser usada como parámetro en URL.
 Véase también [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Divide una cadena por el delimitador dado y devuelve una matriz de cadenas. Alias de `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Devuelve el primer elemento de un array o carácter de una cadena:
 Ver también [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Redondea un número a una precisión dada.
 
 ```latte
@@ -330,8 +335,27 @@ Convierte la primera letra de un valor a mayúsculas. Requiere la extensión PHP
 Vea también [capitalize |#capitalize], [lower |#lower], [upper |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+El filtro agrupa los datos según diferentes criterios.
+
+En este ejemplo, las filas de la tabla se agrupan por la columna `categoryId`. La salida es un array de arrays donde la clave es el valor de la columna `categoryId`. Lea las [instrucciones detalladas |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Véase también [batch |#batch], la función [group |functions#group] y la etiqueta [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Devuelve una cadena que es la concatenación de las cadenas de la matriz. Alias de `join`.
 
 ```latte
@@ -346,8 +370,8 @@ También puede utilizar un alias `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Indenta un texto desde la izquierda un número determinado de tabulaciones u otros caracteres que especifiquemos en el segundo argumento opcional. Las líneas en blanco no se sangrarán.
 
 ```latte
@@ -396,6 +420,68 @@ Devuelve la longitud de una cadena o matriz.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formatea la fecha y la hora de acuerdo con la [configuración regional |develop#locale], lo que garantiza una visualización coherente y localizada de los datos de la hora en diferentes idiomas y regiones. El filtro acepta la fecha como marca de tiempo UNIX, cadena u objeto `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Si utiliza el filtro sin ningún parámetro, mostrará la fecha en el nivel de formato largo, como se explica más adelante.
+
+**a) Utilización del formato**
+
+El parámetro `format` describe qué componentes horarios deben mostrarse. Utiliza códigos de letras, en los que el número de repeticiones afecta a la anchura de la salida:
+
+| Año | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Mes | `M` / `MM` / `MMM`, `MMMM` | `8` / `08` / `ago` / `agosto`
+| Día | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `dom` / `domingo`
+| Hora | `j` / `H` / `h` | preferido / 24 horas / 12 horas
+| Minuto | `m` / `mm` | `5` / `05` <small>(2 dígitos cuando se combinan con segundos)</small>
+| Segundo | `s` / `ss` | `8` / `08` <small>(2 dígitos cuando se combinan con minutos)</small>
+
+El orden de los códigos en el formato no importa, ya que el orden de los componentes se mostrará según las convenciones de la configuración regional. Por lo tanto, el formato es independiente de la configuración regional. Por ejemplo, el formato `yyyyMMMMd` en la localización `en_US` produce `April 15, 2024`, mientras que en la localización `cs_CZ` produce `15. dubna 2024`:
+
+| locale:  | es-ES | en_US
+|---
+| `format: 'dMy'` | 10/8/2024 | 8/10/2024
+| `format: 'yM'` | 8/2024 | 8/2024
+| `format: 'yyyyMMMM'` | agosto de 2024 | August 2024
+| `format: 'MMMM'` | agosto | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 p. m. | 5:54 PM
+
+
+**b) Utilización de estilos predefinidos**
+
+Los parámetros `date` y `time` determinan el nivel de detalle de la visualización de la fecha y la hora. Puede elegir entre varios niveles: `full`, `long`, `medium`, `short`. Puede mostrar sólo la fecha, sólo la hora o ambas:
+
+| locale:  | es-ES | en_US
+|---
+| `date: short` | 23/1/78 | 1/23/78
+| `date: medium` | 23 ene 1978 | Jan 23, 1978
+| `date: long` | 23 de enero de 1978 | January 23, 1978
+| `date: full` | lunes, 23 de enero de 1978 | Monday, January 23, 1978
+| `time: short` | 8:30 | 8:30 AM
+| `time: medium` | 8:30:59 | 8:30:59 AM
+| `time: long` | 8:30:59 CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23/1/78, 8:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 ene 1978, 8:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 de enero de 1978, 8:30 | January 23, 1978 at 8:30 AM
+
+Para la fecha, también puede utilizar el prefijo `relative-` (por ejemplo, `relative-short`), que para fechas cercanas al presente mostrará `yesterday`, `today`, o `tomorrow`; de lo contrario, se mostrará de la forma estándar.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Véase también [fecha |#date].
+
+
 lower .[filter]
 ---------------
 Convierte un valor a minúsculas. Requiere la extensión PHP `mbstring`.
@@ -416,8 +502,8 @@ Si el enlace utiliza un esquema diferente, como `javascript:` o `data:`, y está
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Imprime:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 ¡El mal uso del filtro `noescape` puede llevar a una vulnerabilidad XSS! Nunca lo utilices a menos que estés **absolutamente seguro** de lo que estás haciendo y de que la cadena que estás imprimiendo proviene de una fuente de confianza.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formatea un número con un número dado de decimales. También puede especificar un carácter del punto decimal y del separador de miles.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formatea un número con el número de decimales especificado. Si se establece la [configuración regional |develop#locale], se utilizan los separadores decimales y de miles correspondientes.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Formatea un número con un número dado de decimales. También puede especificar
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+El parámetro `format` le permite definir la apariencia de los números exactamente según sus necesidades. Requiere una [configuración regional |develop#locale] establecida. El formato consta de varios caracteres especiales, cuya descripción completa puede encontrarse en la documentación "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> dígito obligatorio, se muestra siempre aunque sea cero
+- `#` dígito opcional, se muestra sólo si el número tiene un dígito en ese lugar
+- `@` dígito significativo, ayuda a mostrar el número con un cierto número de dígitos significativos
+- `.` marca dónde debe estar el separador decimal (coma o punto, según la configuración regional)
+- `,` se utiliza para separar grupos de dígitos, normalmente miles
+- `%` multiplica el número por 100 y añade el signo de porcentaje
+
+Veamos algunos ejemplos. En el primer ejemplo, los dos decimales son obligatorios; en el segundo, son opcionales. El tercer ejemplo muestra relleno con ceros a ambos lados, y el cuarto muestra sólo los dígitos existentes:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Los dígitos significativos determinan cuántos dígitos, independientemente del punto decimal, deben mostrarse, redondeando el número si es necesario:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Una forma sencilla de mostrar un número como porcentaje. El número se multiplica por 100 y se añade el signo `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Podemos definir un formato diferente para los números positivos y negativos, separados por un carácter `;`. Así, por ejemplo, los números positivos pueden mostrarse con el signo `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Recuerde que el aspecto real de los números puede variar en función de la configuración regional. Por ejemplo, en algunos países se utiliza una coma en lugar de un punto como separador decimal. Este filtro lo tiene en cuenta automáticamente, así que no tienes que preocuparte por ello.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Rellena una cadena de una longitud determinada con otra cadena de la izquierda.
 
@@ -472,7 +606,7 @@ Rellena una cadena de una longitud determinada con otra cadena de la izquierda.
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Rellena una cadena de cierta longitud con otra cadena de la derecha.
 
@@ -514,8 +648,8 @@ Devuelve un elemento aleatorio de una matriz o un carácter de una cadena:
 Véase también [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Repite la cadena x veces.
 
 ```latte
@@ -523,7 +657,7 @@ Repite la cadena x veces.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Sustituye todas las apariciones de la cadena de búsqueda por la cadena de sustitución.
 
@@ -538,7 +672,7 @@ Se pueden realizar varias sustituciones a la vez:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Reemplaza todas las ocurrencias según la expresión regular.
 
@@ -559,8 +693,8 @@ Invierte la cadena o matriz dada.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Redondea un número a una precisión dada.
 
 ```latte
@@ -573,7 +707,7 @@ Redondea un número a una precisión dada.
 Ver también [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Extrae una porción de una matriz o una cadena.
 
@@ -591,9 +725,9 @@ Si la longitud es positiva, la secuencia tendrá hasta ese número de elementos.
 Filter reordenará y restablecerá las claves de la matriz de enteros por defecto. Este comportamiento puede cambiarse estableciendo preserveKeys a true. Las claves de cadena siempre se conservan, independientemente de este parámetro.
 
 
-sort  .[filter]
----------------
-Filtro que ordena un array y mantiene la asociación de índices.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+El filtro ordena los elementos de un array o iterador conservando sus claves asociativas. Cuando se establece una [configuración regional |develop#locale], la ordenación sigue sus reglas a menos que se especifique una función de comparación personalizada.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Matriz ordenada en orden inverso.
 {/foreach}
 ```
 
-Puede pasar su propia función de comparación como parámetro:
+Puede especificar una función de comparación personalizada para la ordenación (el ejemplo muestra cómo invertir la ordenación de mayor a menor):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+El filtro `|sort` también permite ordenar los elementos por clave:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Si necesita ordenar una tabla por una columna específica, puede utilizar el parámetro `by`. El valor `'name'` en el ejemplo especifica que la ordenación se realizará por `$row->name` o `$row['name']`dependiendo de si `$row` es una matriz o un objeto:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+También puede definir una función de devolución de llamada que determine el valor por el que se ordenará:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+El parámetro `byKey` se puede utilizar de la misma manera.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Convierte HTML en texto sin formato. Es decir, elimina las etiquetas HTML y conv
 El texto plano resultante puede contener naturalmente caracteres que representen etiquetas HTML, por ejemplo `'&lt;p&gt;'|stripHtml` se convierte en `<p>`. Nunca envíe el texto resultante con `|noescape`, ya que esto puede dar lugar a una vulnerabilidad de seguridad.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Extrae una porción de una cadena. Este filtro ha sido sustituido por un filtro de [trozos |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ Extrae una porción de una cadena. Este filtro ha sido sustituido por un filtro
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Traduce expresiones a otros idiomas. Para que el filtro esté disponible, es necesario [configurar el traductor |develop#TranslatorExtension]. También puede utilizar las [etiquetas para la traducción |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Traduce expresiones a otros idiomas. Para que el filtro esté disponible, es nec
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Elimina los caracteres iniciales y finales, por defecto los espacios en blanco.
 
 ```latte
@@ -675,7 +835,7 @@ Elimina los caracteres iniciales y finales, por defecto los espacios en blanco.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Acorta una cadena a la longitud máxima dada, pero intenta conservar las palabras enteras. Si la cadena está truncada, añade elipsis al final (esto puede cambiarse con el segundo parámetro).
 
diff --git a/latte/es/functions.texy b/latte/es/functions.texy
index 84ce9d3a17..1fc8c04e2a 100644
--- a/latte/es/functions.texy
+++ b/latte/es/functions.texy
@@ -9,6 +9,8 @@ Además de las funciones comunes de PHP, también puede utilizarlas en plantilla
 | `divisibleBy`| [comprueba si una variable es divisible por un número |#divisibleBy]
 | `even` | [comprueba si el número dado es par |#even]
 | `first` | [devuelve el primer elemento de una matriz o un carácter de una cadena |#first]
+| `group` | [agrupa los datos según varios criterios |#group]
+| `hasBlock` | [detecta la existencia de un bloque |#hasBlock]
 | `last` | [devuelve el último elemento de la matriz o carácter de la cadena|#last]
 | `odd` | [comprueba si el número dado es impar|#odd]
 | `slice` | [extrae un trozo de una matriz o de una cadena |#slice]
@@ -73,8 +75,8 @@ Comprueba si el número dado es par.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Devuelve el primer elemento de un array o carácter de una cadena:
 
 ```latte
@@ -85,6 +87,36 @@ Devuelve el primer elemento de un array o carácter de una cadena:
 Véase también [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Esta función agrupa los datos según diferentes criterios.
+
+En este ejemplo, las filas de la tabla se agrupan por la columna `categoryId`. La salida es una matriz de campos donde la clave es el valor de la columna `categoryId`. Lea las [instrucciones detalladas |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Véase también [grupo de |filters#group] filtros.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Comprueba si existe el bloque del nombre especificado:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Véase también [comprobación |template-inheritance#Checking Block Existence] de existencia de bloque.
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Devuelve el último elemento del array o carácter de la cadena:
@@ -106,8 +138,8 @@ Comprueba si el número dado es impar.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Extrae una porción de un array o de una cadena.
 
 ```latte
diff --git a/latte/es/recipes.texy b/latte/es/recipes.texy
index 1774ae053f..270aa6f68a 100644
--- a/latte/es/recipes.texy
+++ b/latte/es/recipes.texy
@@ -9,7 +9,7 @@ Escriba plantillas en un editor o IDE que tenga soporte para Latte. Será mucho
 
 - NetBeans IDE tiene soporte incorporado
 - PhpStorm: instale el [plugin |https://plugins.jetbrains.com/plugin/7457-latte] Latte en `Settings > Plugins > Marketplace`
-- VS Code: busque en markerplace el plugin "Nette Latte + Neon
+- VS Code: busque en markerplace el plugin de [plantillas |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] o [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Sublime Text 3: en Package Control busque e instale el paquete `Nette` y seleccione Latte en `View > Syntax`
 - en editores antiguos utilice Smarty para resaltar los archivos .latte
 
diff --git a/latte/es/safety-first.texy b/latte/es/safety-first.texy
index 5f70f5225d..4669fe47f3 100644
--- a/latte/es/safety-first.texy
+++ b/latte/es/safety-first.texy
@@ -351,7 +351,7 @@ Latte comprueba automáticamente si la variable utilizada en los atributos `src`
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Escribe:
diff --git a/latte/es/syntax.texy b/latte/es/syntax.texy
index 54e1ea2fcc..2e4e2bacce 100644
--- a/latte/es/syntax.texy
+++ b/latte/es/syntax.texy
@@ -98,7 +98,7 @@ Imprime:
 O utilizando `tag-` prefijo la funcionalidad se aplica en las etiquetas HTML solamente:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Dependiendo del valor de la variable `$url` se imprimirá:
@@ -155,6 +155,20 @@ O directamente sobre el valor (en combinación con [`{=expr}` | https://latte.ne
 ```
 
 
+Etiquetas HTML dinámicas .[#toc-dynamic-html-tags]
+==================================================
+
+Latte soporta etiquetas HTML dinámicas, que son útiles cuando se necesita flexibilidad en los nombres de las etiquetas:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Por ejemplo, el código anterior puede generar `<h1>Heading</h1>` o `<h2>Heading</h2>` en función del valor de la variable `$level`. Las etiquetas HTML dinámicas en Latte deben ir siempre emparejadas. Su alternativa es la [n:tag |tags#n:tag].
+
+Como Latte es un sistema de plantillas seguro, comprueba que el nombre de la etiqueta resultante sea válido y no contenga valores no deseados o maliciosos. También se asegura de que el nombre de la etiqueta final sea siempre el mismo que el de la etiqueta inicial.
+
+
 Comentarios .[#toc-comments]
 ============================
 
diff --git a/latte/es/tags.texy b/latte/es/tags.texy
index 26ab3fbe9d..03b5692ec5 100644
--- a/latte/es/tags.texy
+++ b/latte/es/tags.texy
@@ -16,6 +16,7 @@ Resumen y descripción de todas las etiquetas Latte incorporadas.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [condición ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [prueba si ha habido un cambio |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default]
+| `n:else` | [contenido alternativo para las condiciones |#n:else]
 
 .[table-latte-tags language-latte]
 |## Bucles
@@ -97,8 +98,8 @@ Resumen y descripción de todas las etiquetas Latte incorporadas.
 | `{link}` | [imprime un enlace |application:creating-links#In the Presenter Template]
 | `{plink}` | [imprime un enlace a un [presentador |application:creating-links#In the Presenter Template]
 | `{control}` | [imprime un componente |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [un fragmento de plantilla que puede ser enviado por AJAX |application:ajax#tag-snippet]
-| `{snippetArea}` | snippets sobre
+| `{snippet}`... `{/snippet}` | [un fragmento de plantilla que puede ser enviado por AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [snippets sobre |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [almacena en caché una sección de plantilla|caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Resumen y descripción de todas las etiquetas Latte incorporadas.
 | `{input}` | [imprime un elemento del formulario|forms:rendering#label-input]
 | `{inputError}` | [imprime un mensaje de error para el elemento de entrada del formulario|forms:rendering#inputError]
 | `n:name` | [activa un elemento de entrada HTML |forms:rendering#n:name]
-| `{formPrint}` | [genera un modelo de formulario Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [imprime la clase PHP para los datos del formulario |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [renderización parcial del formulario|forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [renderización del contenedor de formularios |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Como cualquier etiqueta de par, un par de `{if} ... {/ if}` puede escribirse com
 Bien.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Si escribe la condición `{if} ... {/if}` en forma de [atributo n: |syntax#n:attributes]tiene la opción de especificar una rama alternativa utilizando `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+El atributo `n:else` también puede utilizarse junto con [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]y [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Véase también [`{ifset block}` |template-inheritance#checking-block-existence]
 Utilice la condición `{ifset $var}` para determinar si una variable (o múltiples variables) existe y tiene un valor no nulo. En realidad es lo mismo que `if (isset($var))` en PHP. Como cualquier etiqueta de par, esto puede ser escrito en la forma de [n:attribute |syntax#n:attributes], así que vamos a mostrarlo en el ejemplo:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Es bastante práctico, ¿no?
 `{iterateWhile}`
 ----------------
 
-Simplifica la agrupación de datos lineales durante la iteración en un bucle foreach realizando la iteración en un bucle anidado mientras se cumpla la condición. [Lee las instrucciones en el cookbook |cookbook/iteratewhile].
+Simplifica la agrupación de datos lineales durante la iteración en un bucle foreach iterando en un bucle anidado hasta que se cumpla una condición. [Lea las instrucciones detalladas |cookbook/grouping].
 
 También puede sustituir elegantemente a `{first}` y `{last}` en el ejemplo anterior:
 
@@ -489,6 +501,8 @@ También puede sustituir elegantemente a `{first}` y `{last}` en el ejemplo ante
 {/foreach}
 ```
 
+Véase también filtros [por lotes |filters#batch] y [grupos |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Si `$heading === null`, la etiqueta `<h1>` se imprime sin cambios. De lo contrar
 <h3 class="main">...</h3>
 ```
 
+Como Latte es un sistema de plantillas seguro, comprueba que el nuevo nombre de la etiqueta sea válido y no contenga valores no deseados o maliciosos.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/es/template-inheritance.texy b/latte/es/template-inheritance.texy
index 3e9e0c3f62..df83b0277c 100644
--- a/latte/es/template-inheritance.texy
+++ b/latte/es/template-inheritance.texy
@@ -132,7 +132,7 @@ Aquí tienes algunos consejos para trabajar con la herencia de diseños:
 
 - Si utiliza `{layout}` en una plantilla, debe ser la primera etiqueta de plantilla en esa plantilla.
 
-- La maquetación puede [buscarse automáticamente |develop#automatic-layout-lookup] (como en [los presentadores |application:templates#search-for-templates]). En este caso, si la plantilla no debe tener un diseño, lo indicará con la etiqueta `{layout none}`.
+- La maquetación puede [buscarse automáticamente |develop#automatic-layout-lookup] (como en [los presentadores |application:templates#Template Lookup]). En este caso, si la plantilla no debe tener un diseño, lo indicará con la etiqueta `{layout none}`.
 
 - La etiqueta `{layout}` tiene el alias `{extends}`.
 
@@ -396,6 +396,14 @@ Puede utilizar una variable o cualquier expresión en PHP como nombre del bloque
 {/ifset}
 ```
 
+La existencia de bloques también se devuelve mediante la función [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Consejos .[#toc-tips]
 ---------------------
@@ -415,7 +423,7 @@ Aquí tienes algunos consejos para trabajar con bloques:
 Reutilización horizontal `{import}` .{toc: Horizontal Reuse}
 ============================================================
 
-La reutilización horizontal es un tercer mecanismo de reutilización y herencia en Latte. Permite cargar bloques de otras plantillas. Es similar a crear un archivo PHP con funciones de ayuda o un trait.
+La reutilización horizontal es el tercer mecanismo de reutilización y herencia en Latte. Permite cargar bloques de otras plantillas. Es similar a crear un archivo con funciones de ayuda en PHP y luego cargarlo usando `require`.
 
 Aunque la herencia del diseño de las plantillas es una de las características más potentes de Latte, está limitada a la herencia simple: una plantilla sólo puede extender a otra plantilla. La reutilización horizontal es una forma de lograr una herencia múltiple.
 
@@ -447,7 +455,7 @@ La etiqueta `{import}` debe ser la primera etiqueta de plantilla después de `{l
 
 Puede utilizar tantas expresiones `{import}` como desee en una plantilla determinada. Si dos plantillas importadas definen el mismo bloque, gana la primera. Sin embargo, la mayor prioridad la tiene la plantilla principal, que puede sobrescribir cualquier bloque importado.
 
-Todos los bloques sobrescritos pueden incluirse gradualmente insertándolos como [bloque padre |#parent block]:
+El contenido de los bloques sobrescritos puede conservarse insertando el bloque del mismo modo que un [bloque padre |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/fr/@left-menu.texy b/latte/fr/@left-menu.texy
index 16e8f0c1d9..a5ada95b21 100644
--- a/latte/fr/@left-menu.texy
+++ b/latte/fr/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Mise en route |Guide]
 - [Pourquoi utiliser des modèles ? |why-use]
-- Concepts
+- Concepts ⚗️
 	- [Sécurité d'abord |Safety First]
 	- [Héritage des modèles |Template Inheritance]
 	- [Système de types |Type System]
 	- [Bac à sable |Sandbox]
 
-- Pour les concepteurs
+- Pour les concepteurs 🎨
 	- [Syntaxe |Syntax]
 	- [Marqueurs |Tags]
 	- [Filtres |Filters]
 	- [Fonctions |Functions]
 	- [Conseils et astuces |recipes]
 
-- Pour les développeurs
+- Pour les développeurs 🧮
 	- [Pratiques pour les développeurs |develop]
 	- [Extension de Latte |Extending Latte]
 	- [Créer une extension |creating-extension]
 
-- [Livre de recettes |cookbook/@home]
+- [Livre de recettes 💡|cookbook/@home]
 	- [Migration depuis Twig |cookbook/migration-from-twig]
 	- [... plus |cookbook/@home]
 
diff --git a/latte/fr/cookbook/@home.texy b/latte/fr/cookbook/@home.texy
index 962867ecfc..5dd9546e98 100644
--- a/latte/fr/cookbook/@home.texy
+++ b/latte/fr/cookbook/@home.texy
@@ -4,7 +4,9 @@ Livre de cuisine
 .[perex]
 Exemples de codes et de recettes pour accomplir des tâches courantes avec Latte.
 
-- [Tout ce que vous avez toujours voulu savoir sur {iterateWhile} |iteratewhile]
+- [Lignes directrices à l'intention des développeurs |/develop]
+- [Passage de variables entre modèles |passing-variables]
+- [Tout ce que vous avez toujours voulu savoir sur le regroupement |grouping]
 - [Comment écrire des requêtes SQL dans Latte ? |how-to-write-sql-queries-in-latte]
 - [Migration depuis PHP |migration-from-php]
 - [Migration depuis Twig |migration-from-twig]
diff --git a/latte/fr/cookbook/grouping.texy b/latte/fr/cookbook/grouping.texy
new file mode 100644
index 0000000000..0a091fe862
--- /dev/null
+++ b/latte/fr/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Tout ce que vous avez toujours voulu savoir sur le regroupement
+***************************************************************
+
+.[perex]
+Lorsque vous travaillez avec des données dans des modèles, vous rencontrez souvent le besoin de les grouper ou de les afficher spécifiquement selon certains critères. Latte propose à cet effet plusieurs outils puissants.
+
+Le filtre et la fonction `|group` permettent de regrouper efficacement les données sur la base de critères spécifiques, tandis que le filtre `|batch` facilite la division des données en lots fixes et que la balise `{iterateWhile}` offre la possibilité d'un contrôle de cycle plus complexe à l'aide de conditions.
+Chacune de ces balises offre des options spécifiques pour travailler avec les données, ce qui en fait des outils indispensables pour l'affichage dynamique et structuré des informations dans les modèles Latte.
+
+
+Filtre et fonction `group` .[#toc-filter-and-function-group]
+============================================================
+
+Imaginez une table de base de données `items` avec des articles divisés en catégories :
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Pomme
+| 2 | 1 | Banane
+| 3 | 2 | PHP
+| 4 | 3 | Vert
+| 5 | 3 | Rouge
+| 6 | 3 | Bleu
+
+Une liste simple de tous les éléments utilisant un modèle Latte ressemblerait à ceci :
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Toutefois, si nous voulons que les articles soient organisés en groupes par catégorie, nous devons les diviser de manière à ce que chaque catégorie ait sa propre liste. Le résultat serait alors le suivant :
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Cette tâche peut être facilement et élégamment résolue en utilisant `|group`. Nous spécifions `categoryId` comme paramètre, ce qui signifie que les éléments seront divisés en tableaux plus petits en fonction de la valeur de `$item->categoryId` (si `$item` était un tableau, nous utiliserions `$item['categoryId']`) :
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Le filtre peut également être utilisé comme une fonction dans Latte, ce qui nous donne une syntaxe alternative : `{foreach group($items, categoryId) ...}`.
+
+Si vous souhaitez regrouper des éléments selon des critères plus complexes, vous pouvez utiliser une fonction dans le paramètre du filtre. Par exemple, le regroupement des éléments en fonction de la longueur de leur nom ressemblerait à ceci :
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Il est important de noter que `$categoryItems` n'est pas un tableau ordinaire, mais un objet qui se comporte comme un itérateur. Pour accéder au premier élément du groupe, vous pouvez utiliser la fonction [`first()` |latte:functions#first] pour accéder au premier élément du groupe.
+
+Cette flexibilité dans le regroupement des données fait de `group` un outil exceptionnellement utile pour présenter les données dans les modèles Latte.
+
+
+Boucles imbriquées .[#toc-nested-loops]
+---------------------------------------
+
+Supposons que nous ayons une table de base de données avec une autre colonne `subcategoryId` qui définit les sous-catégories pour chaque article. Nous voulons afficher chaque catégorie principale dans une liste distincte et chaque sous-catégorie dans une boucle imbriquée distincte. `<ul>` distincte et chaque sous-catégorie dans une liste imbriquée distincte `<ol>` imbriquée :
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Connexion avec la base de données Nette .[#toc-connection-with-nette-database]
+------------------------------------------------------------------------------
+
+Montrons comment utiliser efficacement le regroupement de données en combinaison avec Nette Database. Supposons que nous travaillions avec la table `items` de l'exemple initial, qui est connectée par la colonne `categoryId` à cette table `categories`:
+
+| CatégorieId | Nom |
+|------------|------------|
+| 1 | Fruits |
+| 2 | Langues |
+| 3 | Couleurs |
+
+Nous chargeons les données de la table `items` à l'aide de la commande Nette Database Explorer `$items = $db->table('items')`. Au cours de l'itération sur ces données, nous avons la possibilité non seulement d'accéder à des attributs tels que `$item->name` et `$item->categoryId`, mais aussi, grâce à la connexion avec la table `categories`, à la ligne correspondante de cette table via `$item->category`. Cette connexion peut donner lieu à des utilisations intéressantes :
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Dans ce cas, nous utilisons le filtre `|group` pour regrouper les données en fonction de la ligne connectée `$item->category`, et pas seulement en fonction de la colonne `categoryId`. Nous obtenons ainsi le site `ActiveRow` de la catégorie donnée dans la clé variable, ce qui nous permet d'afficher directement son nom à l'aide de `{$category->name}`. Il s'agit d'un exemple pratique de la manière dont le regroupement peut simplifier les modèles et faciliter la manipulation des données.
+
+
+Filtre `|batch` .[#toc-filter-batch]
+====================================
+
+Le filtre vous permet de diviser une liste d'éléments en groupes avec un nombre prédéterminé d'éléments. Ce filtre est idéal pour les situations où vous souhaitez présenter des données en plusieurs groupes plus petits, par exemple pour une meilleure clarté ou une meilleure organisation visuelle sur la page.
+
+Imaginons que nous ayons une liste d'éléments et que nous souhaitions les afficher dans des listes contenant chacune un maximum de trois éléments. L'utilisation du filtre `|batch` est très pratique dans ce cas :
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+Dans cet exemple, la liste `$items` est divisée en groupes plus petits, chaque groupe (`$batch`) contenant jusqu'à trois éléments. Chaque groupe est ensuite affiché dans une liste `<ul>` liste séparée.
+
+Si le dernier groupe ne contient pas suffisamment d'éléments pour atteindre le nombre souhaité, le deuxième paramètre du filtre vous permet de définir ce qui viendra compléter ce groupe. Ceci est idéal pour aligner esthétiquement les éléments là où une ligne incomplète pourrait paraître désordonnée.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Étiquette `{iterateWhile}` .[#toc-tag-iteratewhile]
+===================================================
+
+Nous allons démontrer les mêmes tâches que nous avons abordées avec le filtre `|group` en utilisant la balise `{iterateWhile}`. La principale différence entre les deux approches est que `group` traite et regroupe d'abord toutes les données d'entrée, tandis que `{iterateWhile}` contrôle la progression des cycles avec des conditions, de sorte que l'itération se produit de manière séquentielle.
+
+Tout d'abord, nous dessinons un tableau avec des catégories en utilisant iterateWhile :
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Alors que `{foreach}` marque la partie extérieure du cycle, c'est-à-dire l'établissement de listes pour chaque catégorie, la balise `{iterateWhile}` marque la partie intérieure, c'est-à-dire les éléments individuels.
+La condition de la balise end indique que la répétition se poursuivra tant que l'élément actuel et l'élément suivant appartiennent à la même catégorie (`$iterator->nextValue` est l'[élément suivant |/tags#$iterator]).
+
+Si la condition était toujours remplie, tous les éléments seraient dessinés dans le cycle interne :
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Le résultat sera le suivant :
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Quelle est l'utilité de iterateWhile dans ce cas ? Lorsque le tableau est vide et ne contient pas d'éléments, le message empty `<ul></ul>` n'est imprimée.
+
+Si nous spécifions la condition dans la balise d'ouverture `{iterateWhile}`, le comportement change : la condition (et la transition vers l'élément suivant) est exécutée au début du cycle interne, et non à la fin.
+Ainsi, alors que vous entrez toujours dans `{iterateWhile}` sans condition, vous n'entrez dans `{iterateWhile $cond}` que lorsque la condition `$cond` est remplie. Au même moment, l'élément suivant est écrit dans `$item`.
+
+Ceci est utile, par exemple, dans une situation où nous voulons rendre le premier élément de chaque catégorie différemment, comme ceci :
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Nous modifions le code original de manière à rendre d'abord le premier élément, puis, dans le cycle interne `{iterateWhile}`, les autres éléments de la même catégorie :
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Au sein d'un cycle, nous pouvons créer plusieurs boucles internes et même les imbriquer. De cette manière, les sous-catégories peuvent être regroupées, par exemple.
+
+Supposons que le tableau comporte une autre colonne `subcategoryId`, et que, outre le fait que chaque catégorie se trouve dans une colonne distincte, chaque sous-catégorie se trouve dans une colonne distincte. `<ul>`chaque sous-catégorie dans une colonne distincte `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/fr/cookbook/iteratewhile.texy b/latte/fr/cookbook/iteratewhile.texy
deleted file mode 100644
index a06819739a..0000000000
--- a/latte/fr/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Tout ce que vous avez toujours voulu savoir sur {iterateWhile}
-**************************************************************
-
-.[perex]
-La balise `{iterateWhile}` convient pour diverses astuces dans les cycles foreach.
-
-Supposons que nous ayons la table de base de données suivante, où les articles sont divisés en catégories :
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Bien sûr, dessiner les éléments d'une boucle foreach sous forme de liste est facile :
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Mais que faire si vous voulez rendre chaque catégorie dans une liste séparée ? En d'autres termes, comment résoudre la tâche consistant à regrouper les éléments d'une liste linéaire dans un cycle foreach. Le résultat devrait ressembler à ceci :
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Nous allons vous montrer comment cette tâche peut être résolue facilement et élégamment avec iterateWhile :
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Alors que `{foreach}` marque la partie extérieure du cycle, c'est-à-dire le dessin des listes pour chaque catégorie, les balises `{iterateWhile}` indiquent la partie intérieure, c'est-à-dire les éléments individuels.
-La condition dans la balise end indique que la répétition se poursuivra tant que l'élément actuel et le suivant appartiennent à la même catégorie (`$iterator->nextValue` est l'[élément suivant |/tags#$iterator]).
-
-Si la condition est toujours remplie, alors tous les éléments sont dessinés dans le cycle intérieur :
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Le résultat ressemblera à ceci :
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-A quoi sert une telle utilisation de iterateWhile ? En quoi diffère-t-elle de la solution que nous avons montrée au tout début de ce tutoriel ? La différence est que si la table est vide et ne contient pas d'éléments, elle ne rendra pas vide `<ul></ul>`.
-
-
-Solution sans `{iterateWhile}` .[#toc-solution-without-iteratewhile]
---------------------------------------------------------------------
-
-Si nous résolvions la même tâche avec des constructions complètement basiques de systèmes de templates, par exemple en Twig, Blade ou en PHP pur, la solution ressemblerait à ceci :
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* la catégorie a changé *}
-
-		{* nous fermons le précédent <ul>, si ce n'est pas le premier élément *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* nous allons ouvrir une nouvelle liste *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* on ferme la dernière liste *}
-	</ul>
-{/if}
-```
-
-Cependant, ce code est incompréhensible et peu intuitif. Le lien entre les balises HTML d'ouverture et de fermeture n'est pas du tout clair. Il n'est pas clair au premier coup d'œil s'il y a une erreur. Et il nécessite des variables auxiliaires comme `$prevCatId`.
-
-En revanche, la solution avec `{iterateWhile}` est propre, claire, ne nécessite pas de variables auxiliaires et est infaillible.
-
-
-Condition dans la balise de fermeture .[#toc-condition-in-the-closing-tag]
---------------------------------------------------------------------------
-
-Si nous spécifions une condition dans la balise d'ouverture `{iterateWhile}`, le comportement change : la condition (et le passage à l'élément suivant) est exécutée au début du cycle interne, et non à la fin.
-Ainsi, alors que `{iterateWhile}` sans condition est toujours entré, `{iterateWhile $cond}` n'est entré que lorsque la condition `$cond` est remplie. En même temps, l'élément suivant est écrit sur `$item`.
-
-Ceci est utile, par exemple, dans une situation où vous souhaitez rendre le premier élément de chaque catégorie d'une manière différente, comme par exemple :
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Modifions le code original, nous dessinons le premier élément et ensuite les éléments supplémentaires de la même catégorie dans la boucle interne `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Boucles imbriquées .[#toc-nested-loops]
----------------------------------------
-
-Nous pouvons créer plusieurs boucles internes dans un cycle et même les imbriquer. De cette façon, on peut par exemple regrouper des sous-catégories.
-
-Supposons qu'il y ait une autre colonne dans le tableau `subCatId` et qu'en plus de chaque catégorie se trouvant dans une colonne séparée, chaque sous-catégorie se trouve dans une colonne séparée. `<ul>`chaque sous-catégorie se trouvera dans une colonne distincte. `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filter |batch .[#toc-filter-batch]
-----------------------------------
-
-Le regroupement d'éléments linéaires est également assuré par un filtre `batch`, en lots d'un nombre fixe d'éléments :
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Il peut être remplacé par iterateWhile comme suit :
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/fr/cookbook/passing-variables.texy b/latte/fr/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..e4e2f20d27
--- /dev/null
+++ b/latte/fr/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Passage de variables d'un modèle à l'autre
+******************************************
+
+Ce guide explique comment les variables sont transmises entre les modèles dans Latte en utilisant diverses balises telles que `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}`, et d'autres. Vous apprendrez également à travailler avec des variables dans les balises `{block}` et `{define}`, ainsi que l'utilité de la balise `{parameters}`.
+
+
+Types de variables .[#toc-types-of-variables]
+---------------------------------------------
+Les variables dans Latte peuvent être divisées en trois catégories en fonction de la manière dont elles sont définies et de l'endroit où elles le sont :
+
+Les **variables d'entrée** sont celles qui sont transmises au modèle depuis l'extérieur, par exemple, depuis un script PHP ou à l'aide d'une balise comme `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+Les **variables environnantes** sont des variables existant à l'emplacement d'une balise spécifique. Elles comprennent toutes les variables d'entrée et les autres variables créées à l'aide de balises telles que `{var}`, `{default}`, ou à l'intérieur d'une boucle `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Les variables explicites** sont celles qui sont directement spécifiées dans une balise et envoyées au modèle cible.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+La balise `{block}` est utilisée pour définir des blocs de code réutilisables qui peuvent être personnalisés ou étendus dans des modèles hérités. Les variables environnantes définies avant le bloc sont disponibles à l'intérieur du bloc, mais toute modification des variables n'est répercutée qu'à l'intérieur de ce bloc.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+La balise `{define}` est utilisée pour créer des blocs qui ne sont rendus que lorsqu'ils sont appelés à l'aide de `{include}`. Les variables disponibles à l'intérieur de ces blocs dépendent de la présence ou non de paramètres dans la définition. Si des paramètres sont spécifiés, seuls ces paramètres sont accessibles. Dans le cas contraire, toutes les variables d'entrée du modèle dans lequel les blocs sont définis sont accessibles.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+La balise `{parameters}` est utilisée pour déclarer explicitement les variables d'entrée attendues au début du modèle. De cette manière, vous pouvez facilement documenter les variables attendues et leurs types de données. Il est également possible de définir des valeurs par défaut.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+La balise `{include file}` est utilisée pour insérer un modèle entier. Ce modèle est transmis à la fois aux variables d'entrée du modèle dans lequel la balise est utilisée et aux variables explicitement définies. Cependant, le modèle cible peut en limiter la portée en utilisant `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Lors de l'insertion d'un bloc défini dans le même modèle, toutes les variables environnantes et explicitement définies lui sont transmises :
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+Dans cet exemple, les variables `$name` et `$age` sont transmises au bloc `blockName`. Le même comportement s'applique à `{include parent}`.
+
+Lors de l'insertion d'un bloc à partir d'un autre modèle, seules les variables d'entrée et les variables explicitement définies sont transmises. Les variables environnantes ne sont pas automatiquement disponibles.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` ou `{extends}`
+-------------------------
+Ces balises définissent un modèle auquel sont transmises les variables d'entrée du modèle enfant et les variables créées dans le code avant les blocs :
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Modèle `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+La balise `{embed}` est similaire à la balise `{include}` mais permet d'intégrer des blocs dans le modèle. Contrairement à `{include}`, seules les variables explicitement déclarées sont transmises :
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+Dans cet exemple, le modèle `menu.latte` n'a accès qu'à la variable `$items`.
+
+Inversement, les blocs à l'intérieur de `{embed}` ont accès à toutes les variables environnantes :
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+La balise `{import}` est utilisée pour charger des blocs provenant d'autres modèles. Les variables d'entrée et les variables explicitement déclarées sont transmises aux blocs importés.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+La balise `{sandbox}` isole le modèle pour un traitement sûr. Les variables sont transmises exclusivement de manière explicite.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/fr/creating-extension.texy b/latte/fr/creating-extension.texy
index f5ff5552e8..a700a21cbd 100644
--- a/latte/fr/creating-extension.texy
+++ b/latte/fr/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// une fonction d'analyse syntaxique qui crée simplement un nœud pour l'instant
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode (nœud auxiliaire) .[#toc-auxiliarynode]
+-----------------------------------------------------
+
+Si vous créez une nouvelle balise pour Latte, il est conseillé de créer une classe de nœuds dédiée, qui la représentera dans l'arbre AST (voir la classe `ForeachNode` dans l'exemple ci-dessus). Dans certains cas, la classe de nœuds auxiliaire triviale [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] peut s'avérer utile, car elle permet de passer le corps de la méthode `print()` et la liste des nœuds rendus accessibles par la méthode `getIterator()` en tant que paramètres du constructeur :
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Le compilateur passe .[#toc-compiler-passes]
 ============================================
 
diff --git a/latte/fr/develop.texy b/latte/fr/develop.texy
index 4ba666fd93..7e13825f75 100644
--- a/latte/fr/develop.texy
+++ b/latte/fr/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Locale .[#toc-locale]{data-version:3.0.18}
+==========================================
+
+Latte vous permet de définir la locale, qui affecte le formatage des nombres, des dates et des tris. Elle est définie à l'aide de la méthode `setLocale()`. L'identifiant de la locale suit la norme de balise de langue de l'IETF, qui utilise l'extension PHP `intl`. Il se compose d'un code de langue et éventuellement d'un code de pays, par exemple, `en_US` pour l'anglais aux États-Unis, `de_DE` pour l'allemand en Allemagne, etc.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Les paramètres linguistiques affectent les filtres [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] et [bytes |filters#bytes].
+
+.[note]
+Nécessite l'extension PHP `intl`. Les paramètres de Latte n'affectent pas les paramètres linguistiques globaux de PHP.
+
+
 Mode strict .[#toc-strict-mode]{data-version:3.0.8}
 ===================================================
 
@@ -271,19 +287,28 @@ Si vous utilisez des balises personnalisées, créez également votre Linter per
 #!/usr/bin/env php
 <?php
 
-// saisissez le chemin d'accès réel au fichier autoload.php
+// entrez le chemin d'accès au fichier autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// ajouter des extensions individuelles ici
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// ajoutez vos extensions individuelles ici
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Vous pouvez également transmettre votre propre objet `Latte\Engine` au Linter :
+
+```php
+$latte = new Latte\Engine;
+// nous configurons ici l'objet $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Chargement de modèles à partir d'une chaîne .[#toc-loading-templates-from-a-string]
 ===================================================================================
diff --git a/latte/fr/extending-latte.texy b/latte/fr/extending-latte.texy
index 598eb8c810..f56410c7cb 100644
--- a/latte/fr/extending-latte.texy
+++ b/latte/fr/extending-latte.texy
@@ -68,6 +68,16 @@ Comme vous pouvez le voir, la fonction reçoit le côté gauche du filtre avant
 
 Bien sûr, la fonction représentant le filtre peut accepter n'importe quel nombre de paramètres, et les paramètres variadiques sont également supportés.
 
+Si le filtre renvoie une chaîne en HTML, vous pouvez la marquer pour que Latte ne l'échappe pas automatiquement (et donc doublement). Cela évite d'avoir à spécifier `|noescape` dans le modèle.
+La méthode la plus simple consiste à envelopper la chaîne dans un objet `Latte\Runtime\Html`, l'autre méthode étant celle des [filtres contextuels |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+Dans ce cas, le filtre doit assurer l'échappement correct des données.
+
 
 Filtres utilisant la classe .[#toc-filters-using-the-class]
 -----------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// changez le type de contenu en HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/fr/filters.texy b/latte/fr/filters.texy
index 01cd3a3475..1ead7b4dc8 100644
--- a/latte/fr/filters.texy
+++ b/latte/fr/filters.texy
@@ -11,14 +11,16 @@ Les filtres sont des fonctions qui modifient ou formatent les données selon nos
 | `bytes` | [Formate la taille en octets |#bytes]
 | `clamp` | [Fixe la valeur à l'intervalle |#clamp]
 | `dataStream` | [Conversion du protocole URI des données |#datastream]
-| `date` | [Formate la date |#date]
+| `date` | [Formatage de la date et de l'heure |#date]
 | `explode` | [divise une chaîne de caractères par le délimiteur donné |#explode]
 | `first` | [renvoie le premier élément d'un tableau ou le premier caractère d'une chaîne de caractères |#first]
+| `group` | [regroupe les données en fonction de différents critères |#group]
 | `implode` | [joint un tableau à une chaîne de caractères |#implode]
 | `indent` | [indente le texte à partir de la gauche avec un nombre de tabulations |#indent]
 | `join` | [joint un tableau à une chaîne de caractères |#implode]
 | `last` | [renvoie le dernier élément d'un tableau ou le dernier caractère d'une chaîne de caractères |#last]
 | `length` | [retourne la longueur d'une chaîne ou d'un tableau |#length]
+| `localDate` | [Formate la date et l'heure en fonction des paramètres locaux |#localDate]
 | `number` | [Formate un nombre |#number]
 | `padLeft` | [Complète une chaîne de caractères à une longueur donnée en partant de la gauche |#padLeft]
 | `padRight` | [Complète la chaîne à la longueur donnée à partir de la droite |#padRight]
@@ -118,8 +120,8 @@ Filtres .[#toc-filters]
 =======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filtre qui simplifie l'énumération de données linéaires sous la forme d'un tableau. Il retourne un tableau de tableaux avec le nombre d'éléments donné. Si vous fournissez un second paramètre, celui-ci est utilisé pour remplir les éléments manquants sur la dernière ligne.
 
 ```latte
@@ -152,6 +154,8 @@ Imprime :
 </table>
 ```
 
+Voir aussi [groupe |#group] et balise [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Insère des sauts de ligne HTML avant tous les retours à la ligne.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formate une taille en octets sous une forme lisible par l'homme.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formate la taille en octets sous une forme lisible par l'homme. Si la [langue locale |develop#locale] est définie, les séparateurs décimaux et de milliers correspondants sont utilisés.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formate une taille en octets sous une forme lisible par l'homme.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Arrondit un nombre à une précision donnée.
 
 ```latte
@@ -203,8 +207,8 @@ Assure la désinfection des URL. Il vérifie si la variable contient une URL web
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Imprime :
@@ -217,8 +221,8 @@ Imprime :
 Voir aussi [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Renvoie une valeur limitée à l'intervalle inclusif de min et max.
 
 ```latte
@@ -228,14 +232,14 @@ Renvoie une valeur limitée à l'intervalle inclusif de min et max.
 Existe aussi en tant que [fonction |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Convertit le contenu en schéma URI de données. Il peut être utilisé pour insérer des images dans le HTML ou le CSS sans avoir besoin de lier des fichiers externes.
 
 Si nous avons une image dans une variable `$img = Image::fromFile('obrazek.gif')`, alors
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Imprime par exemple :
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Nécessite l'extension PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Renvoie une date au format donné en utilisant les options des fonctions PHP [php:strftime] ou [php:date]. Le filtre permet d'obtenir une date sous la forme d'un timestamp UNIX, d'une chaîne de caractères ou d'un objet de type `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formate la date et l'heure selon le masque utilisé par la fonction PHP [php:date]. Le filtre accepte la date au format timestamp UNIX, sous forme de chaîne de caractères ou d'objet `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Voir aussi [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ escapeUrl .[filter]
 Voir aussi [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Divise une chaîne de caractères par le délimiteur donné et renvoie un tableau de chaînes de caractères. Alias pour `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Renvoie le premier élément d'un tableau ou le premier caractère d'une chaîne
 Voir aussi [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Arrondit un nombre à une précision donnée.
 
 ```latte
@@ -330,8 +335,27 @@ Convertit la première lettre d'une valeur en majuscule. Nécessite l'extension
 Voir aussi [majuscule |#capitalize], [inférieur |#lower], [supérieur |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Le filtre regroupe les données selon différents critères.
+
+Dans cet exemple, les lignes du tableau sont regroupées par la colonne `categoryId`. Le résultat est un tableau de tableaux dont la clé est la valeur de la colonne `categoryId`. Lisez les [instructions détaillées |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Voir aussi [batch |#batch], la fonction [group |functions#group] et la balise [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Retourne une chaîne de caractères qui est la concaténation des chaînes de caractères du tableau. Alias pour `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Vous pouvez également utiliser un alias `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Indente un texte à partir de la gauche d'un nombre donné de tabulations ou d'autres caractères que nous spécifions dans le deuxième argument facultatif. Les lignes vides ne sont pas indentées.
 
 ```latte
@@ -396,6 +420,68 @@ Renvoie la longueur d'une chaîne ou d'un tableau.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formate la date et l'heure en fonction de la [locale |develop#locale], ce qui garantit un affichage cohérent et localisé des données temporelles dans différentes langues et régions. Le filtre accepte la date sous forme d'horodatage UNIX, de chaîne de caractères ou d'objet `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Si vous utilisez le filtre sans aucun paramètre, il affichera la date au niveau du format long, comme expliqué plus loin.
+
+**a) Utilisation du format**
+
+Le paramètre `format` décrit les composantes de l'heure qui doivent être affichées. Il utilise des codes de lettres, dont le nombre de répétitions affecte la largeur de la sortie :
+
+| Année | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Mois | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `août` / `août`
+| Jour : `d` / `dd` / `E` / `EEEE` | `1` / `01` / `dim.` / `dimanche`
+| Heure | `j` / `H` / `h` | préférée / 24 heures / 12 heures
+| Minute | `m` / `mm` | `5` / `05` <small>(2 chiffres lorsqu'ils sont combinés avec les secondes)</small>
+| Heure | `s` / `ss` | `8` / `08` <small>(2 chiffres lorsqu'ils sont combinés avec les secondes)</small>
+
+L'ordre des codes dans le format n'a pas d'importance, car l'ordre des composants sera affiché selon les conventions locales. Le format est donc indépendant de la locale. Par exemple, le format `yyyyMMMMd` dans la locale `en_US` produit `April 15, 2024`, alors que dans la locale `cs_CZ` il produit `15. dubna 2024`:
+
+| locale:  | fr-FR | en_US
+|---
+| `format: 'dMy'` | 10/08/2024 | 8/10/2024
+| `format: 'yM'` | 08/2024 | 8/2024
+| `format: 'yyyyMMMM'` | août 2024 | August 2024
+| `format: 'MMMM'` | août | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 PM | 5:54 PM
+
+
+**b) Utilisation de styles prédéfinis**
+
+Les paramètres `date` et `time` déterminent le niveau de détail de l'affichage de la date et de l'heure. Vous avez le choix entre plusieurs niveaux : `full`, `long`, `medium`, `short`. Vous pouvez afficher uniquement la date, uniquement l'heure ou les deux :
+
+| locale:  | fr-FR | en_US
+|---
+| `date: short` | 23/01/1978 | 1/23/78
+| `date: medium` | 23 janv. 1978 | Jan 23, 1978
+| `date: long` | 23 janvier 1978 | January 23, 1978
+| `date: full` | lundi 23 janvier 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 UTC+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23/01/1978 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 janv. 1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 janvier 1978 à 08:30 | January 23, 1978 at 8:30 AM
+
+Pour la date, vous pouvez également utiliser le préfixe `relative-` (par exemple, `relative-short`), qui affichera `yesterday`, `today` ou `tomorrow` pour les dates proches de la date actuelle ; sinon, l'affichage se fera de manière standard.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Voir aussi [date |#date].
+
+
 lower .[filter]
 ---------------
 Convertit une valeur en minuscule. Nécessite l'extension PHP `mbstring`.
@@ -416,8 +502,8 @@ Si le lien utilise un schéma différent, tel que `javascript:` ou `data:`, et q
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Imprimés :
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 Une mauvaise utilisation du filtre `noescape` peut conduire à une vulnérabilité XSS ! Ne l'utilisez jamais sans être **absolument sûr** de ce que vous faites et que la chaîne que vous imprimez provient d'une source fiable.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formate un nombre avec un nombre donné de décimales. Vous pouvez également spécifier un caractère du point décimal et du séparateur de milliers.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formate un nombre avec le nombre de décimales spécifié. Si la [locale |develop#locale] est définie, les séparateurs de décimales et de milliers correspondants sont utilisés.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Formate un nombre avec un nombre donné de décimales. Vous pouvez également sp
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Le paramètre `format` vous permet de définir l'apparence des chiffres exactement selon vos besoins. Il nécessite une [locale |develop#locale] définie. Le format se compose de plusieurs caractères spéciaux, dont la description complète se trouve dans la documentation "DecimalFormat" ::https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns
+
+- <c id=6/> chiffre obligatoire, toujours affiché même s'il est nul
+- `#` chiffre optionnel, affiché seulement si le nombre a un chiffre à cette place
+- `@` chiffre significatif, permet d'afficher le nombre avec un certain nombre de chiffres significatifs
+- `.` marque l'emplacement du séparateur décimal (virgule ou point, selon la langue)
+- `,` utilisé pour séparer des groupes de chiffres, généralement des milliers
+- `%` multiplie le nombre par 100 et ajoute le signe de pourcentage
+
+Voyons quelques exemples. Dans le premier exemple, deux décimales sont obligatoires ; dans le deuxième, elles sont facultatives. Le troisième exemple montre un remplissage avec des zéros des deux côtés, et le quatrième n'affiche que les chiffres existants :
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Les chiffres significatifs déterminent le nombre de chiffres à afficher, indépendamment de la virgule, en arrondissant le nombre si nécessaire :
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Une façon simple d'afficher un nombre en pourcentage. Le nombre est multiplié par 100 et le signe `%` est ajouté :
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Nous pouvons définir un format différent pour les nombres positifs et négatifs, séparés par le caractère `;`. Ainsi, par exemple, les nombres positifs peuvent être affichés avec le signe `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+N'oubliez pas que l'apparence réelle des nombres peut varier en fonction des paramètres locaux. Par exemple, dans certains pays, une virgule est utilisée à la place d'un point comme séparateur décimal. Ce filtre en tient compte automatiquement, vous n'avez donc pas à vous en préoccuper.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Remplit une chaîne de caractères d'une certaine longueur avec une autre chaîne de caractères à partir de la gauche.
 
@@ -472,7 +606,7 @@ Remplit une chaîne de caractères d'une certaine longueur avec une autre chaîn
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Remplir une chaîne de caractères d'une certaine longueur avec une autre chaîne de caractères de droite.
 
@@ -514,8 +648,8 @@ Renvoie un élément aléatoire du tableau ou un caractère de la chaîne :
 Voir aussi [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Répète la chaîne x fois.
 
 ```latte
@@ -523,7 +657,7 @@ Répète la chaîne x fois.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Remplace toutes les occurrences de la chaîne de recherche par la chaîne de remplacement.
 
@@ -538,7 +672,7 @@ Plusieurs remplacements peuvent être effectués en même temps :
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Remplace toutes les occurrences selon l'expression régulière.
 
@@ -559,8 +693,8 @@ Inverse une chaîne ou un tableau donné.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Arrondit un nombre à une précision donnée.
 
 ```latte
@@ -573,7 +707,7 @@ Arrondit un nombre à une précision donnée.
 Voir aussi [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Extrait une tranche d'un tableau ou d'une chaîne de caractères.
 
@@ -591,9 +725,9 @@ Si length est donné et est positif, alors la séquence aura jusqu'à ce nombre
 Filter réordonnera et réinitialisera les clés du tableau d'entiers par défaut. Ce comportement peut être modifié en définissant preserveKeys à true. Les clés des chaînes de caractères sont toujours préservées, quel que soit ce paramètre.
 
 
-sort  .[filter]
----------------
-Filtre qui trie un tableau et maintient l'association des index.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Le filtre trie les éléments d'un tableau ou d'un itérateur tout en préservant leurs clés associatives. Lorsqu'une [locale |develop#locale] est définie, le tri suit ses règles à moins qu'une fonction de comparaison personnalisée ne soit spécifiée.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Tableau trié dans l'ordre inverse.
 {/foreach}
 ```
 
-Vous pouvez passer votre propre fonction de comparaison en paramètre :
+Vous pouvez spécifier une fonction de comparaison personnalisée pour le tri (l'exemple montre comment inverser le tri du plus grand au plus petit) :
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Le filtre `|sort` vous permet également de trier les éléments par clé :
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Si vous devez trier un tableau en fonction d'une colonne spécifique, vous pouvez utiliser le paramètre `by`. La valeur `'name'` dans l'exemple spécifie que le tri sera effectué par `$row->name` ou `$row['name']`selon que `$row` est un tableau ou un objet :
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Vous pouvez également définir une fonction de rappel qui détermine la valeur à trier :
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Le paramètre `byKey` peut être utilisé de la même manière.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Convertit le HTML en texte brut. C'est-à-dire qu'il supprime les balises HTML e
 Le texte brut résultant peut naturellement contenir des caractères qui représentent des balises HTML, par exemple `'&lt;p&gt;'|stripHtml` est converti en `<p>`. N'éditez jamais le texte résultant avec `|noescape`, car cela pourrait entraîner une faille de sécurité.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Extrait une tranche d'une chaîne de caractères. Ce filtre a été remplacé par un filtre de [tranche |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ Extrait une tranche d'une chaîne de caractères. Ce filtre a été remplacé pa
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Il traduit les expressions dans d'autres langues. Pour rendre ce filtre disponible, vous devez [configurer le traducteur |develop#TranslatorExtension]. Vous pouvez également utiliser les [balises pour la traduction |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Il traduit les expressions dans d'autres langues. Pour rendre ce filtre disponib
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Supprime les caractères de tête et de queue, par défaut les espaces blancs.
 
 ```latte
@@ -675,7 +835,7 @@ Supprime les caractères de tête et de queue, par défaut les espaces blancs.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Raccourcit une chaîne de caractères à la longueur maximale donnée mais essaie de préserver les mots entiers. Si la chaîne est tronquée, elle ajoute des points de suspension à la fin (ceci peut être modifié par le second paramètre).
 
diff --git a/latte/fr/functions.texy b/latte/fr/functions.texy
index 9d2d9e0ba8..fd412da021 100644
--- a/latte/fr/functions.texy
+++ b/latte/fr/functions.texy
@@ -9,6 +9,8 @@ Outre les fonctions PHP courantes, vous pouvez également les utiliser dans les
 | `divisibleBy`| [vérifie si une variable est divisible par un nombre |#divisibleBy]
 | `even` | [vérifie si le nombre donné est pair |#even]
 | `first` | [renvoie le premier élément d'un tableau ou un caractère d'une chaîne de caractères |#first]
+| `group` | [regroupe les données en fonction de différents critères |#group]
+| `hasBlock` | [détecte l'existence d'un bloc |#hasBlock]
 | `last` | [renvoie le dernier élément d'un tableau ou un caractère d'une chaîne de caractères |#last]
 | `odd` | [vérifie si le nombre donné est impair |#odd]
 | `slice` | [extrait une tranche d'un tableau ou d'une chaîne de caractères |#slice]
@@ -73,8 +75,8 @@ Vérifie si le nombre donné est pair.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Retourne le premier élément d'un tableau ou le premier caractère d'une chaîne de caractères :
 
 ```latte
@@ -85,6 +87,36 @@ Retourne le premier élément d'un tableau ou le premier caractère d'une chaîn
 Voir aussi [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Cette fonction permet de regrouper les données selon différents critères.
+
+Dans cet exemple, les lignes du tableau sont regroupées par la colonne `categoryId`. La sortie est un tableau de champs dont la clé est la valeur de la colonne `categoryId`. Lisez les [instructions détaillées |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Voir aussi [groupe de |filters#group] filtres.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Vérifie si le bloc du nom spécifié existe :
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Voir aussi [vérification de l'existence du bloc |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Renvoie le dernier élément du tableau ou le dernier caractère de la chaîne :
@@ -106,8 +138,8 @@ Vérifie si le nombre donné est impair.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Extrait une tranche d'un tableau ou d'une chaîne de caractères.
 
 ```latte
diff --git a/latte/fr/recipes.texy b/latte/fr/recipes.texy
index 0fafcd16d6..4f2be42390 100644
--- a/latte/fr/recipes.texy
+++ b/latte/fr/recipes.texy
@@ -9,7 +9,7 @@ Conseils et astuces
 
 - L'EDI NetBeans a un support intégré
 - PhpStorm : installez le [plugin Latte |https://plugins.jetbrains.com/plugin/7457-latte] en `Settings > Plugins > Marketplace`
-- VS Code : cherchez dans markerplace le plugin "Nette Latte + Neon".
+- VS Code : rechercher sur markerplace le plugin [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ou [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Sublime Text 3 : dans Package Control, trouvez et installez le paquet `Nette` et sélectionnez Latte dans le menu déroulant. `View > Syntax`
 - Dans les anciens éditeurs, utilisez la mise en évidence Smarty pour les fichiers .latte.
 
diff --git a/latte/fr/safety-first.texy b/latte/fr/safety-first.texy
index b8fdd5708b..92e1a40c74 100644
--- a/latte/fr/safety-first.texy
+++ b/latte/fr/safety-first.texy
@@ -351,7 +351,7 @@ Latte vérifie automatiquement si la variable utilisée dans les attributs `src`
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Écrit :
diff --git a/latte/fr/syntax.texy b/latte/fr/syntax.texy
index 7c7d182727..221453d873 100644
--- a/latte/fr/syntax.texy
+++ b/latte/fr/syntax.texy
@@ -98,7 +98,7 @@ Imprimés :
 Ou en utilisant le préfixe `tag-` la fonctionnalité est appliquée sur les balises HTML uniquement :
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Selon la valeur de la variable `$url`, ceci s'imprimera :
@@ -155,6 +155,20 @@ Ou directement sur la valeur (en combinaison avec [`{=expr}` | https://latte.net
 ```
 
 
+Balises HTML dynamiques .[#toc-dynamic-html-tags]
+=================================================
+
+Latte supporte les balises HTML dynamiques, qui sont utiles lorsque vous avez besoin de flexibilité dans les noms de balises :
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Par exemple, le code ci-dessus peut générer `<h1>Heading</h1>` ou `<h2>Heading</h2>` en fonction de la valeur de la variable `$level`. Les balises HTML dynamiques dans Latte doivent toujours être appariées. Leur alternative est la [balise n:tag |tags#n:tag].
+
+Latte étant un système de création de modèles sécurisé, il vérifie que le nom de balise résultant est valide et ne contient pas de valeurs indésirables ou malveillantes. Il s'assure également que le nom de la balise de fin est toujours le même que le nom de la balise d'ouverture.
+
+
 Commentaires .[#toc-comments]
 =============================
 
diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy
index b4f22df9c9..65a994d18c 100644
--- a/latte/fr/tags.texy
+++ b/latte/fr/tags.texy
@@ -16,6 +16,7 @@ Résumé et description de toutes les balises intégrées de Latte.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [condition ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [test si un changement est intervenu|#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default]
+| `n:else` | [contenu alternatif pour les conditions |#n:else]
 
 .[table-latte-tags language-latte]
 |## Boucles
@@ -97,8 +98,8 @@ Résumé et description de toutes les balises intégrées de Latte.
 | `{link}` | [imprime un lien |application:creating-links#In the Presenter Template]
 | `{plink}` | [imprime un lien vers un présentateur |application:creating-links#In the Presenter Template]
 | `{control}` | [imprime un composant |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [un snippet de modèle qui peut être envoyé par AJAX |application:ajax#tag-snippet]
-| `{snippetArea}` | enveloppe des snippets
+| `{snippet}`... `{/snippet}` | [un snippet de modèle qui peut être envoyé par AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [enveloppe des snippets |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [met en cache une section de modèle |caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Résumé et description de toutes les balises intégrées de Latte.
 | `{input}` | [imprime un élément de saisie de formulaire |forms:rendering#label-input]
 | `{inputError}` | [imprime un message d'erreur pour l'élément de saisie du formulaire |forms:rendering#inputError]
 | `n:name` | [active un élément de saisie HTML |forms:rendering#n:name]
-| `{formPrint}` | [génère le plan du formulaire Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [imprime la classe PHP pour les données du formulaire |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [rendu partiel du formulaire |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [rendre le conteneur de formulaire |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Savez-vous que vous pouvez ajouter le préfixe `tag-` aux n:attributs ? La condi
 Bien.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Si vous écrivez la condition `{if} ... {/if}` sous la forme d'un [n:attribut |syntax#n:attributes], vous avez la possibilité de spécifier une branche alternative en utilisant `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+L'attribut `n:else` peut également être utilisé en conjonction avec [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], et [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Voir aussi [`{ifset block}` |template-inheritance#checking-block-existence]
 Utilisez la condition `{ifset $var}` pour déterminer si une variable (ou plusieurs variables) existe et a une valeur non nulle. C'est en fait la même chose que `if (isset($var))` en PHP. Comme toute balise de paire, elle peut être écrite sous la forme [n:attribut |syntax#n:attributes], alors montrons-la en exemple :
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ C'est plutôt pratique, non ?
 `{iterateWhile}`
 ----------------
 
-Il simplifie le regroupement des données linéaires pendant l'itération dans une boucle foreach en effectuant l'itération dans une boucle imbriquée tant que la condition est remplie. [Lire les instructions dans le livre de cuisine |cookbook/iteratewhile].
+Simplifie le regroupement des données linéaires pendant l'itération dans une boucle foreach en itérant dans une boucle imbriquée jusqu'à ce qu'une condition soit remplie. [Lire les instructions détaillées |cookbook/grouping].
 
 Elle peut aussi remplacer élégamment `{first}` et `{last}` dans l'exemple ci-dessus :
 
@@ -489,6 +501,8 @@ Elle peut aussi remplacer élégamment `{first}` et `{last}` dans l'exemple ci-d
 {/foreach}
 ```
 
+Voir également les filtres de [lot |filters#batch] et de [groupe |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Si `$heading === null`, la balise `<h1>` est imprimé sans changement. Sinon, le
 <h3 class="main">...</h3>
 ```
 
+Latte étant un système de templates sécurisé, il vérifie que le nouveau nom de balise est valide et ne contient pas de valeurs indésirables ou malveillantes.
+
 
 n:ifcontent
 -----------
diff --git a/latte/fr/template-inheritance.texy b/latte/fr/template-inheritance.texy
index 3c14000ecc..b0a6fdeab9 100644
--- a/latte/fr/template-inheritance.texy
+++ b/latte/fr/template-inheritance.texy
@@ -132,7 +132,7 @@ Voici quelques conseils pour travailler avec l'héritage de mise en page :
 
 - Si vous utilisez `{layout}` dans un modèle, il doit s'agir de la première balise de modèle de ce modèle.
 
-- La mise en page peut être [recherchée automatiquement |develop#automatic-layout-lookup] (comme dans les [présentateurs |application:templates#search-for-templates]). Dans ce cas, si le modèle ne doit pas avoir de mise en page, il l'indiquera avec la balise `{layout none}`.
+- La mise en page peut être [recherchée automatiquement |develop#automatic-layout-lookup] (comme dans les [présentateurs |application:templates#Template Lookup]). Dans ce cas, si le modèle ne doit pas avoir de mise en page, il l'indiquera avec la balise `{layout none}`.
 
 - La balise `{layout}` a un alias `{extends}`.
 
@@ -396,6 +396,14 @@ Vous pouvez utiliser une variable ou toute expression en PHP comme nom de bloc.
 {/ifset}
 ```
 
+L'existence de blocs est également renvoyée par la fonction [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Conseils .[#toc-tips]
 ---------------------
@@ -415,7 +423,7 @@ Voici quelques conseils pour travailler avec des blocs :
 Réutilisation horizontale `{import}` .{toc: Horizontal Reuse}
 =============================================================
 
-La réutilisation horizontale est un troisième mécanisme de réutilisation et d'héritage dans Latte. Elle vous permet de charger des blocs à partir d'autres modèles. C'est similaire à la création d'un fichier PHP avec des fonctions d'aide ou un trait.
+La réutilisation horizontale est le troisième mécanisme de réutilisation et d'héritage dans Latte. Il permet de charger des blocs à partir d'autres modèles. Il est similaire à la création d'un fichier avec des fonctions d'aide en PHP, puis à son chargement à l'aide de `require`.
 
 Bien que l'héritage de modèles soit l'une des fonctionnalités les plus puissantes de Latte, il est limité à l'héritage simple - un modèle ne peut étendre qu'un seul autre modèle. La réutilisation horizontale est un moyen d'obtenir un héritage multiple.
 
@@ -447,7 +455,7 @@ La balise `{import}` doit être la première balise de modèle après `{layout}`
 
 Vous pouvez utiliser autant d'instructions `{import}` que vous le souhaitez dans un modèle donné. Si deux modèles importés définissent le même bloc, le premier l'emporte. Toutefois, la plus haute priorité est accordée au modèle principal, qui peut écraser tout bloc importé.
 
-Tous les blocs remplacés peuvent être inclus progressivement en les insérant comme [bloc parent |#parent block]:
+Le contenu des blocs écrasés peut être préservé en insérant le bloc de la même manière qu'un [bloc parent |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/hu/@left-menu.texy b/latte/hu/@left-menu.texy
index 7b45ea1690..9bc17c7cad 100644
--- a/latte/hu/@left-menu.texy
+++ b/latte/hu/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Kezdő lépések |Guide]
 - [Miért használjon sablonokat? |why-use]
-- Fogalmak
+- Fogalmak ⚗️
 	- [Első a biztonság |Safety First]
 	- [Sablon öröklődés |Template Inheritance]
 	- [Típus rendszer |Type System]
 	- [Homokozó |Sandbox]
 
-- Tervezőknek
+- Tervezőknek 🎨
 	- [Szintaxis |Syntax]
 	- [Címkék |Tags]
 	- [Szűrők |Filters]
 	- [Funkciók |Functions]
 	- [Tippek és trükkök |recipes]
 
-- Fejlesztőknek
+- Fejlesztőknek 🧮
 	- [Gyakorlatok fejlesztőknek |develop]
 	- [Latte bővítése |Extending Latte]
 	- [Bővítmény létrehozása |creating-extension]
 
-- [Szakácskönyv |cookbook/@home]
+- [Szakácskönyv 💡|cookbook/@home]
 	- [Migráció a Twig-ről |cookbook/migration-from-twig]
 	- [... tovább |cookbook/@home]
 
diff --git a/latte/hu/cookbook/@home.texy b/latte/hu/cookbook/@home.texy
index 4b9e44b15f..b61d28814c 100644
--- a/latte/hu/cookbook/@home.texy
+++ b/latte/hu/cookbook/@home.texy
@@ -4,7 +4,9 @@ Szakácskönyv
 .[perex]
 Példakódok és receptek a Latte segítségével végzett gyakori feladatok elvégzéséhez.
 
-- [Minden, amit mindig is tudni akartál az {iterateWhile} |iteratewhile]
+- [Fejlesztői iránymutatások |/develop]
+- [Változók átadása sablonokon keresztül |passing-variables]
+- [Minden, amit mindig is tudni akart a csoportosításról |grouping]
 - [Hogyan írjunk SQL-lekérdezéseket Latte-ban? |how-to-write-sql-queries-in-latte]
 - [Átállás PHP-ről |migration-from-php]
 - [Átállás a Twig-ről |migration-from-twig]
diff --git a/latte/hu/cookbook/grouping.texy b/latte/hu/cookbook/grouping.texy
new file mode 100644
index 0000000000..2d8bbe32d9
--- /dev/null
+++ b/latte/hu/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Minden, amit mindig is tudni akartál a csoportosításról
+*******************************************************
+
+.[perex]
+Amikor sablonokban dolgozik az adatokkal, gyakran találkozik azzal az igénnyel, hogy csoportosítani vagy bizonyos kritériumok szerint megjeleníteni kell őket. Erre a célra a Latte számos hatékony eszközt kínál.
+
+A `|group` szűrő és funkció lehetővé teszi az adatok hatékony csoportosítását meghatározott kritériumok alapján, míg a `|batch` szűrő megkönnyíti az adatok rögzített tételekre való felosztását, a `{iterateWhile}` címke pedig lehetőséget biztosít a feltételek segítségével történő összetettebb ciklusszabályozásra.
+E címkék mindegyike speciális lehetőségeket kínál az adatokkal való munkához, így nélkülözhetetlen eszközök az információk dinamikus és strukturált megjelenítéséhez a Latte sablonokban.
+
+
+Szűrő és funkció `group` .[#toc-filter-and-function-group]
+==========================================================
+
+Képzeljünk el egy `items` adatbázis-táblát, amelyben kategóriákba sorolt tételek találhatók:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | 1 | Apple
+| 2 | 1 | Banán
+| 3 | 2 | PHP
+| 4 | 3 | Zöld
+| 5 | 3 | Piros
+| 6 | 3 | Kék
+
+Az összes elem egyszerű listája a Latte sablon használatával így nézne ki:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Ha azonban azt szeretnénk, hogy az elemeket kategóriák szerint csoportosítani tudjuk, akkor úgy kell felosztanunk őket, hogy minden kategóriának saját listája legyen. Az eredmény így nézne ki:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+A feladat könnyen és elegánsan megoldható a `|group` segítségével. Paraméterként megadjuk a `categoryId` címet, ami azt jelenti, hogy az elemeket a `$item->categoryId` érték alapján kisebb tömbökre osztjuk fel (ha a `$item` egy tömb lenne, akkor a következővel dolgoznánk `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+A szűrő a Latte-ban függvényként is használható, így alternatív szintaxist kapunk: `{foreach group($items, categoryId) ...}`.
+
+Ha összetettebb kritériumok szerint szeretnénk csoportosítani az elemeket, akkor a szűrő paraméterében használhatunk függvényt. Például az elemek csoportosítása a nevük hossza alapján így nézne ki:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Fontos megjegyezni, hogy a `$categoryItems` nem egy hagyományos tömb, hanem egy olyan objektum, amely iterátorként viselkedik. A csoport első elemének eléréséhez használhatja a [`first()` |latte:functions#first] függvényt.
+
+Az adatok csoportosításának ez a rugalmassága teszi a `group` -t kivételesen hasznos eszközzé az adatok Latte sablonokban történő bemutatásához.
+
+
+Beágyazott hurkok .[#toc-nested-loops]
+--------------------------------------
+
+Tegyük fel, hogy van egy adatbázis-táblánk egy másik `subcategoryId` oszloppal, amely az egyes tételek alkategóriáit határozza meg. Minden egyes fő kategóriát egy különálló `<ul>` listában, és minden alkategóriát egy külön beágyazott listában. `<ol>` listában:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Kapcsolat a Nette adatbázissal .[#toc-connection-with-nette-database]
+---------------------------------------------------------------------
+
+Megmutatjuk, hogyan lehet hatékonyan használni az adatcsoportosítást a Nette Adatbázissal kombinálva. Tegyük fel, hogy az eredeti példában szereplő `items` táblával dolgozunk, amely a `categoryId` oszlopon keresztül kapcsolódik ehhez a `categories` táblához:
+
+| categoryId | név |
+|------------|------------|
+| 1 | Gyümölcsök |
+| 2 | Nyelvek |
+| 3 | Színek |
+
+Az adatokat a `items` táblából a Nette Database Explorer `$items = $db->table('items')` parancsával töltjük be. Az ezeken az adatokon való iteráció során nemcsak az olyan attribútumokhoz férhetünk hozzá, mint a `$item->name` és a `$item->categoryId`, hanem a `categories` táblával való kapcsolatnak köszönhetően a `$item->category` segítségével a tábla kapcsolódó sorához is. Ez a kapcsolat érdekes felhasználási lehetőségeket mutathat fel:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Ebben az esetben a `|group` szűrővel a `$item->category` kapcsolódó sora szerint csoportosítunk, nem csak a `categoryId` oszlop szerint. Ezáltal a változó kulcsában megkapjuk az adott kategória `ActiveRow` címét, így a `{$category->name}` segítségével közvetlenül megjeleníthetjük a nevét. Ez egy gyakorlati példa arra, hogy a csoportosítás hogyan egyszerűsítheti a sablonokat és könnyítheti meg az adatkezelést.
+
+
+Szűrő `|batch` .[#toc-filter-batch]
+===================================
+
+A szűrő lehetővé teszi, hogy az elemek listáját előre meghatározott számú elemet tartalmazó csoportokra ossza. Ez a szűrő ideális olyan helyzetekben, amikor az adatokat több kisebb csoportban szeretné megjeleníteni, például a jobb áttekinthetőség vagy az oldalon való vizuális rendezés érdekében.
+
+Képzeljük el, hogy van egy elemeket tartalmazó listánk, és azokat listákban szeretnénk megjeleníteni, amelyek mindegyike legfeljebb három elemet tartalmazhat. A `|batch` szűrő használata ilyen esetben nagyon praktikus:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+Ebben a példában a `$items` listát kisebb csoportokra osztjuk, és minden csoport (`$batch`) legfeljebb három elemet tartalmaz. Ezután minden csoport egy különálló `<ul>` listában.
+
+Ha az utolsó csoport nem tartalmaz elegendő elemet a kívánt szám eléréséhez, a szűrő második paramétere lehetővé teszi annak meghatározását, hogy mivel egészüljön ki ez a csoport. Ez ideális az elemek esztétikai összehangolására, ahol egy hiányos sor rendezetlennek tűnhet.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Címke `{iterateWhile}` .[#toc-tag-iteratewhile]
+===============================================
+
+A `{iterateWhile}` címkével ugyanazokat a feladatokat mutatjuk be, mint amiket a `|group` szűrővel kezeltünk. A fő különbség a két megközelítés között az, hogy a `group` először feldolgozza és csoportosítja az összes bemeneti adatot, míg a `{iterateWhile}` a feltételekkel rendelkező ciklusok előrehaladását vezérli, így az iteráció szekvenciálisan történik.
+
+Először egy kategóriákat tartalmazó táblázatot rajzolunk az iterateWhile segítségével:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Míg a `{foreach}` a ciklus külső részét jelöli, azaz az egyes kategóriákhoz tartozó listák rajzolását, addig a `{iterateWhile}` címke a belső részt, azaz az egyes elemeket.
+Az end tagben lévő feltétel azt mondja, hogy az ismétlés addig folytatódik, amíg az aktuális és a következő elem ugyanahhoz a kategóriához tartozik (`$iterator->nextValue` a [következő elem |/tags#$iterator]).
+
+Ha a feltétel mindig teljesülne, akkor a belső ciklusban minden elem kirajzolódna:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Az eredmény így fog kinézni:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Mi a haszna az iterateWhile-nak ebben a formában? Ha a táblázat üres, és nem tartalmaz elemeket, nincs üres `<ul></ul>` kerül kiírásra.
+
+Ha a feltételt a nyitó `{iterateWhile}` címkében adjuk meg, a viselkedés megváltozik: a feltétel (és a következő elemre való átmenet) a belső ciklus elején történik, nem pedig a végén.
+Így míg a `{iterateWhile}` mindig feltétel nélkül lép be, addig a `{iterateWhile $cond}` csak akkor lép be, ha a `$cond` feltétel teljesül. És ezzel egyidejűleg a következő elemet írja be a `$item`.
+
+Ez hasznos például olyan helyzetben, amikor az egyes kategóriák első elemét másképp akarjuk megjeleníteni, például így:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Az eredeti kódot úgy módosítjuk, hogy először az első elemet rendereljük, majd a belső ciklusban `{iterateWhile}` rendereljük a többi elemet ugyanabból a kategóriából:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Egy cikluson belül több belső hurkot is létrehozhatunk, és akár egymásba is ágyazhatjuk őket. Így például az alkategóriákat is csoportosíthatjuk.
+
+Tegyük fel, hogy a táblázatnak van egy másik oszlopa is: `subcategoryId`, és amellett, hogy minden kategória egy különálló `<ul>`, minden alkategória egy külön `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/hu/cookbook/iteratewhile.texy b/latte/hu/cookbook/iteratewhile.texy
deleted file mode 100644
index d4952557bd..0000000000
--- a/latte/hu/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Minden, amit mindig is tudni akartál az {iterateWhile}
-******************************************************
-
-.[perex]
-A `{iterateWhile}` címke a foreach ciklusokban különböző trükkökre alkalmas.
-
-Tegyük fel, hogy a következő adatbázis táblával rendelkezünk, ahol az elemek kategóriákba vannak osztva:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Természetesen a foreach ciklusban az elemek listaként való kirajzolása egyszerű:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-De mit tegyünk, ha minden kategóriát külön listában szeretnénk megjeleníteni? Más szóval, hogyan oldjuk meg egy foreach ciklusban egy lineáris lista elemeinek csoportosítását. A kimenetnek így kellene kinéznie:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Megmutatjuk, milyen egyszerűen és elegánsan megoldható a feladat az iterateWhile segítségével:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Míg a `{foreach}` a ciklus külső részét jelöli, azaz az egyes kategóriákhoz tartozó listák rajzolását, addig a `{iterateWhile}` címkék a belső részt, azaz az egyes elemeket jelölik.
-Az end tagben lévő feltétel azt mondja, hogy az ismétlés addig folytatódik, amíg az aktuális és a következő elem ugyanahhoz a kategóriához tartozik (`$iterator->nextValue` a [következő elem |/tags#$iterator]).
-
-Ha a feltétel mindig teljesül, akkor a belső ciklusban minden elem kirajzolódik:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Az eredmény így fog kinézni:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Mire jó az iterateWhile ilyen használata? Miben különbözik attól a megoldástól, amit a bemutató legelején mutattunk? A különbség az, hogy ha a táblázat üres, és nem tartalmaz semmilyen elemet, akkor nem fog üresen renderelni `<ul></ul>`.
-
-
-Megoldás a `{iterateWhile}` nélkül .[#toc-solution-without-iteratewhile]
-------------------------------------------------------------------------
-
-Ha ugyanazt a feladatot a sablonrendszerek teljesen alapvető konstrukcióival oldanánk meg, például Twigben, Blade-ben vagy tiszta PHP-ben, a megoldás valahogy így nézne ki:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* új listát nyitunk *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* lezárjuk az utolsó listát *}
-	</ul>
-{/if}
-```
-
-Ez a kód azonban érthetetlen és nem intuitív. A nyitó és záró HTML-címkék közötti kapcsolat egyáltalán nem egyértelmű. Első pillantásra nem egyértelmű, hogy hiba van-e benne. És olyan segédváltozókat igényel, mint a `$prevCatId`.
-
-Ezzel szemben a `{iterateWhile}` megoldása tiszta, egyértelmű, nem igényel segédváltozókat, és bolondbiztos.
-
-
-Feltétel a záró tagben .[#toc-condition-in-the-closing-tag]
------------------------------------------------------------
-
-Ha a nyitó tagben adunk meg egy feltételt `{iterateWhile}`, a viselkedés megváltozik: a feltétel (és a következő elemre való továbblépés) a belső ciklus elején hajtódik végre, nem pedig a végén.
-Így míg a `{iterateWhile}` feltétel nélkül mindig belép, a `{iterateWhile $cond}` csak akkor lép be, ha a `$cond` feltétel teljesül. Ezzel egyidejűleg a következő elemet írja a `$item`.
-
-Ez hasznos például olyan helyzetekben, amikor az egyes kategóriák első elemét másképp szeretnénk megjeleníteni, például:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Módosítsuk az eredeti kódot, rajzoljuk az első elemet, majd további elemeket ugyanabból a kategóriából a belső ciklusban `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Beágyazott hurkok .[#toc-nested-loops]
---------------------------------------
-
-Egy ciklusban több belső hurkot is létrehozhatunk, és akár egymásba is ágyazhatjuk őket. Így például alkategóriákat csoportosíthatunk.
-
-Tegyük fel, hogy van egy másik oszlop a `subCatId` táblázatban, és amellett, hogy minden kategória egy különálló `<ul>`, minden alkategória egy külön oszlopban lesz. `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Szűrő |batch .[#toc-filter-batch]
----------------------------------
-
-A lineáris elemek csoportosítását szintén a `batch` szűrő biztosítja, mégpedig fix elemszámú tételekbe:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Ez helyettesíthető iterateWhile-val az alábbiak szerint:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/hu/cookbook/passing-variables.texy b/latte/hu/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..b5cfe343ee
--- /dev/null
+++ b/latte/hu/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Változók átadása sablonokon keresztül
+*************************************
+
+Ez az útmutató elmagyarázza, hogy a változókat hogyan adjuk át a sablonok között a Latte-ban különböző címkék segítségével, mint például `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` és mások. Megtudhatja továbbá, hogyan dolgozzon a `{block}` és a `{define}` címkékben lévő változókkal, valamint a `{parameters}` címke célját.
+
+
+A változók típusai .[#toc-types-of-variables]
+---------------------------------------------
+A változókat a Latte-ban három kategóriába sorolhatjuk aszerint, hogy hogyan és hol vannak definiálva:
+
+**Bemeneti változók** azok, amelyeket kívülről adunk át a sablonhoz, például egy PHP szkriptből vagy egy olyan tag segítségével, mint a `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+A **környező változók** egy adott tag helyén létező változók. Ezek közé tartozik minden bemeneti változó és az olyan címkékkel létrehozott egyéb változók, mint a `{var}`, `{default}`, vagy egy cikluson belül a `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**A **explicit változók** azok a változók, amelyeket közvetlenül egy címkén belül határoznak meg és küldenek el a célsablonnak.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+A `{block}` címke újrafelhasználható kódblokkok definiálására szolgál, amelyek testreszabhatók vagy bővíthetők az örökölt sablonokban. A blokk előtt definiált környező változók a blokkon belül is elérhetőek, de a változók bármilyen módosítása csak az adott blokkban jelenik meg.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+A `{define}` címke olyan blokkok létrehozására szolgál, amelyek csak akkor kerülnek megjelenítésre, ha a `{include}` használatával hívják meg őket. Az ezekben a blokkokban elérhető változók attól függnek, hogy a definícióban meg vannak-e adva paraméterek. Ha paraméterek vannak megadva, csak ezek a paraméterek érhetők el. Ha nem, akkor annak a sablonnak az összes bemeneti változója elérhető, ahol a blokkok definiálva vannak.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+A `{parameters}` címkét arra használjuk, hogy a sablon elején kifejezetten deklaráljuk az elvárt bemeneti változókat. Így könnyen dokumentálhatók a várható változók és adattípusaik. Lehetőség van alapértelmezett értékek definiálására is.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+A `{include file}` címke egy teljes sablon beillesztésére szolgál. Ennek a sablonnak átadjuk mind a sablon bemeneti változóit, ahol a taget használjuk, mind az explicit módon definiált változókat. A célsablon azonban a `{parameters}` segítségével korlátozhatja a hatókörét.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Egy ugyanabban a sablonban definiált blokk beillesztésekor az összes környező és explicit módon definiált változót átadjuk neki:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+Ebben a példában a `$name` és a `$age` változókat a `blockName` blokknak adjuk át. Ugyanez a viselkedés vonatkozik a `{include parent}`.
+
+Egy másik sablonból származó blokk beillesztésekor csak a bemeneti változók és az explicit módon definiált változók kerülnek átadásra. A környező változók nem állnak automatikusan rendelkezésre.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` vagy `{extends}`
+---------------------------
+Ezek a címkék egy olyan elrendezést határoznak meg, amelyhez a gyermek sablon bemeneti változói és a blokkok előtt a kódban létrehozott változók kerülnek átadásra:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Sablon `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+A `{embed}` tag hasonló a `{include}` taghez, de lehetővé teszi blokkok beágyazását a sablonba. A `{include}`-tól eltérően csak explicit módon deklarált változókat ad át:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+Ebben a példában a `menu.latte` sablon csak a `$items` változóhoz fér hozzá.
+
+Ezzel szemben a `{embed}` belsejében lévő blokkok hozzáférnek az összes környező változóhoz:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+A `{import}` címke más sablonokból származó blokkok betöltésére szolgál. Az importált blokkoknak mind a bemeneti, mind az explicit módon deklarált változókat átadja.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+A `{sandbox}` címke elkülöníti a sablont a biztonságos feldolgozás érdekében. A változókat kizárólag explicit módon adjuk át.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/hu/creating-extension.texy b/latte/hu/creating-extension.texy
index 18afbba7cd..63d4ddc958 100644
--- a/latte/hu/creating-extension.texy
+++ b/latte/hu/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// egy elemző függvény, amely egyelőre csak egy csomópontot hoz létre.
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Ha új címkét hozunk létre a Latte számára, célszerű létrehozni egy külön node osztályt, amely az AST fában képviseli majd (lásd a `ForeachNode` osztályt a fenti példában). Bizonyos esetekben hasznos lehet az [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] triviális segédcsomópont-osztály, amely lehetővé teszi, hogy a `print()` metódus testét és a `getIterator()` metódus által elérhetővé tett csomópontok listáját konstruktorparaméterként átadjuk:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Compiler Passes .[#toc-compiler-passes]
 =======================================
 
diff --git a/latte/hu/develop.texy b/latte/hu/develop.texy
index 15d8116068..78d5e737db 100644
--- a/latte/hu/develop.texy
+++ b/latte/hu/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Helyszín .[#toc-locale]{data-version:3.0.18}
+============================================
+
+A Latte lehetővé teszi a helyi nyelv beállítását, amely befolyásolja a számok, dátumok és a rendezés formázását. A beállítás a `setLocale()` módszerrel történik. A locale azonosító követi az IETF nyelvi tag szabványát, amely a PHP `intl` kiterjesztését használja. Ez egy nyelvkódból és esetleg egy országkódból áll, például `en_US` az Egyesült Államokban az angol nyelvhez, `de_DE` a német nyelvhez Németországban, stb.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+A nyelvi beállítás befolyásolja a [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] és [bytes |filters#bytes] szűrőket.
+
+.[note]
+A PHP `intl` bővítményt igényli. A Latte beállítása nem befolyásolja a PHP globális nyelvi beállítását.
+
+
 Szigorú üzemmód .[#toc-strict-mode]{data-version:3.0.8}
 =======================================================
 
@@ -274,16 +290,25 @@ Ha egyéni címkéket használ, hozza létre az egyéni Lintert is, például `c
 // adja meg az autoload.php fájl tényleges elérési útvonalát
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// egyedi kiterjesztések hozzáadása itt
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// itt adja hozzá az egyéni kiterjesztéseket
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternatívaként átadhatja saját `Latte\Engine` objektumát is a Linter-nek:
+
+```php
+$latte = new Latte\Engine;
+// itt konfiguráljuk a $latte objektumot
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Sablonok betöltése egy karakterláncból .[#toc-loading-templates-from-a-string]
 ==============================================================================
diff --git a/latte/hu/extending-latte.texy b/latte/hu/extending-latte.texy
index aa1b38451f..3a5c70cb0b 100644
--- a/latte/hu/extending-latte.texy
+++ b/latte/hu/extending-latte.texy
@@ -68,6 +68,16 @@ Mint látható, a függvény a következő argumentumként a szűrő bal oldalá
 
 Természetesen a szűrőt reprezentáló függvény tetszőleges számú paramétert fogadhat el, és a változó paraméterek is támogatottak.
 
+Ha a szűrő egy karakterláncot ad vissza HTML-ben, akkor megjelölheted, hogy a Latte ne automatikusan (és ezért duplán) szedje ki. Így elkerülhető a `|noescape` megadása a sablonban.
+A legegyszerűbb, ha a sztringet egy `Latte\Runtime\Html` objektumba csomagoljuk, a másik lehetőség a [Contextual Filters |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+Ebben az esetben a szűrőnek biztosítania kell az adatok helyes kikerülését.
+
 
 Az osztályt használó szűrők .[#toc-filters-using-the-class]
 -----------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// a tartalomtípust HTML-re módosítja
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/hu/filters.texy b/latte/hu/filters.texy
index 6e67a8ec5f..fec3099615 100644
--- a/latte/hu/filters.texy
+++ b/latte/hu/filters.texy
@@ -7,63 +7,65 @@ A szűrők olyan függvények, amelyek megváltoztatják vagy formázzák az ada
 .[table-latte-filters]
 |## String / tömb átalakítás
 | `batch` | [lineáris adatok listázása egy táblázatban |#batch]
-| `breakLines` | [HTML sorkizárt beillesztése az újsorok előtt |#breakLines].
+| `breakLines` | [HTML sorkizárt beillesztése az újsorok előtt |#breakLines]
 | `bytes` | [méretformázás bájtban |#bytes]
-| `clamp` | [az értéket a tartományba szorítja |#clamp].
+| `clamp` | [az értéket a tartományba szorítja |#clamp]
 | `dataStream` | [Adat URI protokoll átalakítás |#datastream]
-| `date` | [dátumformázás |#date]
-| `explode` | [a karakterláncot a megadott elválasztóval osztja fel |#explode].
-| `first` | [visszaadja a tömb első elemét vagy a karakterlánc első karakterét |#first].
-| `implode` | [egy tömböt egy karakterlánccal kapcsol össze |#implode].
+| `date` | [dátum és idő formázása |#date]
+| `explode` | [a karakterláncot a megadott elválasztóval osztja fel |#explode]
+| `first` | [visszaadja a tömb első elemét vagy a karakterlánc első karakterét |#first]
+| `group` | [adatok csoportosítása különböző kritériumok |#group] szerint
+| `implode` | [egy tömböt egy karakterlánccal kapcsol össze |#implode]
 | `indent` | [a szöveget balról behúzza a tabulátorok számával |#indent]
-| `join` | [egy tömböt egy karakterlánchoz kapcsol |#implode].
-| `last` | [visszaadja a tömb utolsó elemét vagy a karakterlánc utolsó karakterét |#last].
-| `length` | [egy karakterlánc vagy tömb hosszát adja vissza |#length].
+| `join` | [egy tömböt egy karakterlánchoz kapcsol |#implode]
+| `last` | [visszaadja a tömb utolsó elemét vagy a karakterlánc utolsó karakterét |#last]
+| `length` | [egy karakterlánc vagy tömb hosszát adja vissza |#length]
+| `localDate` | [A dátum és az idő formázása a helyi beállításoknak megfelelően |#localDate]
 | `number` | [formázza a számot |#number]
-| `padLeft` | [balról balra kiegészíti a karakterláncot a megadott hosszúságúra |#padLeft].
-| `padRight` | [a stringet jobbról a megadott hosszúságra egészíti ki |#padRight].
-| `random` | [visszaadja a tömb véletlenszerű elemét vagy a karakterlánc karakterét |#random].
+| `padLeft` | [balról balra kiegészíti a karakterláncot a megadott hosszúságúra |#padLeft]
+| `padRight` | [a stringet jobbról a megadott hosszúságra egészíti ki |#padRight]
+| `random` | [visszaadja a tömb véletlenszerű elemét vagy a karakterlánc karakterét |#random]
 | `repeat` | [megismétli a karakterláncot |#repeat]
-| `replace` | [a keresett karakterlánc minden előfordulását helyettesíti a helyettesítő karakterlánccal |#replace].
-| `replaceRE` | [az összes előfordulást a reguláris kifejezésnek megfelelően helyettesíti |#replaceRE].
-| `reverse` | [megfordítja az UTF-8 karakterláncot vagy tömböt |#reverse].
-| `slice` | [kivonja egy tömb vagy egy karakterlánc egy szeletét |#slice].
+| `replace` | [a keresett karakterlánc minden előfordulását helyettesíti a helyettesítő karakterlánccal |#replace]
+| `replaceRE` | [az összes előfordulást a reguláris kifejezésnek megfelelően helyettesíti |#replaceRE]
+| `reverse` | [megfordítja az UTF-8 karakterláncot vagy tömböt |#reverse]
+| `slice` | [kivonja egy tömb vagy egy karakterlánc egy szeletét |#slice]
 | `sort` | [rendezi a tömböt |#sort]
-| `spaceless` | [eltávolítja a szóközöket |#spaceless], hasonlóan a [spaceless |tags] taghez.
-| `split` | [egy karakterláncot a megadott elválasztójel alapján szétválaszt |#explode].
+| `spaceless` | [eltávolítja a szóközöket |#spaceless], hasonlóan a [spaceless |tags] taghez
+| `split` | [egy karakterláncot a megadott elválasztójel alapján szétválaszt |#explode]
 | `strip` | [eltávolítja a szóközöket |#spaceless]
-| `stripHtml` | [eltávolítja a HTML-címkéket és a HTML-elemeket szöveggé alakítja át |#stripHtml].
+| `stripHtml` | [eltávolítja a HTML-címkéket és a HTML-elemeket szöveggé alakítja át |#stripHtml]
 | `substr` | [visszaadja a karakterlánc egy részét |#substr]
-| `trim` | [eltávolítja a szóközöket a karakterláncból |#trim].
+| `trim` | [eltávolítja a szóközöket a karakterláncból |#trim]
 | `translate` | [fordítás más nyelvekre |#translate]
-| `truncate` | [lerövidíti a hosszúságot, megőrizve az egész szavakat |#truncate].
-| `webalize` | [az UTF-8 karakterláncot az URL-ben használt formához igazítja |#webalize].
+| `truncate` | [lerövidíti a hosszúságot, megőrizve az egész szavakat |#truncate]
+| `webalize` | [az UTF-8 karakterláncot az URL-ben használt formához igazítja |#webalize]
 
 .[table-latte-filters]
 |## Betűhüvelyezés
 | `capitalize` | [kisbetűs, minden szó első betűje nagybetűs |#capitalize]
-| `firstUpper` | [az első betűt nagybetűvé teszi |#firstUpper].
+| `firstUpper` | [az első betűt nagybetűvé teszi |#firstUpper]
 | `lower` | [a karakterláncot kisbetűvé teszi |#lower]
 | `upper` | [nagybetűvé teszi a karakterláncot |#upper]
 
 .[table-latte-filters]
 |## Számok kerekítése
-| `ceil` | [kerekít egy számot egy adott pontosságig |#ceil].
-| `floor` | [Egy számot adott pontosságra kerekít lefelé |#floor].
-| `round` | [kerekít egy számot adott pontosságra |#round].
+| `ceil` | [kerekít egy számot egy adott pontosságig |#ceil]
+| `floor` | [Egy számot adott pontosságra kerekít lefelé |#floor]
+| `round` | [kerekít egy számot adott pontosságra |#round]
 
 .[table-latte-filters]
 |## Escaping
 | `escapeUrl` | [az URL-ben szereplő paramétert elrejti |#escapeUrl]
-| `noescape` | [változó nyomtatása szaggatás nélkül |#noescape].
-| `query` | [lekérdezési karakterláncot generál az URL-ben |#query].
+| `noescape` | [változó nyomtatása szaggatás nélkül |#noescape]
+| `query` | [lekérdezési karakterláncot generál az URL-ben |#query]
 
 A HTML (`escapeHtml` és `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) és iCalendar (`escapeICal`) számára is vannak escaping szűrők, amelyeket a Latte a [kontextustudatos escapingnek |safety-first#Context-aware escaping] köszönhetően maga használ, és nem kell megírni őket.
 
 .[table-latte-filters]
 |## Biztonság
-| `checkUrl` | [szanálja a href attribútumon belül használt karakterláncot |#checkUrl].
-| `nocheck` | [megakadályozza az automatikus URL-szanálást |#nocheck].
+| `checkUrl` | [szanálja a href attribútumon belül használt karakterláncot |#checkUrl]
+| `nocheck` | [megakadályozza az automatikus URL-szanálást |#nocheck]
 
 A `src` és a `href` attribútumokat [automatikusan ellenőrzi |safety-first#link checking], így a `checkUrl` szűrőt szinte nem is kell használni.
 
@@ -118,8 +120,8 @@ Szűrők .[#toc-filters]
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Szűrő, amely leegyszerűsíti a lineáris adatok táblázatos formában történő felsorolását. Egy tömb tömböt ad vissza a megadott számú elemmel. Ha megad egy második paramétert, akkor ezt az utolsó sor hiányzó elemeinek kitöltésére használja.
 
 ```latte
@@ -152,6 +154,8 @@ Nyomtatás:
 </table>
 ```
 
+Lásd még a [group |#group] és az [iterateWhile |tags#iterateWhile] címkét.
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ HTML-sorszünetet illeszt be minden újsor előtt.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Bájtban megadott méretet formázza ember által olvashatóvá.
+bytes(int $precision=2) .[filter]
+---------------------------------
+A bájtokban megadott méretet ember által olvasható formába formázza. Ha a [nyelvi tartomány |develop#locale] be van állítva, akkor a megfelelő tizedes és ezres elválasztójeleket használja.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Bájtban megadott méretet formázza ember által olvashatóvá.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Egy számot adott pontosságra kerekít.
 
 ```latte
@@ -203,8 +207,8 @@ Kényszeríti az URL szanálását. Ellenőrzi, hogy a változó tartalmaz-e web
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Nyomtat:
@@ -217,8 +221,8 @@ Nyomtat:
 Lásd [mégeck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 A min és max tartományba szorított értéket adja vissza.
 
 ```latte
@@ -228,14 +232,14 @@ A min és max tartományba szorított értéket adja vissza.
 Létezik [függvényként |functions#clamp] is.
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 A tartalmat adat URI-sémává alakítja át. Használható képek HTML- vagy CSS-be való beillesztésére anélkül, hogy külső fájlokat kellene linkelni.
 
 Legyen egy kép egy változóban `$img = Image::fromFile('obrazek.gif')`, akkor
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Kinyomtatja például:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 PHP-bővítményt igényel: `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Visszaad egy dátumot a megadott formátumban a [php:strftime] vagy [php:date] PHP függvények opcióinak használatával. A szűrő a dátumot UNIX időbélyegként, stringként vagy a `DateTime` típusú objektumként kapja meg.
+date(string $format) .[filter]
+------------------------------
+A dátumot és az időt a [php:date] PHP-funkció által használt maszknak megfelelően formázza. A szűrő elfogadja a dátumot UNIX időbélyeg formátumban, sztringként vagy `DateTimeInterface` objektumként.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Lásd még [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Kikerül egy változót, amelyet URL-ben paraméterként kell használni.
 Lásd még [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Egy karakterláncot a megadott elválasztójel alapján szétválaszt, és karakterláncok tömbjét adja vissza. Alias a `split` számára.
 
 ```latte
@@ -306,8 +311,8 @@ Visszaadja a tömb első elemét vagy a karakterlánc első karakterét:
 Lásd még [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Egy számot adott pontosságra kerekít.
 
 ```latte
@@ -330,8 +335,27 @@ Az érték első betűjét nagybetűvé alakítja. PHP-bővítményt igényel `m
 Lásd még [nagybetű |#capitalize], [kisbetű |#lower], [nagybetű |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+A szűrő különböző kritériumok szerint csoportosítja az adatokat.
+
+Ebben a példában a táblázat sorai a `categoryId` oszlop alapján vannak csoportosítva. A kimenet egy tömb tömbökből álló tömb, ahol a kulcs a `categoryId` oszlopban szereplő érték. Olvassa el a [részletes utasításokat |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Lásd még a [batch |#batch], a [group |functions#group] függvény és az [iterateWhile |tags#iterateWhile] tag.
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Visszaad egy stringet, amely a tömbben lévő stringek összevonása. Alias a következőhöz: `join`.
 
 ```latte
@@ -346,8 +370,8 @@ A `join` alias is használható:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 A szöveg balról történő behúzása egy adott számú tabulátorral vagy más karakterrel, amelyet a második választható argumentumban adunk meg. Az üres sorok nem kerülnek behúzásra.
 
 ```latte
@@ -396,6 +420,68 @@ Egy karakterlánc vagy tömb hosszát adja vissza.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+A dátum és az idő formázása a [nyelvterületnek |develop#locale] megfelelően, így biztosítva az időadatok konzisztens és lokalizált megjelenítését a különböző nyelveken és régiókban. A szűrő a dátumot UNIX időbélyegként, stringként vagy `DateTimeInterface` objektumként fogadja el.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Ha a szűrőt paraméterek nélkül használja, akkor a dátumot hosszú formátumban adja ki, ahogyan azt a továbbiakban kifejtjük.
+
+**a) A formátum használata**
+
+A `format` paraméter leírja, hogy mely időösszetevőket kell megjeleníteni. Betűkódokat használ, ahol az ismétlések száma befolyásolja a kimenet szélességét:
+
+| Év | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Hónap | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `aug.` / `augusztus`
+| Nap | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `V` / `vasárnap`
+| Hour | `j` / `H` / `h` | preferred / 24-hour / 12-hour
+| Perc | `m` / `mm` | `5` / `05` <small>(2 számjegy, ha másodpercekkel kombinálják)</small>
+| Másodperc | `s` / `ss` | `8` / `08` <small>(2 számjegy, ha percekkel kombinálva)</small>
+
+A kódok sorrendje a formátumban nem számít, mivel az összetevők sorrendje a helyi konvencióknak megfelelően jelenik meg. Ezért a formátum helytől független. Például a `yyyyMMMMd` formátum a `en_US` nyelvjárásban a `April 15, 2024`, míg a `cs_CZ` nyelvjárásban a `15. dubna 2024` formátumot adja ki:
+
+| locale:  | hu-HU | en_US
+|---
+| `format: 'dMy'` | 2024. 08. 10. | 8/10/2024
+| `format: 'yM'` | 2024. 8. | 8/2024
+| `format: 'yyyyMMMM'` | 2024. augusztus | August 2024
+| `format: 'MMMM'` | augusztus | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | du. 5:54 | 5:54 PM
+
+
+**b) Előre beállított stílusok használata**
+
+A `date` és a `time` paraméterek határozzák meg a dátum és az idő megjelenítésének részletességét. Több szint közül választhat: `full`, `long`, `medium`, `short`. Megjelenítheti csak a dátumot, csak az időt vagy mindkettőt:
+
+| locale:  | hu-HU | en_US
+|---
+| `date: short` | 1978. 01. 23. | 1/23/78
+| `date: medium` | 1978. jan. 23. | Jan 23, 1978
+| `date: long` | 1978. január 23. | January 23, 1978
+| `date: full` | 1978. január 23., hétfő | Monday, January 23, 1978
+| `time: short` | 8:30 | 8:30 AM
+| `time: medium` | 8:30:59 | 8:30:59 AM
+| `time: long` | 8:30:59 CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 1978. 01. 23. 8:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 1978. jan. 23. 8:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 1978. január 23. 8:30 | January 23, 1978 at 8:30 AM
+
+A dátumhoz használhatja a `relative-` előtagot is (pl. `relative-short`), amely a jelenhez közeli dátumok esetében a `yesterday`, `today` vagy `tomorrow`, egyébként a szokásos módon jelenik meg.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Lásd még [dátum |#date].
+
+
 lower .[filter]
 ---------------
 Egy értéket kisbetűvé alakít. PHP-bővítményt igényel `mbstring`.
@@ -416,8 +502,8 @@ Ha a hivatkozás más sémát használ, például `javascript:` vagy `data:`, é
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Nyomtatások:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 A `noescape` szűrő visszaélése XSS sebezhetőséghez vezethet! Soha ne használja, hacsak nem **teljesen biztos** abban, hogy mit csinál, és hogy a nyomtatott karakterlánc megbízható forrásból származik.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Egy számot adott számú tizedesjegyig formáz. Megadhatja a tizedesvessző és az ezres elválasztó karakterét is.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Egy számot a megadott számú tizedesjegyig formáz. Ha a [nyelvi terület |develop#locale] be van állítva, akkor a megfelelő tizedes és ezres elválasztójeleket használja.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Egy számot adott számú tizedesjegyig formáz. Megadhatja a tizedesvessző és
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+A `format` paraméter lehetővé teszi, hogy a számok megjelenését pontosan az Ön igényei szerint határozza meg. Beállított [nyelvterületet |develop#locale] igényel. A formátum több speciális karakterből áll, amelyek teljes leírása a "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns dokumentációban található:
+
+- <c id=6/> kötelező számjegy, mindig megjelenik, még akkor is, ha nulla.
+- `#` opcionális számjegy, csak akkor jelenik meg, ha a számnak van számjegye az adott helyen.
+- `@` szignifikáns számjegy, segít a számot bizonyos számú szignifikáns számjeggyel megjeleníteni.
+- `.` a tizedesvessző helyét jelöli (vessző vagy pont, a területi adattól függően).
+- `,` számjegycsoportok, általában ezrek elválasztására szolgál.
+- `%` megszorozza a számot 100-zal, és hozzáadja a százalékjelet.
+
+Nézzünk néhány példát. Az első példában a két tizedesjegy kötelező, a másodikban opcionális. A harmadik példa mindkét oldalon nullákkal való kitöltést mutat, a negyedik példa pedig csak a meglévő számjegyeket jeleníti meg:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+A szignifikáns számjegyek határozzák meg, hogy a tizedesvesszőtől függetlenül hány számjegyet kell megjeleníteni, szükség esetén kerekítve a számot:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Egy szám százalékban történő megjelenítésének egyszerű módja. A számot megszorozzuk 100-zal, és hozzáadjuk a `%` jelet:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+A pozitív és negatív számok számára eltérő formátumot határozhatunk meg, amelyet egy `;` karakterrel választunk el. Így például a pozitív számok a `+` jellel jeleníthetők meg:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Ne feledje, hogy a számok tényleges megjelenése a helyi beállításoktól függően változhat. Egyes országokban például pont helyett vesszőt használnak tizedesválasztóként. Ez a szűrő automatikusan figyelembe veszi ezt, így nem kell aggódnia emiatt.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Egy adott hosszúságú karakterláncot balról egy másik karakterlánccal kitölti.
 
@@ -472,7 +606,7 @@ Egy adott hosszúságú karakterláncot balról egy másik karakterlánccal kit
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Egy adott hosszúságú karakterláncot egy másik, jobbról jövő karakterlánccal kitölti.
 
@@ -514,8 +648,8 @@ Visszaadja a tömb véletlenszerű elemét vagy a karakterlánc karakterét:
 Lásd még [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Megismétli a karakterláncot x-szer.
 
 ```latte
@@ -523,7 +657,7 @@ Megismétli a karakterláncot x-szer.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 A keresett karakterlánc minden előfordulását helyettesítő karakterlánccal helyettesíti.
 
@@ -538,7 +672,7 @@ Egyszerre több csere is elvégezhető:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Az összes előfordulást helyettesíti a reguláris kifejezésnek megfelelően.
 
@@ -559,8 +693,8 @@ Megfordítja a megadott karakterláncot vagy tömböt.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Egy számot adott pontosságra kerekít.
 
 ```latte
@@ -573,7 +707,7 @@ Egy számot adott pontosságra kerekít.
 Lásd még [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Egy tömb vagy egy karakterlánc egy szeletének kivonása.
 
@@ -591,9 +725,9 @@ Ha a length értéke pozitív, akkor a szekvencia legfeljebb ennyi elemet tartal
 A Filter alapértelmezés szerint átrendezi és visszaállítja az integer tömb kulcsát. Ez a viselkedés megváltoztatható a preserveKeys true értékre állításával. A string kulcsok ettől a paramétertől függetlenül mindig megmaradnak.
 
 
-sort  .[filter]
----------------
-Szűrő, amely egy tömböt rendezi és fenntartja az index hozzárendelést.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+A szűrő egy tömb vagy iterátor elemeit rendezi, miközben megőrzi az asszociatív kulcsokat. Ha egy [területi |develop#locale] beállítás van megadva, a rendezés annak szabályait követi, kivéve, ha egyéni összehasonlító függvény van megadva.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ A tömb fordított sorrendbe rendezve.
 {/foreach}
 ```
 
-Saját összehasonlító függvényt adhat át paraméterként:
+Megadhat egy egyéni összehasonlító függvényt a rendezéshez (a példa azt mutatja, hogyan lehet a legnagyobbtól a legkisebbig megfordítani a rendezést):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+A `|sort` szűrő lehetővé teszi az elemek kulcs szerinti rendezését is:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Ha egy táblázatot egy adott oszlop szerint kell rendezni, használhatja a `by` paramétert. A példában szereplő `'name'` érték azt adja meg, hogy a rendezés a `$row->name` vagy a szerint történjen. `$row['name']`, attól függően, hogy a `$row` egy tömb vagy egy objektum:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Meghatározhat egy visszahívási függvényt is, amely meghatározza a rendezés értékét:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+A `byKey` paraméter ugyanígy használható.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ A HTML-t egyszerű szöveggé alakítja. Vagyis eltávolítja a HTML-címkéket,
 Az így kapott sima szöveg természetesen tartalmazhat olyan karaktereket, amelyek HTML-címkéket képviselnek, például a `'&lt;p&gt;'|stripHtml` átváltozik `<p>`. Soha ne adja ki az eredményül kapott szöveget a `|noescape` címmel, mivel ez biztonsági réshez vezethet.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Kivonja egy karakterlánc egy szeletét. Ezt a szűrőt felváltotta a [slice |#slice] szűrő.
 
 ```latte
@@ -655,8 +815,8 @@ Kivonja egy karakterlánc egy szeletét. Ezt a szűrőt felváltotta a [slice |#
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Kifejezéseket fordít le más nyelvekre. Ahhoz, hogy a szűrő elérhető legyen, be kell [állítania a fordítót |develop#TranslatorExtension]. A [címkéket |tags#Translation] is használhatja [a fordításhoz |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Kifejezéseket fordít le más nyelvekre. Ahhoz, hogy a szűrő elérhető legye
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Vezető és követő karakterek eltávolítása, alapértelmezés szerint szóköz.
 
 ```latte
@@ -675,7 +835,7 @@ Vezető és követő karakterek eltávolítása, alapértelmezés szerint szók
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Rövidíti a karakterláncot a megadott maximális hosszúságra, de megpróbálja megőrizni az egész szavakat. Ha a karakterlánc csonkolva van, ellipszist ad a végére (ez a második paraméterrel módosítható).
 
diff --git a/latte/hu/functions.texy b/latte/hu/functions.texy
index be9120f389..4fc3da164d 100644
--- a/latte/hu/functions.texy
+++ b/latte/hu/functions.texy
@@ -5,13 +5,15 @@ Latte funkciók
 Az általános PHP-funkciók mellett ezeket is használhatod a sablonokban.
 
 .[table-latte-filters]
-| `clamp` | [az értéket a tartományba szorítja |#clamp].
+| `clamp` | [az értéket a tartományba szorítja |#clamp]
 | `divisibleBy`| [ellenőrzi, hogy egy változó osztható-e egy számmal |#divisibleBy]
 | `even` | [ellenőrzi, hogy a megadott szám páros-e |#even]
-| `first` | [visszaadja a tömb első elemét vagy a karakterlánc első karakterét |#first].
-| `last` | [visszaadja a tömb utolsó elemét vagy a karakterlánc utolsó karakterét |#last].
-| `odd` | [ellenőrzi, hogy az adott szám páratlan-e |#odd].
-| `slice` | [kivonja egy tömb vagy egy karakterlánc egy szeletét |#slice].
+| `first` | [visszaadja a tömb első elemét vagy a karakterlánc első karakterét |#first]
+| `group` | [adatok csoportosítása különböző kritériumok szerint|#group]
+| `hasBlock` | [érzékeli egy blokk létezését |#hasBlock]
+| `last` | [visszaadja a tömb utolsó elemét vagy a karakterlánc utolsó karakterét |#last]
+| `odd` | [ellenőrzi, hogy az adott szám páratlan-e |#odd]
+| `slice` | [kivonja egy tömb vagy egy karakterlánc egy szeletét |#slice]
 
 
 Használat .[#toc-usage]
@@ -73,8 +75,8 @@ Ellenőrzi, hogy az adott szám páros-e.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Visszaadja a tömb első elemét vagy a karakterlánc első karakterét:
 
 ```latte
@@ -85,6 +87,36 @@ Visszaadja a tömb első elemét vagy a karakterlánc első karakterét:
 Lásd még [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Ez a funkció különböző kritériumok szerint csoportosítja az adatokat.
+
+Ebben a példában a táblázat sorait a `categoryId` oszlop alapján csoportosítja. A kimenet egy mezőkből álló tömb, ahol a kulcs a `categoryId` oszlopban szereplő érték. Olvassa el a [részletes utasításokat |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Lásd még [szűrőcsoport |filters#group].
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Ellenőrzi, hogy a megadott nevű blokk létezik-e:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Lásd még a [blokk létezésének ellenőrzése |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 A tömb utolsó elemét vagy a karakterlánc utolsó karakterét adja vissza:
@@ -106,8 +138,8 @@ Ellenőrzi, hogy a megadott szám páratlan-e.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Kivonja egy tömb vagy egy karakterlánc egy szeletét.
 
 ```latte
diff --git a/latte/hu/recipes.texy b/latte/hu/recipes.texy
index 099db80aa9..15ba057b29 100644
--- a/latte/hu/recipes.texy
+++ b/latte/hu/recipes.texy
@@ -9,7 +9,7 @@ Szerkesztők és IDE .[#toc-editors-and-ide]
 
 - A NetBeans IDE beépített támogatással rendelkezik
 - PhpStorm: telepítse a [Latte bővítményt |https://plugins.jetbrains.com/plugin/7457-latte] a `Settings > Plugins > Marketplace`
-- VS Code: keresse meg a markerplace-t a "Nette Latte + Neon" pluginnal.
+- VS kód: keresés markerplace a [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] vagy [Nette Latte sablonok |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] pluginhoz
 - Sublime Text 3: a Package Controlban keresse meg és telepítse a `Nette` csomagot és válassza ki a Latte-t a `View > Syntax`
 - a régi szerkesztőkben használja a Smarty kiemelést a .latte fájlokra
 
diff --git a/latte/hu/safety-first.texy b/latte/hu/safety-first.texy
index f13a4f2ee0..1df495fcb7 100644
--- a/latte/hu/safety-first.texy
+++ b/latte/hu/safety-first.texy
@@ -351,7 +351,7 @@ A Latte automatikusan ellenőrzi, hogy a `src` vagy a `href` attribútumban hasz
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Írja:
diff --git a/latte/hu/syntax.texy b/latte/hu/syntax.texy
index fb7a5ba3aa..61340ef0e8 100644
--- a/latte/hu/syntax.texy
+++ b/latte/hu/syntax.texy
@@ -98,7 +98,7 @@ Nyomtatás:
 A `tag-` előtag használatával a funkciót csak a HTML-címkékre alkalmazzuk:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 A `$url` változó értékétől függően ez kiírásra kerül:
@@ -155,6 +155,20 @@ Vagy közvetlenül az értékre (a [`{=expr}` | https://latte.nette.org/hu/tags#
 ```
 
 
+Dinamikus HTML címkék .[#toc-dynamic-html-tags]
+===============================================
+
+A Latte támogatja a dinamikus HTML címkéket, amelyek akkor hasznosak, ha a címkék nevének rugalmasságára van szükség:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Például a fenti kód képes generálni `<h1>Heading</h1>` vagy `<h2>Heading</h2>` a `$level` változó értékétől függően. A Latte dinamikus HTML-címkéket mindig párosítani kell. Alternatívájuk az [n:tag |tags#n:tag].
+
+Mivel a Latte egy biztonságos templating rendszer, ellenőrzi, hogy a kapott tag neve érvényes-e, és nem tartalmaz-e nem kívánt vagy rosszindulatú értékeket. Azt is biztosítja, hogy a végcímke neve mindig megegyezik a nyitócímke nevével.
+
+
 Hozzászólások .[#toc-comments]
 ==============================
 
diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy
index d718df8e62..07b861fd40 100644
--- a/latte/hu/tags.texy
+++ b/latte/hu/tags.texy
@@ -16,6 +16,7 @@ Az összes beépített Latte-címke összefoglalása és leírása.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [feltétel ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [tesztelés, hogy történt-e változás |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default]
+| `n:else` | [alternatív tartalom a feltételekhez |#n:else]
 
 .[table-latte-tags language-latte]
 |## Loops
@@ -97,8 +98,8 @@ Az összes beépített Latte-címke összefoglalása és leírása.
 | `{link}` | [linket nyomtat |application:creating-links#In the Presenter Template]
 | `{plink}` | [bemutatóra mutató link nyomtatása |application:creating-links#In the Presenter Template]
 | `{control}` | [komponens nyomtatása |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [AJAX-szel küldhető sablonrészlet |application:ajax#tag-snippet]
-| `{snippetArea}` | snippet borítékolás
+| `{snippet}`... `{/snippet}` | [AJAX-szel küldhető sablonrészlet |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [snippet borítékolás |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [egy sablonrészlet gyorsítótárba helyezése |caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Az összes beépített Latte-címke összefoglalása és leírása.
 | `{input}` | [nyomtat egy űrlap beviteli elemet |forms:rendering#label-input]
 | `{inputError}` | [hibaüzenetet nyomtat az űrlap beviteli eleméhez |forms:rendering#inputError]
 | `n:name` | [HTML beviteli elem aktiválása |forms:rendering#n:name]
-| `{formPrint}` | [Latte űrlap tervezetet készít |forms:rendering#formPrint]
-| `{formPrintClass}` | [PHP osztály nyomtatása az űrlap adataihoz |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [részleges űrlap renderelés |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [az űrlap tárolójának renderelése |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Tudtad, hogy az n:attribútumokhoz hozzáadhatod a `tag-` előtagot? Ekkor a fel
 Szép.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Ha a `{if} ... {/if}` feltételt [n:attribútum |syntax#n:attributes] formájában írja, akkor lehetősége van a `n:else` segítségével egy alternatív ágat is megadni:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+A `n:else` attribútum a következővel együtt is használható [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], és [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Lásd még [`{ifset block}` |template-inheritance#checking-block-existence]
 A `{ifset $var}` feltétel segítségével meghatározhatja, hogy egy változó (vagy több változó) létezik-e, és van-e nem null értékű értéke. Ez tulajdonképpen ugyanaz, mint a `if (isset($var))` a PHP-ben. Mint minden páros tag, ez is leírható [n:attribútum |syntax#n:attributes] formában, ezért mutassuk meg példában:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Ez elég praktikus, nem igaz?
 `{iterateWhile}`
 ----------------
 
-Egyszerűsíti a lineáris adatok csoportosítását a foreach ciklusban történő iteráció során azáltal, hogy az iterációt egy beágyazott ciklusban hajtja végre, amíg a feltétel teljesül. [Olvassa el az utasításokat a szakácskönyvben |cookbook/iteratewhile].
+Egyszerűsíti a lineáris adatok csoportosítását a foreach ciklusban történő iteráció során egy beágyazott ciklusban történő iterálással, amíg egy feltétel nem teljesül. [Olvassa el a részletes utasításokat |cookbook/grouping].
 
 Elegánsan helyettesítheti a `{first}` és a `{last}` címet is a fenti példában:
 
@@ -489,6 +501,8 @@ Elegánsan helyettesítheti a `{first}` és a `{last}` címet is a fenti példá
 {/foreach}
 ```
 
+Lásd még a [kötegelt |filters#batch] és [csoportos |filters#group] szűrőket.
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Ha a `$heading === null`, a `<h1>` címke változatlanul kiírásra kerül. Elle
 <h3 class="main">...</h3>
 ```
 
+Mivel a Latte egy biztonságos templating rendszer, ellenőrzi, hogy az új tag neve érvényes-e, és nem tartalmaz-e nem kívánt vagy rosszindulatú értékeket.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/hu/template-inheritance.texy b/latte/hu/template-inheritance.texy
index d0575b7cae..bed94f1ba5 100644
--- a/latte/hu/template-inheritance.texy
+++ b/latte/hu/template-inheritance.texy
@@ -132,7 +132,7 @@ Tippek .[#toc-tips]
 
 - Ha a `{layout}` címet használja egy sablonban, akkor annak a sablonban az első sabloncímkének kell lennie.
 
-- Az elrendezés [automatikusan kereshető |develop#automatic-layout-lookup] (mint [az előadókban |application:templates#search-for-templates]). Ebben az esetben, ha a sablonban nem kell elrendezés, akkor ezt a `{layout none}` címkével jelzi.
+- Az elrendezés [automatikusan kereshető |develop#automatic-layout-lookup] (mint [az előadókban |application:templates#Template Lookup]). Ebben az esetben, ha a sablonban nem kell elrendezés, akkor ezt a `{layout none}` címkével jelzi.
 
 - A `{layout}` címkének a `{extends}` aliasával rendelkezik.
 
@@ -396,6 +396,14 @@ A blokk neveként használhat egy változót vagy bármely PHP kifejezését. Eb
 {/ifset}
 ```
 
+A blokkok meglétét szintén a [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Tippek .[#toc-tips]
 -------------------
@@ -415,7 +423,7 @@ Tippek .[#toc-tips]
 Vízszintes újrafelhasználás `{import}` .{toc: Horizontal Reuse}
 ===============================================================
 
-A horizontális újrafelhasználás egy harmadik újrafelhasználhatósági és öröklési mechanizmus a Latte-ban. Lehetővé teszi, hogy blokkokat töltsön be más sablonokból. Ez hasonló ahhoz, mintha egy PHP-fájlt hoznál létre segédfüggvényekkel vagy egy tulajdonsággal.
+A horizontális újrafelhasználás a Latte harmadik újrafelhasználási és öröklési mechanizmusa. Lehetővé teszi a blokkok betöltését más sablonokból. Ez hasonló ahhoz, mintha PHP-ben létrehoznánk egy fájlt segédfüggvényekkel, majd betöltenénk a `require` segítségével.
 
 Bár a sablonok elrendezésének öröklése a Latte egyik legerősebb funkciója, az egyszerű öröklésre korlátozódik - egy sablon csak egy másik sablont terjeszthet ki. A horizontális újrafelhasználás egy módja a többszörös öröklés elérésének.
 
@@ -447,7 +455,7 @@ A `{import}` címkének kell lennie az első sabloncímkének a `{layout}` után
 
 Annyi `{import}` utasítást használhat egy adott sablonban, amennyit csak akar. Ha két importált sablon ugyanazt a blokkot definiálja, akkor az első nyer. A legnagyobb prioritást azonban a fő sablon kapja, amely bármelyik importált blokkot felülírhatja.
 
-Minden felülírt blokk fokozatosan bevonható, ha [szülői blokkként |#parent block] beillesztjük őket:
+A felülírt blokkok tartalma megőrizhető a blokknak a [szülő blokkhoz |#parent block] hasonló módon történő beillesztésével:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/it/@left-menu.texy b/latte/it/@left-menu.texy
index 68e71464d5..e99aa51e48 100644
--- a/latte/it/@left-menu.texy
+++ b/latte/it/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Per iniziare |Guide]
 - [Perché usare i modelli? |why-use]
-- Concetti
+- Concetti ⚗️
 	- La [sicurezza prima di tutto |Safety First]
 	- [Ereditarietà dei template |Template Inheritance]
 	- [Sistema di tipi |Type System]
 	- [Sandbox |Sandbox]
 
-- Per i progettisti
+- Per i progettisti 🎨
 	- [Sintassi |Syntax]
 	- [Tag |Tags]
 	- [Filtri |Filters]
 	- [Funzioni |Functions]
 	- [Suggerimenti e trucchi |recipes]
 
-- Per gli sviluppatori
+- Per gli sviluppatori 🧮
 	- [Pratiche per gli sviluppatori|develop]
 	- [Estensione di Latte |Extending Latte]
 	- [Creare un'estensione |creating-extension]
 
-- [Libro di cucina |cookbook/@home]
+- [Libro di cucina 💡|cookbook/@home]
 	- [Migrazione da Twig |cookbook/migration-from-twig]
 	- [... altro |cookbook/@home]
 
diff --git a/latte/it/cookbook/@home.texy b/latte/it/cookbook/@home.texy
index cf6e79c376..75fc7ec293 100644
--- a/latte/it/cookbook/@home.texy
+++ b/latte/it/cookbook/@home.texy
@@ -4,7 +4,9 @@ Libro di cucina
 .[perex]
 Codici di esempio e ricette per eseguire operazioni comuni con Latte.
 
-- [Tutto quello che avreste sempre voluto sapere su {iterateWhile} |iteratewhile]
+- [Linee guida per gli sviluppatori |/develop]
+- [Passaggio di variabili tra modelli |passing-variables]
+- [Tutto quello che avete sempre voluto sapere sul raggruppamento |grouping]
 - [Come scrivere query SQL in Latte? |how-to-write-sql-queries-in-latte]
 - [Migrazione da PHP |migration-from-php]
 - [Migrazione da Twig |migration-from-twig]
diff --git a/latte/it/cookbook/grouping.texy b/latte/it/cookbook/grouping.texy
new file mode 100644
index 0000000000..f79fd29425
--- /dev/null
+++ b/latte/it/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Tutto quello che avete sempre voluto sapere sul raggruppamento
+**************************************************************
+
+.[perex]
+Quando si lavora con i dati nei modelli, spesso si ha la necessità di raggrupparli o di visualizzarli in modo specifico in base a determinati criteri. A questo scopo, Latte offre diversi strumenti potenti.
+
+Il filtro e la funzione `|group` consentono di raggruppare efficacemente i dati in base a criteri specifici, mentre il filtro `|batch` facilita la suddivisione dei dati in lotti fissi e il tag `{iterateWhile}` offre la possibilità di un controllo del ciclo più complesso con condizioni.
+Ognuno di questi tag offre opzioni specifiche per lavorare con i dati, rendendoli strumenti indispensabili per la visualizzazione dinamica e strutturata delle informazioni nei modelli Latte.
+
+
+Filtro e funzione `group` .[#toc-filter-and-function-group]
+===========================================================
+
+Immaginate una tabella del database `items` con articoli suddivisi in categorie:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Mela
+| 2 | 1 | Banana
+| 3 | 2 | PHP
+| 4 | 3 | Verde
+| 5 | 3 | Rosso
+| 6 | 3 | Blu
+
+Un semplice elenco di tutti gli elementi utilizzando un modello Latte si presenterebbe come segue:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Tuttavia, se vogliamo che gli articoli siano organizzati in gruppi per categoria, dobbiamo dividerli in modo che ogni categoria abbia un proprio elenco. Il risultato sarebbe quindi simile a questo:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Il compito può essere risolto in modo semplice ed elegante utilizzando `|group`. Specifichiamo `categoryId` come parametro, il che significa che gli elementi saranno suddivisi in array più piccoli in base al valore di `$item->categoryId` (se `$item` fosse un array, useremmo `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Il filtro può essere usato anche come funzione in Latte, con una sintassi alternativa: `{foreach group($items, categoryId) ...}`.
+
+Se si desidera raggruppare gli elementi in base a criteri più complessi, è possibile utilizzare una funzione nel parametro del filtro. Ad esempio, il raggruppamento degli elementi in base alla lunghezza del loro nome può avvenire in questo modo:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+È importante notare che `$categoryItems` non è un normale array, ma un oggetto che si comporta come un iteratore. Per accedere al primo elemento del gruppo, si può usare la funzione [`first()` |latte:functions#first] la funzione.
+
+Questa flessibilità nel raggruppamento dei dati rende `group` uno strumento eccezionalmente utile per la presentazione dei dati nei modelli Latte.
+
+
+Cicli annidati .[#toc-nested-loops]
+-----------------------------------
+
+Supponiamo di avere una tabella di database con un'altra colonna `subcategoryId` che definisce le sottocategorie per ogni articolo. Vogliamo visualizzare ogni categoria principale in un elenco separato e ogni `<ul>` e ogni sottocategoria in un elenco annidato separato `<ol>` separato:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Connessione con il database Nette .[#toc-connection-with-nette-database]
+------------------------------------------------------------------------
+
+Mostriamo come utilizzare efficacemente il raggruppamento dei dati in combinazione con Nette Database. Supponiamo di lavorare con la tabella `items` dell'esempio iniziale, che è collegata attraverso la colonna `categoryId` a questa tabella `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Frutta |
+| 2 | Lingue |
+| 3 | Colori |
+
+Carichiamo i dati dalla tabella `items` utilizzando il comando `$items = $db->table('items')` di Nette Database Explorer. Durante l'iterazione su questi dati, abbiamo la possibilità non solo di accedere ad attributi come `$item->name` e `$item->categoryId`, ma, grazie alla connessione con la tabella `categories`, anche alla relativa riga in essa contenuta tramite `$item->category`. Questa connessione può rivelarsi interessante:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+In questo caso, utilizziamo il filtro `|group` per raggruppare in base alla riga collegata `$item->category`, non solo in base alla colonna `categoryId`. In questo modo si ottiene il `ActiveRow` della categoria data nella chiave variabile, consentendo di visualizzarne direttamente il nome utilizzando `{$category->name}`. Questo è un esempio pratico di come il raggruppamento possa semplificare i modelli e facilitare la gestione dei dati.
+
+
+Filtro `|batch` .[#toc-filter-batch]
+====================================
+
+Il filtro consente di suddividere un elenco di elementi in gruppi con un numero predeterminato di elementi. Questo filtro è ideale per le situazioni in cui si desidera presentare i dati in diversi gruppi più piccoli, ad esempio per una migliore chiarezza o organizzazione visiva della pagina.
+
+Immaginiamo di avere un elenco di elementi e di volerli visualizzare in elenchi, ciascuno contenente un massimo di tre elementi. L'uso del filtro `|batch` è molto pratico in questo caso:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+In questo esempio, l'elenco `$items` viene suddiviso in gruppi più piccoli, ciascuno dei quali (`$batch`) contiene un massimo di tre elementi. Ogni gruppo viene quindi visualizzato in un elenco `<ul>` elenco separato.
+
+Se l'ultimo gruppo non contiene abbastanza elementi per raggiungere il numero desiderato, il secondo parametro del filtro consente di definire con cosa verrà integrato questo gruppo. Questo è ideale per allineare esteticamente gli elementi in cui una riga incompleta potrebbe sembrare disordinata.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Tag `{iterateWhile}` .[#toc-tag-iteratewhile]
+=============================================
+
+Dimostreremo gli stessi compiti che abbiamo affrontato con il filtro `|group` utilizzando il tag `{iterateWhile}`. La differenza principale tra i due approcci è che `group` elabora e raggruppa prima tutti i dati in ingresso, mentre `{iterateWhile}` controlla l'avanzamento dei cicli con le condizioni, quindi l'iterazione avviene in modo sequenziale.
+
+Per prima cosa, disegniamo una tabella con le categorie usando iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Mentre `{foreach}` segna la parte esterna del ciclo, cioè il disegno di liste per ogni categoria, il tag `{iterateWhile}` segna la parte interna, cioè i singoli elementi.
+La condizione nel tag end dice che la ripetizione continuerà finché l'elemento corrente e quello successivo appartengono alla stessa categoria (`$iterator->nextValue` è l'[elemento successivo |/tags#$iterator]).
+
+Se la condizione fosse sempre soddisfatta, tutti gli elementi verrebbero disegnati nel ciclo interno:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Il risultato sarà simile a questo:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+A cosa serve iterareWhile in questo modo? Quando la tabella è vuota e non contiene elementi, non viene stampato alcun elemento vuoto. `<ul></ul>` viene stampato.
+
+Se si specifica la condizione nel tag di apertura `{iterateWhile}`, il comportamento cambia: la condizione (e la transizione all'elemento successivo) viene eseguita all'inizio del ciclo interno, non alla fine.
+Così, mentre si entra sempre in `{iterateWhile}` senza condizioni, si entra in `{iterateWhile $cond}` solo quando la condizione `$cond` è soddisfatta. Allo stesso tempo, l'elemento successivo viene scritto in `$item`.
+
+Questo è utile, ad esempio, in una situazione in cui si vuole rendere il primo elemento di ogni categoria in modo diverso, come in questo caso:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Modifichiamo il codice originale in modo da rendere prima il primo elemento e poi nel ciclo interno `{iterateWhile}` rendiamo gli altri elementi della stessa categoria:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+All'interno di un ciclo, possiamo creare più cicli interni e persino annidarli. In questo modo, si possono raggruppare le sottocategorie, per esempio.
+
+Supponiamo che la tabella abbia un'altra colonna `subcategoryId`, e che oltre a ciascuna categoria sia in una sezione separata `<ul>`, ogni sottocategoria in un ciclo separato `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/it/cookbook/iteratewhile.texy b/latte/it/cookbook/iteratewhile.texy
deleted file mode 100644
index 273c5d87e9..0000000000
--- a/latte/it/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Tutto quello che avete sempre voluto sapere su {iterateWhile}
-*************************************************************
-
-.[perex]
-Il tag `{iterateWhile}` è adatto a vari trucchi nei cicli foreach.
-
-Supponiamo di avere la seguente tabella di database, in cui gli articoli sono divisi in categorie:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Naturalmente, disegnare gli elementi in un ciclo foreach come elenco è facile:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Ma cosa fare se si vuole rendere ogni categoria in un elenco separato? In altre parole, come risolvere il compito di raggruppare gli elementi di un elenco lineare in un ciclo foreach. L'output dovrebbe essere simile a questo:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Vi mostreremo come questo compito possa essere risolto in modo semplice ed elegante con iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Mentre `{foreach}` segna la parte esterna del ciclo, cioè il disegno delle liste per ogni categoria, i tag `{iterateWhile}` indicano la parte interna, cioè i singoli elementi.
-La condizione nel tag end dice che la ripetizione continuerà finché l'elemento corrente e quello successivo appartengono alla stessa categoria (`$iterator->nextValue` è l'[elemento successivo |/tags#$iterator]).
-
-Se la condizione è sempre soddisfatta, allora tutti gli elementi vengono disegnati nel ciclo interno:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Il risultato sarà simile a questo:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-A cosa serve questo uso di iterateWhile? In cosa differisce dalla soluzione mostrata all'inizio di questo tutorial? La differenza è che se la tabella è vuota e non contiene alcun elemento, non verrà resa vuota `<ul></ul>`.
-
-
-Soluzione senza `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-----------------------------------------------------------------------
-
-Se risolvessimo lo stesso compito con costruzioni completamente elementari di sistemi di template, per esempio in Twig, Blade o PHP puro, la soluzione sarebbe simile a questa:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* chiudiamo la precedente <ul>, se non è il primo elemento *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* apriremo una nuova lista *}
-	<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* chiudiamo l'ultima lista *}
-	</ul>
-{/if}
-```
-
-Tuttavia, questo codice è incomprensibile e poco intuitivo. Il collegamento tra i tag HTML di apertura e di chiusura non è affatto chiaro. Non è chiaro a prima vista se c'è un errore. E richiede variabili ausiliarie come `$prevCatId`.
-
-Al contrario, la soluzione con `{iterateWhile}` è pulita, chiara, non necessita di variabili ausiliarie ed è a prova di errore.
-
-
-Condizione nel tag di chiusura .[#toc-condition-in-the-closing-tag]
--------------------------------------------------------------------
-
-Se si specifica una condizione nel tag di apertura `{iterateWhile}`, il comportamento cambia: la condizione (e l'avanzamento all'elemento successivo) viene eseguita all'inizio del ciclo interno, non alla fine.
-Così, mentre `{iterateWhile}` senza condizione viene sempre inserito, `{iterateWhile $cond}` viene inserito solo quando la condizione `$cond` è soddisfatta. Allo stesso tempo, il seguente elemento viene scritto in `$item`.
-
-Questo è utile, ad esempio, in una situazione in cui si vuole rendere il primo elemento di ogni categoria in modo diverso, come ad esempio:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Modifichiamo il codice originale, disegniamo il primo elemento e poi altri elementi della stessa categoria nel ciclo interno `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Cicli annidati .[#toc-nested-loops]
------------------------------------
-
-È possibile creare più cicli interni in un ciclo e persino annidarli. In questo modo, ad esempio, si possono raggruppare le sottocategorie.
-
-Supponiamo che ci sia un'altra colonna nella tabella `subCatId` e che, oltre ad avere ogni categoria in una sezione separata, ogni sottocategoria sia in una sezione separata. `<ul>`ogni sottocategoria sarà in una colonna separata `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtro |batch .[#toc-filter-batch]
-----------------------------------
-
-Il raggruppamento degli elementi lineari è fornito anche da un filtro `batch`, in lotti con un numero fisso di elementi:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Può essere sostituito da iterateWhile come segue:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/it/cookbook/passing-variables.texy b/latte/it/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..c0293f0b51
--- /dev/null
+++ b/latte/it/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Passaggio di variabili tra modelli
+**********************************
+
+Questa guida spiega come si passano le variabili tra i template di Latte utilizzando vari tag come `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` e altri. Imparerete anche come lavorare con le variabili nei tag `{block}` e `{define}` e lo scopo del tag `{parameters}`.
+
+
+Tipi di variabili .[#toc-types-of-variables]
+--------------------------------------------
+Le variabili di Latte possono essere suddivise in tre categorie in base a come e dove vengono definite:
+
+Le **variabili di input** sono quelle che vengono passate al template dall'esterno, ad esempio da uno script PHP o utilizzando un tag come `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+Le **Variabili di contorno** sono le variabili esistenti nella posizione di uno specifico tag. Queste includono tutte le variabili di input e altre variabili create usando tag come `{var}`, `{default}`, o all'interno di un ciclo `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+Le **Variabili esplicite** sono quelle specificate direttamente all'interno di un tag e inviate al template di destinazione.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Il tag `{block}` è usato per definire blocchi di codice riutilizzabili che possono essere personalizzati o estesi in modelli ereditati. Le variabili circostanti definite prima del blocco sono disponibili all'interno del blocco, ma qualsiasi modifica alle variabili si riflette solo all'interno del blocco.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Il tag `{define}` è usato per creare blocchi che vengono resi solo quando vengono chiamati usando `{include}`. Le variabili disponibili all'interno di questi blocchi dipendono dalla presenza o meno di parametri nella definizione. Se i parametri sono specificati, solo quelli sono accessibili. In caso contrario, sono accessibili tutte le variabili di input del template in cui sono definiti i blocchi.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Il tag `{parameters}` è usato per dichiarare esplicitamente le variabili di input attese all'inizio del template. In questo modo, è possibile documentare facilmente le variabili attese e i loro tipi di dati. È anche possibile definire valori predefiniti.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Il tag `{include file}` è usato per inserire un intero template. A questo template vengono passate sia le variabili di input del template in cui viene usato il tag, sia variabili definite esplicitamente. Tuttavia, il template di destinazione può limitare l'ambito utilizzando `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Quando si inserisce un blocco definito nello stesso modello, gli vengono passate tutte le variabili circostanti ed esplicitamente definite:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+In questo esempio, le variabili `$name` e `$age` vengono passate al blocco `blockName`. Lo stesso comportamento si applica a `{include parent}`.
+
+Quando si inserisce un blocco da un altro template, vengono passate solo le variabili di input e quelle definite esplicitamente. Le variabili circostanti non sono automaticamente disponibili.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` o `{extends}`
+------------------------
+Questi tag definiscono un layout a cui passano le variabili di input del template figlio e le variabili create nel codice prima dei blocchi:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Template `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Il tag `{embed}` è simile al tag `{include}`, ma consente di incorporare blocchi nel template. A differenza di `{include}`, vengono passate solo le variabili dichiarate esplicitamente:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+In questo esempio, il template `menu.latte` ha accesso solo alla variabile `$items`.
+
+Al contrario, i blocchi all'interno di `{embed}` hanno accesso a tutte le variabili circostanti:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Il tag `{import}` è usato per caricare blocchi da altri template. Ai blocchi importati vengono passati sia input che variabili dichiarate esplicitamente.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Il tag `{sandbox}` isola il template per un'elaborazione sicura. Le variabili sono passate esclusivamente in modo esplicito.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/it/creating-extension.texy b/latte/it/creating-extension.texy
index a321dfa0a8..1ab63db38d 100644
--- a/latte/it/creating-extension.texy
+++ b/latte/it/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// una funzione di parsing che per ora crea solo un nodo
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+Nodo ausiliario .[#toc-auxiliarynode]
+-------------------------------------
+
+Se si sta creando un nuovo tag per Latte, è consigliabile creare una classe di nodi dedicata, che lo rappresenti nell'albero AST (si veda la classe `ForeachNode` nell'esempio precedente). In alcuni casi, potrebbe essere utile la classe di nodi ausiliari [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], che consente di passare il corpo del metodo `print()` e l'elenco dei nodi resi accessibili dal metodo `getIterator()` come parametri del costruttore:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Il compilatore passa .[#toc-compiler-passes]
 ============================================
 
diff --git a/latte/it/develop.texy b/latte/it/develop.texy
index 4f9fc093a1..4ef1b775b2 100644
--- a/latte/it/develop.texy
+++ b/latte/it/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Locale .[#toc-locale]{data-version:3.0.18}
+==========================================
+
+Latte consente di impostare il locale, che influisce sulla formattazione di numeri, date e ordinamenti. Viene impostato con il metodo `setLocale()`. L'identificatore di locale segue lo standard IETF per i tag di lingua, che utilizza l'estensione PHP `intl`. È composto da un codice di lingua ed eventualmente da un codice di paese, ad esempio `en_US` per l'inglese negli Stati Uniti, `de_DE` per il tedesco in Germania, ecc.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+L'impostazione del locale influisce sui filtri [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] e [bytes |filters#bytes].
+
+.[note]
+Richiede l'estensione PHP `intl`. L'impostazione di Latte non influisce sull'impostazione globale del locale in PHP.
+
+
 Modalità rigorosa .[#toc-strict-mode]{data-version:3.0.8}
 =========================================================
 
@@ -274,16 +290,25 @@ Se si usano tag personalizzati, creare anche un Linter personalizzato, ad esempi
 // inserire il percorso effettivo del file autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// aggiungere qui le singole estensioni
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// aggiungere qui le estensioni individuali
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+In alternativa, è possibile passare il proprio oggetto `Latte\Engine` a Linter:
+
+```php
+$latte = new Latte\Engine;
+// Qui configuriamo l'oggetto $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Caricare modelli da una stringa .[#toc-loading-templates-from-a-string]
 =======================================================================
diff --git a/latte/it/extending-latte.texy b/latte/it/extending-latte.texy
index 913314c0ad..a64f7c8f76 100644
--- a/latte/it/extending-latte.texy
+++ b/latte/it/extending-latte.texy
@@ -68,6 +68,16 @@ Come si può vedere, la funzione riceve il lato sinistro del filtro prima della
 
 Naturalmente, la funzione che rappresenta il filtro può accettare un numero qualsiasi di parametri e sono supportati anche i parametri variabili.
 
+Se il filtro restituisce una stringa in HTML, è possibile contrassegnarla in modo che Latte non esegua automaticamente (e quindi doppiamente) l'escape. Questo evita la necessità di specificare `|noescape` nel template.
+Il modo più semplice è avvolgere la stringa in un oggetto `Latte\Runtime\Html`, l'altro modo è [Filtri contestuali |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+In questo caso, il filtro deve garantire il corretto escape dei dati.
+
 
 Filtri che utilizzano la classe .[#toc-filters-using-the-class]
 ---------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// cambia il tipo di contenuto in HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/it/filters.texy b/latte/it/filters.texy
index 024d7cd79d..2ec0315540 100644
--- a/latte/it/filters.texy
+++ b/latte/it/filters.texy
@@ -11,14 +11,16 @@ I filtri sono funzioni che modificano o formattano i dati nella forma desiderata
 | `bytes` | [Formatta la dimensione in byte |#bytes]
 | `clamp` | [blocca il valore all'intervallo |#clamp]
 | `dataStream` | [Conversione del protocollo URI dei dati |#datastream]
-| `date` | [formatta la data |#date]
+| `date` | [formatta la data e l'ora |#date]
 | `explode` | [divide una stringa in base al delimitatore dato |#explode]
 | `first` | [restituisce il primo elemento di un array o un carattere di una stringa |#first]
+| `group` | [raggruppa i dati secondo vari criteri |#group]
 | `implode` | [unisce un array a una stringa |#implode]
 | `indent` | [indenta il testo da sinistra con un certo numero di tabulazioni |#indent]
 | `join` | [unisce un array a una stringa |#implode]
 | `last` | [restituisce l'ultimo elemento di un array o un carattere di una stringa |#last]
 | `length` | [restituisce la lunghezza di una stringa o di un array |#length]
+| `localDate` | [formatta la data e l'ora in base al locale |#localDate]
 | `number` | [formatta un numero |#number]
 | `padLeft` | [completa la stringa alla lunghezza data da sinistra |#padLeft]
 | `padRight` | [completa la stringa alla lunghezza data da destra |#padRight]
@@ -118,8 +120,8 @@ Filtri .[#toc-filters]
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filtro che semplifica l'elencazione di dati lineari sotto forma di tabella. Restituisce un array di array con il numero di elementi indicato. Se si fornisce un secondo parametro, questo viene utilizzato per riempire gli elementi mancanti nell'ultima riga.
 
 ```latte
@@ -152,6 +154,8 @@ Stampa:
 </table>
 ```
 
+Vedere anche [gruppo |#group] e tag [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Inserisce le interruzioni di riga HTML prima di tutti i newline.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formatta una dimensione in byte in forma leggibile.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formatta la dimensione in byte in una forma leggibile. Se il [locale |develop#locale] è impostato, vengono utilizzati i corrispondenti separatori decimali e delle migliaia.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formatta una dimensione in byte in forma leggibile.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Arrotonda un numero fino a una determinata precisione.
 
 ```latte
@@ -203,8 +207,8 @@ Impone la sanitizzazione degli URL. Controlla se la variabile contiene un URL we
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Stampa:
@@ -217,8 +221,8 @@ Stampa:
 Vedere anche [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Restituisce un valore limitato all'intervallo inclusivo di min e max.
 
 ```latte
@@ -228,14 +232,14 @@ Restituisce un valore limitato all'intervallo inclusivo di min e max.
 Esiste anche come [funzione |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Converte il contenuto in uno schema URI di dati. Può essere usato per inserire immagini in HTML o CSS senza la necessità di collegare file esterni.
 
 Poniamo di avere un'immagine in una variabile `$img = Image::fromFile('obrazek.gif')`, allora
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Stampa ad esempio:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Richiede l'estensione PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Restituisce una data nel formato indicato, utilizzando le opzioni delle funzioni PHP [php:strftime] o [php:date]. Il filtro ottiene una data come timestamp UNIX, una stringa o un oggetto di tipo `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formatta la data e l'ora secondo la maschera utilizzata dalla funzione PHP [php:date]. Il filtro accetta la data in formato UNIX timestamp, come stringa o come oggetto `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Vedere anche [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Permette di separare una variabile da usare come parametro nell'URL.
 Vedere anche [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Divide una stringa in base al delimitatore dato e restituisce un array di stringhe. Alias di `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Restituisce il primo elemento di una matrice o un carattere di una stringa:
 Vedere anche [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Arrotonda un numero fino a una determinata precisione.
 
 ```latte
@@ -330,8 +335,27 @@ Converte la prima lettera di un valore in maiuscolo. Richiede l'estensione PHP `
 Vedere anche [capitalize |#capitalize], [lower |#lower], [upper |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Il filtro raggruppa i dati in base a diversi criteri.
+
+In questo esempio, le righe della tabella sono raggruppate in base alla colonna `categoryId`. L'output è un array di array in cui la chiave è il valore della colonna `categoryId`. Leggete le [istruzioni dettagliate |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Vedere anche [batch |#batch], la funzione [group |functions#group] e il tag [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Restituisce una stringa che è la concatenazione delle stringhe dell'array. Alias di `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Restituisce una stringa che è la concatenazione delle stringhe dell'array. Alia
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Rientra un testo da sinistra di un determinato numero di tabulazioni o di altri caratteri, specificati nel secondo argomento opzionale. Le righe vuote non sono rientrate.
 
 ```latte
@@ -396,6 +420,68 @@ Restituisce la lunghezza di una stringa o di un array.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formatta la data e l'ora in base al [locale |develop#locale], garantendo una visualizzazione coerente e localizzata dei dati temporali in diverse lingue e regioni. Il filtro accetta la data come timestamp UNIX, stringa o oggetto `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Se si utilizza il filtro senza alcun parametro, verrà emessa la data nel livello di formato lungo, come spiegato più avanti.
+
+**a) Utilizzo del formato**
+
+Il parametro `format` descrive quali componenti dell'ora devono essere visualizzati. Utilizza codici di lettere, il cui numero di ripetizioni influisce sull'ampiezza dell'output:
+
+| Anno | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Mese | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `ago` / `agosto`
+| Giorno | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `dom` / `domenica`
+| Ora | `j` / `H` / `h` | preferito / 24 ore / 12 ore
+| Minuto | `m` / `mm` | `5` / `05` <small>(2 cifre se combinato con i secondi)</small>
+| Secondo | `s` / `ss` | `8` / `08` <small>(2 cifre se combinato con i minuti)</small>
+
+L'ordine dei codici nel formato non ha importanza, poiché l'ordine dei componenti sarà visualizzato in base alle convenzioni del locale. Pertanto, il formato è indipendente dal locale. Ad esempio, il formato `yyyyMMMMd` nel locale `en_US` produce `April 15, 2024`, mentre nel locale `cs_CZ` produce `15. dubna 2024`:
+
+| locale:  | it-IT | en_US
+|---
+| `format: 'dMy'` | 10/8/2024 | 8/10/2024
+| `format: 'yM'` | 8/2024 | 8/2024
+| `format: 'yyyyMMMM'` | agosto 2024 | August 2024
+| `format: 'MMMM'` | agosto | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 PM | 5:54 PM
+
+
+**b) Utilizzo di stili preimpostati**
+
+I parametri `date` e `time` determinano il livello di dettaglio della visualizzazione di data e ora. È possibile scegliere tra diversi livelli: `full`, `long`, `medium`, `short`. È possibile visualizzare solo la data, solo l'ora o entrambe:
+
+| locale:  | it-IT | en_US
+|---
+| `date: short` | 23/01/78 | 1/23/78
+| `date: medium` | 23 gen 1978 | Jan 23, 1978
+| `date: long` | 23 gennaio 1978 | January 23, 1978
+| `date: full` | lunedì 23 gennaio 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23/01/78, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 gen 1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 gennaio 1978 alle ore 08:30 | January 23, 1978 at 8:30 AM
+
+Per la data si può anche usare il prefisso `relative-` (ad esempio, `relative-short`), che per le date vicine al presente visualizzerà `yesterday`, `today`, o `tomorrow`; altrimenti, verrà visualizzato nel modo standard.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Vedere anche [data |#date].
+
+
 lower .[filter]
 ---------------
 Converte un valore in minuscolo. Richiede l'estensione PHP `mbstring`.
@@ -416,8 +502,8 @@ Se il link utilizza uno schema diverso, come `javascript:` o `data:`, e si è si
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Stampe:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 L'uso improprio del filtro `noescape` può portare a una vulnerabilità XSS! Non utilizzatelo mai a meno che non siate **assolutamente sicuri** di quello che state facendo e che la stringa che state stampando provenga da una fonte affidabile.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formatta un numero con un determinato numero di cifre decimali. È anche possibile specificare un carattere del punto decimale e del separatore delle migliaia.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formatta un numero con un numero specificato di cifre decimali. Se il [locale |develop#locale] è impostato, vengono utilizzati i corrispondenti separatori decimali e delle migliaia.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Formatta un numero con un determinato numero di cifre decimali. È anche possibi
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Il parametro `format` consente di definire l'aspetto dei numeri esattamente secondo le proprie esigenze. Richiede un [locale |develop#locale] impostato. Il formato consiste in diversi caratteri speciali, la cui descrizione completa si trova nella documentazione "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> cifra obbligatoria, sempre visualizzata anche se è zero
+- `#` cifra opzionale, visualizzata solo se il numero ha una cifra in quel posto
+- `@` cifra significativa, aiuta a visualizzare il numero con un certo numero di cifre significative
+- `.` segna la posizione del separatore decimale (virgola o punto, a seconda del locale)
+- `,` si usa per separare gruppi di cifre, di solito le migliaia
+- `%` moltiplica il numero per 100 e aggiunge il segno di percentuale
+
+Vediamo alcuni esempi. Nel primo esempio, le due cifre decimali sono obbligatorie; nel secondo, sono facoltative. Il terzo esempio mostra un'imbottitura con zeri su entrambi i lati, mentre il quarto visualizza solo le cifre esistenti:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Le cifre significative determinano il numero di cifre da visualizzare, indipendentemente dal punto decimale, arrotondando il numero se necessario:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Un modo semplice per visualizzare un numero come percentuale. Il numero viene moltiplicato per 100 e viene aggiunto il segno `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Possiamo definire un formato diverso per i numeri positivi e negativi, separati da un carattere `;`. In questo modo, ad esempio, i numeri positivi possono essere visualizzati con il segno `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Ricordate che l'aspetto effettivo dei numeri può variare a seconda delle impostazioni locali. Ad esempio, in alcuni Paesi si usa una virgola al posto del punto come separatore decimale. Questo filtro ne tiene conto automaticamente, quindi non è necessario preoccuparsene.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Imbottisce una stringa di una certa lunghezza con un'altra stringa a partire da sinistra.
 
@@ -472,7 +606,7 @@ Imbottisce una stringa di una certa lunghezza con un'altra stringa a partire da
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Imbottisce una stringa di una certa lunghezza con un'altra stringa proveniente da destra.
 
@@ -514,8 +648,8 @@ Restituisce un elemento casuale di una matrice o un carattere di una stringa:
 Vedere anche [primo |#first], [ultimo |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Ripete la stringa x volte.
 
 ```latte
@@ -523,7 +657,7 @@ Ripete la stringa x volte.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Sostituisce tutte le occorrenze della stringa di ricerca con la stringa di sostituzione.
 
@@ -538,7 +672,7 @@ Sostituisce tutte le occorrenze della stringa di ricerca con la stringa di sosti
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Sostituisce tutte le occorrenze in base all'espressione regolare.
 
@@ -559,8 +693,8 @@ Inverte la stringa o l'array dato.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Arrotonda un numero a una determinata precisione.
 
 ```latte
@@ -573,7 +707,7 @@ Arrotonda un numero a una determinata precisione.
 Vedere anche [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Estrae una fetta di un array o di una stringa.
 
@@ -591,9 +725,9 @@ Se la lunghezza è data ed è positiva, la sequenza conterrà fino a quel numero
 Per impostazione predefinita, Filter riordina e reimposta le chiavi dell'array di interi. Questo comportamento può essere modificato impostando preserveKeys su true. Le chiavi stringa vengono sempre conservate, indipendentemente da questo parametro.
 
 
-sort  .[filter]
----------------
-Filtro che ordina un array e mantiene l'associazione degli indici.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Il filtro ordina gli elementi di un array o di un iteratore preservandone le chiavi associative. Quando viene impostato un [locale |develop#locale], l'ordinamento segue le sue regole, a meno che non venga specificata una funzione di confronto personalizzata.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Array ordinato in ordine inverso.
 {/foreach}
 ```
 
-È possibile passare la propria funzione di confronto come parametro:
+È possibile specificare una funzione di confronto personalizzata per l'ordinamento (l'esempio mostra come invertire l'ordinamento dal più grande al più piccolo):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Il filtro `|sort` consente anche di ordinare gli elementi per chiave:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Se si desidera ordinare una tabella in base a una colonna specifica, è possibile utilizzare il parametro `by`. Il valore `'name'` nell'esempio specifica che l'ordinamento sarà effettuato da `$row->name` o da `$row['name']`a seconda che `$row` sia una matrice o un oggetto:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Si può anche definire una funzione di callback che determina il valore da ordinare:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Il parametro `byKey` può essere utilizzato allo stesso modo.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Converte l'HTML in testo normale. Ossia, rimuove i tag HTML e converte le entit
 Il testo normale risultante può naturalmente contenere caratteri che rappresentano tag HTML, ad esempio `'&lt;p&gt;'|stripHtml` viene convertito in `<p>`. Non inviare mai il testo risultante con `|noescape`, perché ciò potrebbe causare una vulnerabilità della sicurezza.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Estrae una fetta di una stringa. Questo filtro è stato sostituito da un filtro [a fetta |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ Estrae una fetta di una stringa. Questo filtro è stato sostituito da un filtro
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Traduce le espressioni in altre lingue. Per rendere disponibile il filtro, è necessario [impostare il traduttore |develop#TranslatorExtension]. Si possono anche usare i [tag per la traduzione |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Traduce le espressioni in altre lingue. Per rendere disponibile il filtro, è ne
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Spogliare i caratteri iniziali e finali, per impostazione predefinita gli spazi bianchi.
 
 ```latte
@@ -675,7 +835,7 @@ Spogliare i caratteri iniziali e finali, per impostazione predefinita gli spazi
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Accorcia una stringa alla lunghezza massima indicata, ma cerca di conservare le parole intere. Se la stringa è troncata, aggiunge un'ellissi alla fine (questo può essere cambiato con il secondo parametro).
 
diff --git a/latte/it/functions.texy b/latte/it/functions.texy
index 987cf7618d..fcab6f3beb 100644
--- a/latte/it/functions.texy
+++ b/latte/it/functions.texy
@@ -9,6 +9,8 @@ Oltre alle comuni funzioni PHP, è possibile utilizzarle anche nei template.
 | `divisibleBy`| [controlla se una variabile è divisibile per un numero |#divisibleBy]
 | `even` | [controlla se il numero dato è pari |#even]
 | `first` | [restituisce il primo elemento di un array o un carattere di una stringa |#first]
+| `group` | [raggruppa i dati secondo vari criteri |#group]
+| `hasBlock` | [rileva l'esistenza di un blocco |#hasBlock]
 | `last` | [restituisce l'ultimo elemento di un array o un carattere di una stringa |#last]
 | `odd` | [controlla se il numero dato è dispari |#odd]
 | `slice` | [estrae una fetta di un array o di una stringa |#slice]
@@ -73,8 +75,8 @@ Verifica se il numero dato è pari.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Restituisce il primo elemento di una matrice o un carattere di una stringa:
 
 ```latte
@@ -85,6 +87,36 @@ Restituisce il primo elemento di una matrice o un carattere di una stringa:
 Vedere anche [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Questa funzione raggruppa i dati in base a diversi criteri.
+
+In questo esempio, le righe della tabella sono raggruppate in base alla colonna `categoryId`. L'output è una matrice di campi in cui la chiave è il valore della colonna `categoryId`. Leggete le [istruzioni dettagliate |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Vedere anche [gruppo di |filters#group] filtri.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Controlla se il blocco con il nome specificato esiste:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Si veda anche il [controllo dell'esistenza del blocco |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Restituisce l'ultimo elemento della matrice o il carattere della stringa:
@@ -106,8 +138,8 @@ Controlla se il numero dato è dispari.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Estrae una fetta di un array o di una stringa.
 
 ```latte
diff --git a/latte/it/recipes.texy b/latte/it/recipes.texy
index 5985254606..70b673c3c4 100644
--- a/latte/it/recipes.texy
+++ b/latte/it/recipes.texy
@@ -9,7 +9,7 @@ Scrivete i modelli in un editor o IDE che supporti Latte. Sarà molto più piace
 
 - NetBeans IDE ha un supporto integrato
 - PhpStorm: installare il [plugin Latte |https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace`
-- VS Code: cercare il plugin "Nette Latte + Neon" in Markerplace
+- Codice VS: cercare markerplace per il plugin [dei modelli |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] o [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Sublime Text 3: in Package Control trovare e installare il pacchetto `Nette` e selezionare Latte in `View > Syntax`
 - nei vecchi editor usare l'evidenziazione Smarty per i file .latte
 
diff --git a/latte/it/safety-first.texy b/latte/it/safety-first.texy
index 6ed5a293af..e70e37a2af 100644
--- a/latte/it/safety-first.texy
+++ b/latte/it/safety-first.texy
@@ -351,7 +351,7 @@ Latte controlla automaticamente se la variabile utilizzata negli attributi `src`
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Scrive:
diff --git a/latte/it/syntax.texy b/latte/it/syntax.texy
index c96747b66d..4678d5ee18 100644
--- a/latte/it/syntax.texy
+++ b/latte/it/syntax.texy
@@ -98,7 +98,7 @@ Stampe:
 Oppure utilizzando il prefisso `tag-` la funzionalità viene applicata solo ai tag HTML:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 A seconda del valore della variabile `$url` verrà stampato:
@@ -155,6 +155,20 @@ O direttamente sul valore (in combinazione con [`{=expr}` | https://latte.nette.
 ```
 
 
+Tag HTML dinamici .[#toc-dynamic-html-tags]
+===========================================
+
+Latte supporta i tag HTML dinamici, utili quando si ha bisogno di flessibilità nei nomi dei tag:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Ad esempio, il codice qui sopra può generare `<h1>Heading</h1>` o `<h2>Heading</h2>` a seconda del valore della variabile `$level`. I tag HTML dinamici in Latte devono sempre essere accoppiati. L'alternativa è il [n:tag |tags#n:tag].
+
+Poiché Latte è un sistema di template sicuro, controlla che il nome del tag risultante sia valido e non contenga valori indesiderati o dannosi. Inoltre, garantisce che il nome del tag finale sia sempre uguale a quello del tag di apertura.
+
+
 Commenti .[#toc-comments]
 =========================
 
diff --git a/latte/it/tags.texy b/latte/it/tags.texy
index 3411ee7656..ab70a24b30 100644
--- a/latte/it/tags.texy
+++ b/latte/it/tags.texy
@@ -16,6 +16,7 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [condizione ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [verifica se c'è stata una modifica |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condizione switch |#switch-case-default]
+| `n:else` | [contenuto alternativo per le condizioni |#n:else]
 
 .[table-latte-tags language-latte]
 |## Cicli
@@ -97,8 +98,8 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte.
 | `{link}` | [stampa un link |application:creating-links#In the Presenter Template]
 | `{plink}` | [stampa un link a un presentatore |application:creating-links#In the Presenter Template]
 | `{control}` | [stampa un componente |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [uno snippet di modello che può essere inviato tramite AJAX |application:ajax#tag-snippet]
-| `{snippetArea}` | snippet busta
+| `{snippet}`... `{/snippet}` | [uno snippet di modello che può essere inviato tramite AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [snippet busta |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [memorizza nella cache una sezione del template |caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte.
 | `{input}` | [stampa un elemento di input del modulo |forms:rendering#label-input]
 | `{inputError}` | [stampa il messaggio di errore per l'elemento di input del modulo |forms:rendering#inputError]
 | `n:name` | [attiva un elemento di input HTML |forms:rendering#n:name]
-| `{formPrint}` | [genera il blueprint del modulo Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [stampa la classe PHP per i dati del modulo |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [rendering parziale del modulo |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [rendere il contenitore del modulo |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Sapete che è possibile aggiungere il prefisso `tag-` a n:attributi? In questo m
 Bello.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Se si scrive la condizione `{if} ... {/if}` sotto forma di un [attributo n: |syntax#n:attributes], si ha la possibilità di specificare un ramo alternativo usando `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+L'attributo `n:else` può essere usato anche insieme a [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], e [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Vedi anche [`{ifset block}` |template-inheritance#checking-block-existence]
 Utilizzare la condizione `{ifset $var}` per determinare se una variabile (o più variabili) esiste e ha un valore non nullo. In realtà è la stessa cosa di `if (isset($var))` in PHP. Come ogni tag di coppia, può essere scritto nella forma [n:attribute |syntax#n:attributes], quindi lo mostriamo in un esempio:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Il contenuto di `{sep}` viene reso se l'iterazione non è l'ultima, quindi è ad
 `{iterateWhile}`
 ----------------
 
-Semplifica il raggruppamento dei dati lineari durante l'iterazione in un ciclo foreach, eseguendo l'iterazione in un ciclo annidato finché la condizione è soddisfatta. [Leggete le istruzioni nel ricettario |cookbook/iteratewhile].
+Semplifica il raggruppamento dei dati lineari durante l'iterazione in un ciclo foreach, iterando in un ciclo annidato finché non viene soddisfatta una condizione. [Leggete le istruzioni dettagliate |cookbook/grouping].
 
 Può anche sostituire elegantemente `{first}` e `{last}` nell'esempio precedente:
 
@@ -489,6 +501,8 @@ Può anche sostituire elegantemente `{first}` e `{last}` nell'esempio precedente
 {/foreach}
 ```
 
+Vedere anche i filtri [batch |filters#batch] e [di gruppo |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Se `$heading === null`, il tag `<h1>` viene stampato senza modifiche. Altrimenti
 <h3 class="main">...</h3>
 ```
 
+Poiché Latte è un sistema di template sicuro, controlla che il nome del nuovo tag sia valido e non contenga valori indesiderati o dannosi.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/it/template-inheritance.texy b/latte/it/template-inheritance.texy
index b7023338f1..3e2123efa0 100644
--- a/latte/it/template-inheritance.texy
+++ b/latte/it/template-inheritance.texy
@@ -132,7 +132,7 @@ Ecco alcuni suggerimenti per lavorare con l'ereditarietà dei layout:
 
 - Se si usa `{layout}` in un modello, deve essere il primo tag del modello in quel modello.
 
-- Il layout può essere [cercato automaticamente |develop#automatic-layout-lookup] (come nei [presentatori |application:templates#search-for-templates]). In questo caso, se il modello non deve avere un layout, lo indicherà con il tag `{layout none}`.
+- Il layout può essere [cercato automaticamente |develop#automatic-layout-lookup] (come nei [presentatori |application:templates#Template Lookup]). In questo caso, se il modello non deve avere un layout, lo indicherà con il tag `{layout none}`.
 
 - Il tag `{layout}` ha l'alias `{extends}`.
 
@@ -396,6 +396,14 @@ Si può usare una variabile o qualsiasi espressione in PHP come nome del blocco.
 {/ifset}
 ```
 
+L'esistenza di blocchi viene restituita anche dalla funzione [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Suggerimenti .[#toc-tips]
 -------------------------
@@ -415,7 +423,7 @@ Ecco alcuni suggerimenti per lavorare con i blocchi:
 Riutilizzo orizzontale `{import}` .{toc: Horizontal Reuse}
 ==========================================================
 
-Il riutilizzo orizzontale è un terzo meccanismo di riusabilità ed ereditarietà di Latte. Permette di caricare blocchi da altri modelli. È simile alla creazione di un file PHP con funzioni di aiuto o un tratto.
+Il riutilizzo orizzontale è il terzo meccanismo di riutilizzo ed ereditarietà di Latte. Permette di caricare blocchi da altri modelli. È simile alla creazione di un file con funzioni di aiuto in PHP e al suo caricamento tramite `require`.
 
 L'ereditarietà dei layout dei modelli è una delle caratteristiche più potenti di Latte, ma è limitata all'ereditarietà semplice: un modello può estendere solo un altro modello. Il riutilizzo orizzontale è un modo per ottenere l'ereditarietà multipla.
 
@@ -447,7 +455,7 @@ Il tag `{import}` deve essere il primo tag del template dopo `{layout}`. Il nome
 
 Si possono usare tutte le dichiarazioni `{import}` che si vogliono in un dato template. Se due template importati definiscono lo stesso blocco, vince il primo. Tuttavia, la massima priorità è data al modello principale, che può sovrascrivere qualsiasi blocco importato.
 
-Tutti i blocchi sovrascritti possono essere inclusi gradualmente inserendoli come [blocco padre |#parent block]:
+Il contenuto dei blocchi sovrascritti può essere conservato inserendo il blocco nello stesso modo di un [blocco padre |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/ja/@left-menu.texy b/latte/ja/@left-menu.texy
index f0733f9e0b..e7e4839e28 100644
--- a/latte/ja/@left-menu.texy
+++ b/latte/ja/@left-menu.texy
@@ -1,24 +1,24 @@
 - [はじめに |Guide]
 - [なぜテンプレートを使うのか? |why-use]
-- コンセプト
+- コンセプト ⚗️
 	- [安全第一 |Safety First]
 	- [テンプレート継承 |Template Inheritance]
 	- [型システム |Type System]
 	- [サンドボックス |Sandbox]
 
-- 設計者向け
+- 設計者向け 🎨
 	- [構文 |Syntax]
 	- [タグ |Tags]
 	- [フィルター |Filters]
 	- [関数 |Functions]
 	- [ヒントとコツ |recipes]
 
-- 開発者向け
+- 開発者向け 🧮
 	- [開発者の ためのプラクティス |develop]
 	- [Latteを拡張する |Extending Latte]
 	- [拡張機能の 作成 |creating-extension]
 
-- [クックブック |cookbook/@home]
+- [クックブック 💡|cookbook/@home]
 	- [Twigからの移行 |cookbook/migration-from-twig]
 	- [... もっと見る |cookbook/@home]
 
diff --git a/latte/ja/cookbook/@home.texy b/latte/ja/cookbook/@home.texy
index 965ad57a73..5729049722 100644
--- a/latte/ja/cookbook/@home.texy
+++ b/latte/ja/cookbook/@home.texy
@@ -4,7 +4,9 @@
 .[perex]
 Latteでよくある作業を実現するためのコード例とレシピを紹介。
 
-- [{iterateWhile}についてあなたがいつも知りたかったことすべて |iteratewhile]
+[- 開発者ガイドライン |/develop]
+[- テンプレート間で変数を渡す |passing-variables]
+[- グループ化について知りたかったことすべて |grouping]
 - [LatteでSQLクエリを書くには? |how-to-write-sql-queries-in-latte]
 - [PHPからの移行 |migration-from-php]
 - [Twigからの移行 |migration-from-twig]
diff --git a/latte/ja/cookbook/grouping.texy b/latte/ja/cookbook/grouping.texy
new file mode 100644
index 0000000000..c555e66466
--- /dev/null
+++ b/latte/ja/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+グループ化について知りたかったことのすべて
+*********************
+
+.[perex]
+テンプレートでデータを扱うとき、特定の条件に従ってデータをグループ化したり、特別に表示したりする必要性にしばしば遭遇します。この目的のために、Latteはいくつかの強力なツールを提供しています。
+
+フィルタとファンクション`|group` は指定された条件に基づいて効率的にデータをグループ化することができます。`|batch` フィルタはデータを一定のバッチに分割することを容易にし、`{iterateWhile}` タグは条件によってより複雑なサイクル制御の可能性を提供します。
+これらのタグはそれぞれデータ操作のための特別なオプションを提供し、ラテのテンプレートで情報をダイナミックかつ構造的に表示するために不可欠なツールとなっています。
+
+
+フィルタと関数`group` .[#toc-filter-and-function-group]
+================================================
+
+アイテムがカテゴリーに分けられたデータベース・テーブル`items` を想像してください:
+
+| id|カテゴリーID|名前
+|------------------
+| 1|アップル
+| 2|1|バナナ
+| 3|2|PHP
+| 4|3|グリーン
+| 5|3|赤
+| 6|3|青
+
+ラテテンプレートを使った単純な全項目リストは次のようになる:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+しかし、アイテムをカテゴリーごとにグループ化したい場合は、各カテゴリーが独自のリストを持つようにアイテムを分割する必要があります。その結果、次のようになる:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+このタスクは、`|group` を使って簡単かつエレガントに解決できる。パラメータとして`categoryId` を指定する。つまり、`$item->categoryId` の値に基づいて、アイテムがより小さな配列に分割されることを意味する(`$item` が配列の場合、次のようになる)。 `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+フィルタはLatteの関数として使うこともできるので、別の構文も用意されている:`{foreach group($items, categoryId) ...}`.
+
+より複雑な条件に従ってアイテムをグループ化したい場合は、filterパラメータに関数を使用できます。たとえば、名前の長さでアイテムをグループ化すると、次のようになります:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+注意すべき点は、`$categoryItems` は通常の配列ではなく、イテレータのように振る舞うオブジェクトであるということです。グループの最初の項目にアクセスするには [`first()` |latte:functions#first]関数を使います。
+
+このようにデータを柔軟にグループ化できるので、`group` はラテのテンプレートでデータを表示するのに非常に便利なツールです。
+
+
+ネストされたループ .[#toc-nested-loops]
+------------------------------
+
+各アイテムのサブカテゴリーを定義する別のカラム`subcategoryId` を持つデータベーステーブルがあるとします。各メインカテゴリを個別のリストで表示し、各サブカテゴリを個別のネストされた `<ul>`リストで表示し、各サブカテゴリーを別のネストされた `<ol>`リストに表示したい:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Nette データベースとの接続 .[#toc-connection-with-nette-database]
+-------------------------------------------------------
+
+Nette Databaseと組み合わせて、データグループ化を効果的に使う方法を説明しよう。最初の例の`items` テーブルを操作しているとします。 テーブルは、`categoryId` カラムを通して、この`categories` テーブルに接続されています:
+
+categoryId | name ||カテゴリーID ||名前
+|------------|------------|
+| 1 | フルーツ
+| 2| 言語
+| 3|色
+
+Nette Database Explorerのコマンド`$items = $db->table('items')` を使って、`items` テーブルからデータをロードする。これらのデータに対する反復の間、`$item->name` や`$item->categoryId` のような属性にアクセスする機会があるだけでなく、`categories` テーブルとの接続のおかげで、`$item->category` を介してその中の関連行にもアクセスすることができます。この接続は、興味深い使い方ができる:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+この場合、`|group` フィルタを使用して、`categoryId` 列だけでなく、接続された行`$item->category` によってグループ化します。これにより、変数キーに指定されたカテゴリの`ActiveRow` が得られ、`{$category->name}` を使ってその名前を直接表示することができる。これは、グループ化によってテンプレートが簡素化され、データの取り扱いが容易になることの実例である。
+
+
+フィルター`|batch` .[#toc-filter-batch]
+==================================
+
+フィルタを使うと、要素のリストをあらかじめ決められた数のグループに分割することができます。このフィルタは、例えば、ページ上でより明瞭に、あるいは視覚的に整理するために、データをいくつかの小さなグループに分けて表示したい場合に最適です。
+
+アイテムのリストがあり、それぞれ最大3つのアイテムを含むリストで表示したいとします。このような場合、`|batch` フィルタの使用は非常に実用的です:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+この例では、リスト`$items` は小さなグループに分割され、各グループ (`$batch`) には最大3つのアイテムが含まれます。各グループは別々の `<ul>`リストに表示されます。
+
+最後のグループには必要な数に達するだけの要素が含まれていない場合、フィルタの2番目のパラメータで、このグループに何を追加するかを定義することができます。これは、不完全な行が無秩序に見えるかもしれない要素を美的に整列させるのに理想的です。
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+タグ`{iterateWhile}` .[#toc-tag-iteratewhile]
+===========================================
+
+`{iterateWhile}` タグを使用して、`|group` フィルタで扱ったのと同じタスクを実演する。この2つのアプローチの主な違いは、`group` が最初にすべての入力データを処理してグループ化するのに対し、`{iterateWhile}` は条件付きサイクルの進行を制御するため、反復が順次発生することです。
+
+まず、iterateWhileを使用して、カテゴリーで表を描画する:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+`{foreach}` がサイクルの外側、すなわち各カテゴリーのリストを描画する部分を示すのに対し、`{iterateWhile}` タグは内側、すなわち個々の項目を示す。
+終了タグの条件は、現在の要素と次の要素が同じカテゴリーに属している限り、繰り返しを続けるというものです(`$iterator->nextValue` は[次の項目 |/tags#$iterator]です)。
+
+この条件が常に満たされていれば、すべての要素が内側のサイクルで描かれることになる:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+結果は次のようになる:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+このようなiterateWhileの使い方は何でしょうか?テーブルが空で要素がない場合、空の `<ul></ul>`は出力されません。
+
+冒頭の`{iterateWhile}` タグで条件を指定すると、動作が変わります。条件(および次の要素への遷移)は、終了時ではなく、内部サイクルの開始時に実行されます。
+したがって、`{iterateWhile}` には常に無条件で入るが、`{iterateWhile $cond}` には`$cond` の条件が満たされたときだけ入る。そして同時に、次の要素が`$item` に書き込まれる。
+
+これは、例えば、各カテゴリーの最初の要素を、次のように異なるようにレンダリングしたい場合に便利です:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+元のコードを修正して、まず最初の項目をレンダリングし、次に内側のサイクル`{iterateWhile}` で同じカテゴリの他の項目をレンダリングするようにします:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+1つのサイクルの中で、複数の内部ループを作成し、ネストさせることもできる。こうすることで、たとえば、サブカテゴリーをグループ化することができる。
+
+テーブルにもう1つのカラム`subcategoryId` 、各カテゴリーがそれぞれ別のカラムにあるとします。 `<ul>`サブカテゴリーを別の `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/ja/cookbook/iteratewhile.texy b/latte/ja/cookbook/iteratewhile.texy
deleted file mode 100644
index 9686a95cd5..0000000000
--- a/latte/ja/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-iterateWhile}について、あなたがいつも知りたかったことすべて。
-*************************************
-
-.[perex]
-`{iterateWhile}` というタグは、foreach サイクルでの様々なトリックに適しています。
-
-次のようなデータベースのテーブルがあり、項目がカテゴリに分けられているとします。
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-もちろん、foreachループのアイテムをリストとして描画するのは簡単です。
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-しかし、各カテゴリを別々のリストで表示したい場合はどうすればよいのだろうか?言い換えれば、foreachサイクルで線形リストからアイテムをグループ化するタスクをどのように解決するかということです。出力はこのようになるはずだ。
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-このタスクをiterateWhileでいかに簡単かつエレガントに解決できるかをお見せします。
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-`{foreach}` がサイクルの外側、つまり各カテゴリのリストの描画を示すのに対して、`{iterateWhile}` タグは内側、つまり個々の項目を示しています。
-終了タグの条件は、現在の要素と次の要素が同じカテゴリに属している限り、繰り返しを続けるというものです(`$iterator->nextValue` は[次のアイテム |/tags#$iterator])。
-
-もし、この条件が常に満たされるなら、すべての要素が内部のサイクルで描かれることになる。
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-結果は次のようになる。
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-このような iterateWhile の使い方にどんな利点があるのでしょうか?このチュートリアルの一番最初に紹介した解決策とどう違うのでしょうか?違いは、テーブルが空で要素を含んでいない場合、レンダリングが空にならないことです。 `<ul></ul>`.
-
-
-`{iterateWhile}` のない場合の解決策 .[#toc-solution-without-iteratewhile]
-----------------------------------------------------------------
-
-もし、同じタスクを完全に基本的な構造のテンプレートシステム、例えばTwigやBlade、あるいは純粋なPHPで解決するとしたら、解決策は次のようになります。
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-しかし、このコードは理解しがたく、直感的ではありません。HTMLタグの開始と終了の間の接続がまったく明確ではありません。間違いがあっても一目瞭然ではありません。しかも、`$prevCatId` のような補助変数を必要とする。
-
-これに対して、`{iterateWhile}` を使った解決策は、すっきりしていて、明確で、補助変数が必要なく、間違いがありません。
-
-
-終了タグの条件  .[#toc-condition-in-the-closing-tag]
----------------------------------------------
-
-開始タグ`{iterateWhile}` で条件を指定すると、動作が変わります。条件 (と次の要素への移動) は内部サイクルの最初で実行され、最後では実行されなくなります。
-したがって、条件なしの`{iterateWhile}` は常に入力されますが、`{iterateWhile $cond}` は条件`$cond` が満たされたときだけ入力されます。同時に、次の要素が`$item` に書き込まれる。
-
-これは,たとえば,各カテゴリーの最初の要素を異なる方法でレンダリングしたいような場合に便利である.
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-元のコードを修正して、最初の項目を描画し、次に同じカテゴリから追加の項目を内部ループで描画することにしましょう`{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-ネストされたループ .[#toc-nested-loops]
-------------------------------
-
-1つのサイクルで複数の内部ループを作成し、さらにそれらを入れ子にすることができる。この方法で、例えば、サブカテゴリーをグループ化することができる。
-
-テーブル`subCatId` に別のカラムがあるとします。各カテゴリが別のカラムにあることに加えて、各サブカテゴリは別のカラムにあります。 `<ul>`にあることに加え、各サブカテゴリーは別々の `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-フィルタ|バッチ .[#toc-filter-batch]
------------------------------
-
-線形項目のグループ化は、フィルタ`batch` によっても提供され、一定の要素数を持つバッチに分けられます。
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-これは,次のように iterateWhile で置き換えることができます.
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/ja/cookbook/passing-variables.texy b/latte/ja/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..3defa3a278
--- /dev/null
+++ b/latte/ja/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+テンプレート間での変数の受け渡し
+****************
+
+このガイドでは、`{include}` 、`{import}` 、`{embed}` 、`{layout}` 、`{sandbox}` などのさまざまなタグを使って、Latte のテンプレート間で変数を受け渡す方法を説明します。また、`{block}` や`{define}` タグで変数を扱う方法や、`{parameters}` タグの目的についても説明します。
+
+
+変数の種類 .[#toc-types-of-variables]
+--------------------------------
+ラテの変数は、その定義方法と定義場所によって3つのカテゴリーに分けられる:
+
+**入力変数**は、例えばPHPスクリプトから、あるいは`{include}` のようなタグを使用して、外部からテンプレートに渡されるものです。
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**周囲変数** は、特定のタグの位置に存在する変数です。これらの変数には、すべての入力変数と、`{var}` 、`{default}` のようなタグを使用して作成された変数、または`{foreach}` のようなループ内の変数が含まれます。
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**明示変数** は、タグ内で直接指定され、ターゲット・テンプレートに送信される変数です。
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+`{block}` タグは、継承したテンプレートでカスタマイズや拡張が可能な、再利用可能なコード・ブロックを定義するために使用します。ブロックの前に定義された変数を囲む変数はブロックの内部で使用できますが、変数への変更はそのブロックの内部でのみ反映されます。
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+`{define}` タグは、`{include}` を使用して呼び出されたときにのみレンダリングされるブロックを作成するために使用します。これらのブロックの内部で使用できる変数は、定義でパラメータが指定されて いるかどうかによって異なります。パラメータが指定されている場合は、それらのパラメータにのみアクセスできます。パラメータが指定されていない場合は、ブロックが定義されているテンプレートのすべての入力変数にアクセスできます。
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+`{parameters}` タグは、テンプレートの冒頭で期待される入力変数を明示的に宣言するために使用します。こうすることで、期待される変数とそのデータ型を簡単に文書化することができます。デフォルト値を定義することも可能です。
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+`{include file}` タグは、テンプレート全体を挿入するために使用します。このテンプレートには、タグが使用されるテンプレートの入力変数と、明示的に定義された変数の両方が渡されます。ただし、ターゲット・テンプレートは、`{parameters}` を使用してスコープを制限することができます。
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+同じテンプレートで定義されたブロックを挿入する場合、周囲にある変数と明示的に定義された変 数はすべてそのブロックに渡されます:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+この例では、`$name` と`$age` 変数が`blockName` ブロックに渡されます。この例では、`{include parent}` と 変数が ブロックに渡されます。
+
+他のテンプレートからブロックを挿入する場合、渡されるのは入力変数と明示的に定義された変数のみです。周囲にある変数は、自動的には利用できません。
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` または`{extends}`
+-------------------------
+これらのタグは、子テンプレートの入力変数と、ブロックの前のコードで作成された変数が渡されるレイアウトを定義します:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+テンプレート`layout.latte` :
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+`{embed}` タグは`{include}` タグと似ていますが、テンプレートにブロックを埋め込むことができます。`{include}` とは異なり、明示的に宣言された変数のみが渡されます:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+この例では、`menu.latte` テンプレートは`$items` 変数にのみアクセスできます。
+
+逆に、`{embed}` 内のブロックは、周囲のすべての変数にアクセスできる:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+`{import}` タグは、他のテンプレートからブロックを読み込むために使用します。入力変数と明示的に宣言された変数の両方が、インポートされたブロックに渡されます。
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+`{sandbox}` タグは、安全な処理のためにテンプレートを分離します。変数は明示的に渡されます。
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/ja/creating-extension.texy b/latte/ja/creating-extension.texy
index 40c4a14cec..b930a07ec2 100644
--- a/latte/ja/creating-extension.texy
+++ b/latte/ja/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// a parsing function that just creates a node for now
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+補助ノード.[#toc-auxiliarynode]
+--------------------------
+
+Latte用の新しいタグを作成する場合は、ASTツリーでそれを表現する専用のノードクラスを作成することをお勧めします(上記の例の`ForeachNode` クラスを参照)。このクラスでは、`print()` メソッドのボディと、`getIterator()` メソッドによってアクセス可能になったノードのリストをコンストラクタのパラメータとして渡すことができます:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 コンパイラのパス .[#toc-compiler-passes]
 ================================
 
diff --git a/latte/ja/develop.texy b/latte/ja/develop.texy
index 6ce5a51c8d..27fab15e1c 100644
--- a/latte/ja/develop.texy
+++ b/latte/ja/develop.texy
@@ -163,7 +163,24 @@ try {
 	// PHPのラテ・エラーとコンパイル・エラーをキャッチする
 
 	echo 'Error: ' . $e->getMessage();
-}```
+}
+```
+
+
+ロケール .[#toc-locale]{data-version:3.0.18}
+========================================
+
+Latteではロケールを設定することができます。ロケールは数値、日付、ソートのフォーマットに影響します。ロケールは`setLocale()` 。ロケール識別子は IETF の言語タグ標準に従い、PHP の`intl` 拡張モジュールを使用します。これは、言語コードと場合によっては国コードで構成されます。 たとえば、`en_US` は米国の英語、`de_DE` はドイツのドイツ語といった具合です。
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+ロケールの設定は、フィルタ[localDate |filters#localDate]、[sort |filters#sort]、[number |filters#number] および[bytes |filters#bytes] に影響します。
+
+.[note]
+PHP の`intl` 拡張モジュールが必要です。Latte での設定は、PHP のグローバルロケール設定には影響しません。
 
 
 ストリクトモード .[#toc-strict-mode]{data-version:3.0.8}
@@ -271,18 +288,27 @@ vendor/bin/latte-lint <path>
 #!/usr/bin/env php
 <?php
 
-// enter the actual path to the autoload.php file
+// autoload.phpファイルへの実際のパスを入力します。
+ ここに個々の拡張子を追加します
+
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// ここに個々のエクステンションを追加する
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+//$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
-exit($ok ? 0 : 1);
-```
+exit($ok ? 0 : 1);```
+
+あるいは、独自の`Latte\Engine` オブジェクトを Linter に渡すこともできます:
+
+```php
+$latte = new Latte\Engine;
+// ここでは、$latteオブジェクトを設定します。
+
+$linter = new Latte\Tools\Linter(engine: $latte);```
 
 
 文字列からテンプレートを読み込む .[#toc-loading-templates-from-a-string]
diff --git a/latte/ja/extending-latte.texy b/latte/ja/extending-latte.texy
index 89d74f20ab..ac08174855 100644
--- a/latte/ja/extending-latte.texy
+++ b/latte/ja/extending-latte.texy
@@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 
 もちろん、フィルタを表す関数は任意の数のパラメータを受け取ることができ、可変長のパラメータもサポートされています。
 
+フィルターがHTMLの文字列を返す場合、ラテが自動的に(つまり二重に)エスケープしないようにマークすることができます。これにより、テンプレートで`|noescape` を指定する必要がなくなります。
+最も簡単な方法は、`Latte\Runtime\Html` オブジェクトで文字列をラップすることです。もう一つの方法は、[コンテキストフィルタ |#Contextual Filters]です。
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+この場合、フィルターはデータの正しいエスケープを保証しなければならない。
+
 
 クラスを使ったフィルタ .[#toc-filters-using-the-class]
 -------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// change content-type to HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/ja/filters.texy b/latte/ja/filters.texy
index d2c6eb78c2..d34cbb3761 100644
--- a/latte/ja/filters.texy
+++ b/latte/ja/filters.texy
@@ -11,14 +11,16 @@
 |`bytes` | [サイズをバイト単位でフォーマットする|#bytes]
 |`clamp` | [値を範囲にクランプする|#clamp]
 |`dataStream` | [データ URI プロトコル変換 |#datastream]
-|`date` | [日付の書式設定|#date]
+|`date` | [日付と時刻をフォーマットする |#date]
 |`explode` | [与えられたデリミターで文字列を分割する|#explode]
 |`first` | [配列の最初の要素または文字列の文字を返します |#first]
+|`group` | [様々な基準に従ってデータをグループ 化する|#group]
 |`implode` | [配列と文字列を結合します|#implode]
 |`indent` | テキストを[左からタブの数だけインデントする|#indent]
 |`join` | [配列と 文字列を結合します|#implode]
 |`last` | 配列の[最後の要素または文字列の文字を返します|#last]
 |`length` | [文字列または配列の長さを返す|#length]
+|`localDate` | [日付と時刻をロケールにしたがってフォーマットする。 |#localDate]
 |`number` | [数値をフォーマットする|#number]
 |`padLeft` | [左から指定された長さまで文字列を伸ばします|#padLeft]
 |`padRight` | 右[から指定 された長さまで文字列を補完する|#padRight]
@@ -118,8 +120,8 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 =====================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 線形データの表形式でのリストアップを簡略化するフィルタです。これは、指定された数の項目を持つ配列の配列を返します。第2パラメータを指定した場合、これは最終行の欠落した項目を埋めるために使用されます。
 
 ```latte
@@ -152,6 +154,8 @@ batch(int length, mixed item): array .[filter]
 </table>
 ```
 
+[group |#group]および[iterateWhile |tags#iterateWhile]タグも参照のこと。
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ breakLines .[filter]
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-バイト単位のサイズを人間が読みやすい形に整形する。
+bytes(int $precision=2) .[filter]
+---------------------------------
+バイト単位のサイズを人間が読める形に整形する。[ロケールが |develop#locale]設定されている場合は、対応する10進数と1000のセパレータが使用される。
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ bytes(int precision = 2) .[filter]
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 数値を指定された精度で丸める。
 
 ```latte
@@ -203,8 +207,8 @@ URLのサニタイズ処理を行います。変数が Web URL (つまり HTTP/H
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 印刷します。
@@ -217,8 +221,8 @@ URLのサニタイズ処理を行います。変数が Web URL (つまり HTTP/H
 [nocheckも |#nocheck]参照してください。
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 minとmaxの包括的な範囲にクランプされた値を返す。
 
 ```latte
@@ -228,14 +232,14 @@ minとmaxの包括的な範囲にクランプされた値を返す。
 [関数としても |functions#clamp]存在する。
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 コンテンツをデータURIスキームに変換します。外部ファイルへのリンクを必要とせず、HTMLやCSSに画像を挿入するのに利用できます。
 
 変数`$img = Image::fromFile('obrazek.gif')` に画像を入れておくとします。
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 例えば印刷します。
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 PHP 拡張機能が必要です`fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-[php:strftime] あるいは[php:date] の PHP 関数のオプションを使用して、指定した書式で日付を返します。フィルタは、UNIXタイムスタンプ、文字列、あるいは`DateTime` 型のオブジェクトとして日付を取得します。
+date(string $format) .[filter]
+------------------------------
+PHP の関数[php:date] で使われるマスクに従って、日付と時刻をフォーマットします。このフィルタは、UNIX タイムスタンプ形式、文字列、あるいは`DateTimeInterface` オブジェクトとして日付を受け取ります。
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+[localDateも |#localDate]参照のこと。
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ URLのパラメータとして使用される変数をエスケープします
 [クエリも |#query]参照。
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 文字列を指定された区切り文字で分割し、文字列の配列を返します。`split` のエイリアス .
 
 ```latte
@@ -306,8 +311,8 @@ first .[filter]
 [last |#last],[randomも |#random]参照のこと。
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 与えられた精度で数値を丸める。
 
 ```latte
@@ -330,8 +335,27 @@ firstUpper .[filter]
 [capitalize |#capitalize],[lower |#lower],[upper |#upper] も参照ください。
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+フィルタは、異なる基準に従ってデータをグループ化します。
+
+この例では、テーブルの行はカラム`categoryId` によってグループ化されています。出力は、列`categoryId` の値をキーとする配列の配列です。[詳細な |cookbook/grouping]説明をお読みください。
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+[バッチ |#batch]、[group |functions#group]関数、[iterateWhile |tags#iterateWhile]タグも参照してください。
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 配列中の文字列を連結した文字列を返します。`join` のエイリアス.
 
 ```latte
@@ -346,8 +370,8 @@ implode(string glue = '') .[filter]
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 テキストを左から、オプションの第2引数で指定した数のタブまたは他の文字でインデントします。空白行はインデントされません。
 
 ```latte
@@ -396,6 +420,68 @@ length .[filter]
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+[ロケールにしたがって |develop#locale]日付と時刻をフォーマットし、異なる言語や地域間で時刻データの一貫したローカライズされた表示を保証します。このフィルタは、UNIXタイムスタンプ、文字列、`DateTimeInterface` オブジェクトとして日付を受け付けます。
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+このフィルターをパラメーターなしで使用すると、後で説明するように、長い書式レベルの日付が出力される。
+
+**a) フォーマットの使用**
+
+`format` パラメーターはどの時間要素を表示するかを指定します。これは文字コードを使用し、繰り返しの数が出力の幅に影響します:
+
+| 年|`y` /`yy` /`yyyy` |`2024` / `24` / `2024`
+| 月|`M` /`MM` /`MMM` /`MMMM` | `8` / `08` / `8月` / `8月`
+| 日| `d` /`dd` /`E` /`EEEE` |`1` /`01` /`Sun` / `Sunday`
+| 時間|`j` /`H` /`h` |希望|24時間|12時間
+| 分|`m` /`mm` |`5` /`05` <small>(秒と組み合わせる場合は2桁)</small>
+| 秒 |`s` /`ss` |`8` /`08` <small>(分と組み合わせた場合は2桁)</small>
+
+構成要素の順序はロケールの規約に従って表示されるため、フォーマット内のコードの順序は問題ではない。したがって、書式はロケールに依存しない。たとえば、`en_US` ロケールでは`yyyyMMMMd` という書式は`April 15, 2024` を出力しますが、`cs_CZ` ロケールでは`15. dubna 2024` を出力します:
+
+| locale:  | ja-JP | en_US
+|---
+| `format: 'dMy'` | 2024/8/10 | 8/10/2024
+| `format: 'yM'` | 2024/8 | 8/2024
+| `format: 'yyyyMMMM'` | 2024年8月 | August 2024
+| `format: 'MMMM'` | 8月 | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 午後5:54 | 5:54 PM
+
+
+**b) プリセットスタイルの使用**
+
+`date` と`time` パラメータは、日付と時刻表示の詳細レベルを決定します。いくつかのレベルから選択できます:`full` `long`,`medium`,`short` 。日付のみ、時刻のみ、または両方を表示することができます:
+
+| locale:  | ja-JP | en_US
+|---
+| `date: short` | 1978/01/23 | 1/23/78
+| `date: medium` | 1978/01/23 | Jan 23, 1978
+| `date: long` | 1978年1月23日 | January 23, 1978
+| `date: full` | 1978年1月23日月曜日 | Monday, January 23, 1978
+| `time: short` | 8:30 | 8:30 AM
+| `time: medium` | 8:30:59 | 8:30:59 AM
+| `time: long` | 8:30:59 GMT+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 1978/01/23 8:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 1978/01/23 8:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 1978年1月23日 8:30 | January 23, 1978 at 8:30 AM
+
+日付には接頭辞`relative-` (例:`relative-short` )を使うこともでき、現在に近い日付の場合は`yesterday` 、`today` 、`tomorrow` と表示される。それ以外の場合は標準的な方法で表示される。
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+[日付も |#date]参照。
+
+
 lower .[filter]
 ---------------
 値を小文字に変換します。PHP 拡張モジュール`mbstring` が必要です。
@@ -416,8 +502,8 @@ nocheck .[filter]
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 印刷物
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 `noescape` フィルタを誤用すると、XSS 脆弱性につながる可能性があります!自分が何をしているのか、そして印刷する文字列が信頼できるソースから来たものであるという **絶対** の確信がない限り、決してこれを使わないでください。
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-数値を小数点以下の桁数で表示します。また、小数点、桁区切りの文字も指定できます。
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+指定した小数点以下の桁数で数値をフォーマットする。[ロケールが |develop#locale]設定されている場合は、対応する小数点以下の桁区切り文字が使用される。
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[fil
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+`format` パラメータを使用すると、ニーズに合わせて数字の外観を正確に定義することができる。これには[ロケールが |develop#locale]必要である。この書式はいくつかの特殊文字で構成されており、その完全な説明は"DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patternsドキュメントにあります:
+
+-<c id=6/> 必須桁。ゼロであっても常に表示される。
+-`#` オプションの桁。数字がその位置に数字を持つ場合のみ表示される。
+-`@` 有意桁。有効桁数を指定して数値を表示するのに役立ちます。
+-`.` 小数点の区切り位置を示すマーク(ロケールによってカンマまたはドット)。
+-`,` 数桁のグループ(通常は数千)を区切るために使用します。
+-`%` 数値に100を掛け、パーセント記号を加える。
+
+いくつかの例を見てみよう。最初の例では小数点以下2桁は必須であり、2番目の例では任意である。3つ目の例では両脇にゼロを含むパディングが表示され、4つ目の例では既存の桁のみが表示されます:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+有効数字は、小数点以下の桁数に関係なく、何桁表示するかを決定し、必要であれば四捨五入する:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+数値をパーセント表示する簡単な方法。数値を100倍し、`%` の記号を加える:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+正の数と負の数について、`;` 文字で区切った異なる書式を定義することができる。こうすることで、例えば正の数を`+` 記号で表示することができる:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+数字の実際の見た目は、ロケールの設定によって異なる可能性があることを覚えておいてください。例えば、ある国では小数点以下の区切り文字としてドットの代わりにカンマが使われます。このフィルターは自動的にこれを考慮しますので、心配する必要はありません。
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 指定された長さの文字列を、左から別の文字列で埋め尽くします。
 
@@ -472,7 +606,7 @@ padLeft(int length, string pad = ' ') .[filter]
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 ある文字列を右から別の文字列で一定の長さになるように詰めます。
 
@@ -514,8 +648,8 @@ random .[filter]
 [first |#first],[last |#last] も参照してください。
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 文字列をx回繰り返す。
 
 ```latte
@@ -523,7 +657,7 @@ repeat(int count) .[filter]
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 検索文字列を置換文字列で置き換えます。
 
@@ -538,7 +672,7 @@ replace(string|array search, string replace = '') .[filter]
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 正規表現にしたがって、すべての出現箇所を置き換えます。
 
@@ -559,8 +693,8 @@ reverse .[filter]
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 指定された精度で数値を丸めます。
 
 ```latte
@@ -573,7 +707,7 @@ round(int precision = 0) .[filter]
 [ceil |#ceil],[floorも |#floor]参照のこと。
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 配列または文字列のスライスを抽出します。
 
@@ -591,9 +725,9 @@ length が正の値であれば,シーケンスはその要素数までとな
 Filter は、デフォルトで整数配列のキーを並べ替え、リセットします。この挙動は、preserveKeys を true に設定することで変更可能です。文字列のキーは、このパラメータに関係なく、常に保存されます。
 
 
-sort  .[filter]
----------------
-配列をソートし、インデックスの関連付けを維持するフィルタです。
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+フィルタは、配列やイテレータの要素を連想キーを保持したままソートします。[ロケールが |develop#locale]設定されている場合は、独自の比較関数が指定されていない限り その規則に従います。
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ sort  .[filter]
 {/foreach}
 ```
 
-パラメータとして、独自の比較関数を渡すことができます。
+ソートにはカスタム比較関数を指定することができる(例では最大から最小への逆順ソートを示している):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+`|sort` フィルタでは、要素をキーでソートすることもできます:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+テーブルを特定のカラムでソートする必要がある場合は、`by` パラメータを使用できます。この例の値`'name'` は、`$row->name` または `$row['name']`でソートされることを指定します。`$row` が配列かオブジェクトかによります:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+また、ソートする値を決定するコールバック関数を定義することもできます:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+`byKey` パラメータも同様に使用できます。
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ HTMLをプレーンテキストに変換する。つまり、HTMLタグを削除
 変換後のプレーンテキストには、当然ながらHTMLタグを表す文字が含まれます。例えば、`'&lt;p&gt;'|stripHtml` は、次のように変換されます。 `<p>`.セキュリティ上の脆弱性があるため、結果のテキストを`|noescape` で出力することは絶対に避けてください。
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 文字列のスライスを抽出する。このフィルタは、[スライス |#slice]フィルタに置き換えられました。
 
 ```latte
@@ -655,8 +815,8 @@ substr(int offset, int length = null) .[filter]
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 式を他の言語に翻訳します。このフィルタを利用できるようにするには、[トランスレータを |develop#TranslatorExtension]設定する必要があります。また、[翻訳用のタグを |tags#Translation]使用することもできます。
 
 ```latte
@@ -665,8 +825,8 @@ translate(string message, ...args) .[filter]
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 先頭と末尾の文字を除去します。デフォルトは空白文字です。
 
 ```latte
@@ -675,7 +835,7 @@ trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 文字列を与えられた最大の長さまで短縮するが、単語全体を保存しようとする。文字列が切り詰められた場合、最後に省略記号を付加します (これは第2引数で変更可能です)。
 
diff --git a/latte/ja/functions.texy b/latte/ja/functions.texy
index 6adc243ba1..075b624a34 100644
--- a/latte/ja/functions.texy
+++ b/latte/ja/functions.texy
@@ -9,6 +9,8 @@ PHPの一般的な関数に加え、テンプレートでも使用すること
 |`divisibleBy`|[ある変数がある数値で割り切れるかどうかをチェックします|#divisibleBy]
 |`even` |[与えられた数値が偶数かどうかをチェックします|#even]
 |`first` | [配列の最初の要素または文字列の文字を返します|#first]
+|`group` | [様々な基準に従ってデータをグループ 化する|#group]
+|`hasBlock` |[ブロックの存在を検出する |#hasBlock]
 |`last` | [配列の最後の要素、または文字列の文字を返す|#last]
 |`odd` | [与えられた数が奇数かどうかをチェックする|#odd]
 |`slice`  | [配列または文字列のスライスを抽出します|#slice]
@@ -73,8 +75,8 @@ even(int $value): bool .[method]
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 配列の最初の要素、または文字列の1文字を返します。
 
 ```latte
@@ -85,6 +87,36 @@ first(string|array $value): mixed .[method]
 [last |#last],[filter first |filters#first] も参照してください。
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+この関数は、異なる基準に従ってデータをグループ化します。
+
+この例では、テーブルの行が列`categoryId` によってグループ化されています。出力は、列`categoryId` の値をキーとするフィールドの配列です。[詳細な |cookbook/grouping]説明をお読みください。
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+filter[groupも |filters#group]参照。
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+指定された名前のブロックが存在するかどうかをチェックする:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+[ブロック存在チェックも |template-inheritance#Checking Block Existence]参照のこと。
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 配列の最後の要素または文字列の文字を返します。
@@ -106,8 +138,8 @@ odd(int $value): bool .[method]
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 配列または文字列のスライスを抽出します。
 
 ```latte
diff --git a/latte/ja/recipes.texy b/latte/ja/recipes.texy
index 56ba9e0068..6d64bc9d3e 100644
--- a/latte/ja/recipes.texy
+++ b/latte/ja/recipes.texy
@@ -9,7 +9,7 @@ Latteに対応したエディタやIDEでテンプレートを書きましょう
 
 - NetBeans IDEはサポートが組み込まれています
 - PhpStorm:[Latteプラグ |https://plugins.jetbrains.com/plugin/7457-latte]インをインストールする`Settings > Plugins > Marketplace`
-- VS Code:マーカープレイスで「Nette Latte + Neon」プラグインを探す
+- VSコード:[Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte]または[Nette Latteテンプレートプラグインの |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]markerplace検索
 - Sublime Text 3: パッケージコントロールで`Nette` パッケージを検索してインストールし、Latteを選択します。`View > Syntax`
 - 古いエディタでは、.latte ファイルに Smarty ハイライトを使用します。
 
diff --git a/latte/ja/safety-first.texy b/latte/ja/safety-first.texy
index 8af99cf01d..f5d16e3692 100644
--- a/latte/ja/safety-first.texy
+++ b/latte/ja/safety-first.texy
@@ -351,7 +351,7 @@ Latte は`src` または`href` 属性で使用されている変数に Web URL (
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 書き込みを行います。
diff --git a/latte/ja/syntax.texy b/latte/ja/syntax.texy
index ff6904aeaa..f1bf39d6ce 100644
--- a/latte/ja/syntax.texy
+++ b/latte/ja/syntax.texy
@@ -98,7 +98,7 @@ n:属性 .[#toc-n-attributes]
 また、`tag-` という接頭辞をつけると、HTML タグにのみ機能が適用されます。
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 変数`$url` の値によって、このように表示されます。
@@ -155,6 +155,20 @@ Latteでは、パイプ記号を使った記法でフィルタを呼び出すこ
 ```
 
 
+ダイナミックHTMLタグ .[#toc-dynamic-html-tags]
+======================================
+
+Latteは動的HTMLタグをサポートしており、タグ名に柔軟性が必要な場合に便利です:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+例えば、上記のコードでは `<h1>Heading</h1>`または `<h2>Heading</h2>``$level`を生成することができる。LatteのダイナミックHTMLタグは常にペアでなければなりません。その代わりとなるのが[n:tag |tags#n:tag]です。
+
+Latteは安全なテンプレートシステムであるため、生成されるタグ名が有効で、不要な値や悪意のある値を含まないことをチェックします。また、終了タグ名が常に開始タグ名と同じであることを保証します。
+
+
 コメント .[#toc-comments]
 =====================
 
diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy
index c543dd89bc..3431742402 100644
--- a/latte/ja/tags.texy
+++ b/latte/ja/tags.texy
@@ -16,6 +16,7 @@ Latte内蔵の全タグの概要と説明。
 |`{ifset}`...`{elseifset}`...`{/ifset}` |[条件 ifset |#ifset-elseifset]
 |`{ifchanged}`...`{/ifchanged}` |[変化があったかどうかのテスト|#ifchanged]
 |`{switch}` `{case}` `{default}` `{/switch}` |[条件スイッチ |#switch-case-default]
+|`n:else` |[コンディションの代替コンテンツ |#n:else]
 
 .[table-latte-tags language-latte]
 |## ループ
@@ -97,8 +98,8 @@ Latte内蔵の全タグの概要と説明。
 |`{link}` |[リンクを表示する|application:en:creating-links#In the Presenter Template]
 |`{plink}` |[プレゼンターへのリンクを表示する|application:en:creating-links#In the Presenter Template]
 |`{control}` |[コンポーネントを表示します|application:en:components#Rendering]
-|`{snippet}`...`{/snippet}` |[AJAXで送信可能なテンプレートスニペット |application:en:ajax#tag-snippet]
-|`{snippetArea}` | スニペットの封筒
+|`{snippet}`...`{/snippet}` |[AJAXで送信可能なテンプレートスニペット |application:en:ajax#snippets-in-latte]
+|`{snippetArea}` | [スニペットの封筒 |application:en:ajax#snippet-areas]
 |`{cache}`...`{/cache}` |[テンプレートセクションをキャッシュする|caching:en#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Latte内蔵の全タグの概要と説明。
 |`{input}` |[フォーム入力要素を表示します。|forms:en:rendering#label-input]
 |`{inputError}` | [フォーム入力要素のエラーメッセージを表示します。|forms:en:rendering#inputError]
 |`n:name` |[HTML入力要素をアクティブにする|forms:en:rendering#n:name]
-|`{formPrint}` |[ラテ型フォームの青写真を生成する|forms:en:rendering#formPrint]
-|`{formPrintClass}` |[フォームデータのための PHP クラスを表示する|forms:en:in-presenter#mapping-to-classes]
-|`{formContext}`...`{/formContext}` |[フォームの部分的なレンダリング |forms:en:rendering#special-cases]
 |`{formContainer}`...`{/formContainer}` |[フォームコンテナのレンダリング |forms:en:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ n:attributesに接頭辞`tag-` を付けることができることをご存知
 いいですね。
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+ の条件を`{if} ... {/if}` [n:属性の |syntax#n:attributes]形で記述した場合、 を使って別の分岐を指定するオプションがある:
+
+
+
+ 。`n:else````latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+``` `n:else` [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]および [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ n:attributesに接頭辞`tag-` を付けることができることをご存知
 変数(あるいは複数の変数)が存在し、かつ非 null 値であるかどうかを調べるには、`{ifset $var}` 条件を使用します。これは、実際にはPHPの`if (isset($var))` と同じです。他のペアタグと同様に、[n:attributeの |syntax#n:attributes]形式で書くことができますので、例で紹介しましょう。
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ n:attributeの前に`inner-` というプレフィックスを付けることが
 `{iterateWhile}`
 ----------------
 
-条件を満たす限りネストしたループで反復処理を行うことで、foreachループでの反復処理中の線形データのグループ化を簡略化します。[クックブックの |cookbook/iteratewhile]説明をお読みください。
+条件が満たされるまでネストされたループで反復することにより、foreachループでの反復中に線形データのグループ化を簡素化する。[詳しい |cookbook/grouping]説明を読む。
 
 また、上の例の`{first}` と`{last}` をエレガントに置き換えることができます。
 
@@ -489,6 +501,8 @@ n:attributeの前に`inner-` というプレフィックスを付けることが
 {/foreach}
 ```
 
+[バッチ |filters#batch]フィルター、[グループ |filters#group]フィルターも参照のこと。
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ n:タグ .[#toc-n-tag]
 <h3 class="main">...</h3>
 ```
 
+Latteは安全なテンプレートシステムなので、新しいタグ名が有効で、不要な値や悪意のある値が含まれていないことをチェックします。
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/ja/template-inheritance.texy b/latte/ja/template-inheritance.texy
index cbdf021eeb..026d023a13 100644
--- a/latte/ja/template-inheritance.texy
+++ b/latte/ja/template-inheritance.texy
@@ -132,7 +132,7 @@ Latteのテンプレート継承のコンセプトは、PHPのクラス継承に
 
 - テンプレート内で`{layout}` を使用する場合、そのテンプレート内の最初のテンプレートタグでなければなりません。
 
-- レイアウトは[自動的に検索 |develop#automatic-layout-lookup]することができます([プレゼンターの |application:en:templates#search-for-templates]ように)。この場合、テンプレートがレイアウトを持つべきではない場合は、`{layout none}` タグでその旨を表示します。
+- レイアウトは[自動的に検索 |develop#automatic-layout-lookup]することができます([プレゼンターの |application:en:templates#Template Lookup]ように)。この場合、テンプレートがレイアウトを持つべきではない場合は、`{layout none}` タグでその旨を表示します。
 
 - タグ`{layout}` はエイリアス`{extends}` を持ちます。
 
@@ -396,6 +396,14 @@ Hi, I am Mary.
 {/ifset}
 ```
 
+ブロックの存在は、関数 [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 ヒント .[#toc-tips]
 ----------------
@@ -415,7 +423,7 @@ Hi, I am Mary.
 水平方向の再利用`{import}` .{toc: Horizontal Reuse}
 ===========================================
 
-水平方向の再利用はLatteの3つ目の再利用性・継承の仕組みです。他のテンプレートからブロックを読み込むことができるようになります。ヘルパー関数やtraitでPHPファイルを作成するのと同じようなものです。
+水平方向の再利用は、Latteにおける再利用と継承の3番目のメカニズムです。他のテンプレートからブロックを読み込むことができます。PHPでヘルパー関数を含むファイルを作成し、`require` を使って読み込むのと似ています。
 
 テンプレートレイアウトの継承はLatteの最も強力な機能の一つですが、単純な継承に限られています。水平方向の再利用は、複数の継承を実現する方法です。
 
@@ -447,7 +455,7 @@ Hi, I am Mary.
 
 `{import}` ステートメントは、任意のテンプレートで好きなだけ使用することができます。インポートされた2つのテンプレートが同じブロックを定義している場合、先に定義されたものが優先されます。ただし、メイン・テンプレートが最も優先され、インポートされたブロックを上書きすることができます。
 
-上書きされたブロックはすべて、[親ブロックとして |#parent block]挿入することで、徐々に含めることができます。
+上書きされたブロックの内容は、[親ブロックと |#parent block]同じようにブロックを挿入することで保持できる:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/pl/@left-menu.texy b/latte/pl/@left-menu.texy
index c6d3b03a80..b7a4ae5c6d 100644
--- a/latte/pl/@left-menu.texy
+++ b/latte/pl/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Zaczynając od Latte |guide]
 - [Dlaczego warto używać szablonów? |why-use]
-- Koncepcje
+- Koncepcje ⚗️
 	- [Bezpieczeństwo przede wszystkim |safety-first]
 	- [Dziedziczenie szablonów |Template Inheritance]
 	- [System typu |type-system]
 	- [Piaskownica |Sandbox]
 
-- Dla projektantów
+- Dla projektantów 🎨
 	- [Składnia |syntax]
 	- [Tagi |tags]
 	- [Filtry |filters]
 	- [Funkcje |functions]
 	- [Porady i wskazówki |recipes]
 
-- Dla deweloperów
+- Dla deweloperów 🧮
 	- [Praktyki deweloperskie |develop]
 	- [Expanding Latte |extending-latte]
 	- [Tworzenie rozszerzenia |creating-extension]
 
-- [Samouczki i procedury |cookbook/@home]
+- [Samouczki i procedury 💡|cookbook/@home]
 	- [Migracja z Twig |cookbook/migration-from-twig]
 	- [... więcej |cookbook/@home]
 
diff --git a/latte/pl/cookbook/@home.texy b/latte/pl/cookbook/@home.texy
index 2f49c82fcc..8603948ab9 100644
--- a/latte/pl/cookbook/@home.texy
+++ b/latte/pl/cookbook/@home.texy
@@ -4,7 +4,9 @@ Instrukcje i procedury
 .[perex]
 Przykładowe kody i przepisy na wykonanie typowych zadań z Latte.
 
-- [Wszystko, co kiedykolwiek chciałeś wiedzieć o {iterateWhile} |iteratewhile].
+- [Wytyczne dla deweloperów |/develop]
+- [Przekazywanie zmiennych między szablonami |passing-variables]
+- [Wszystko, co zawsze chciałeś wiedzieć o grupowaniu |grouping]
 - [Jak pisać zapytania SQL w Latte? |how-to-write-sql-queries-in-latte]
 - [Migracja z PHP |migration-from-php]
 - [Migracja z Twig |migration-from-twig]
diff --git a/latte/pl/cookbook/grouping.texy b/latte/pl/cookbook/grouping.texy
new file mode 100644
index 0000000000..e4ebfa59e4
--- /dev/null
+++ b/latte/pl/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Wszystko, co zawsze chciałeś wiedzieć o grupowaniu
+**************************************************
+
+.[perex]
+Podczas pracy z danymi w szablonach często pojawia się potrzeba ich grupowania lub wyświetlania według określonych kryteriów. W tym celu Latte oferuje kilka zaawansowanych narzędzi.
+
+Filtr i funkcja `|group` pozwalają na efektywne grupowanie danych w oparciu o określone kryteria, podczas gdy filtr `|batch` ułatwia dzielenie danych na stałe partie, a tag `{iterateWhile}` zapewnia możliwość bardziej złożonej kontroli cyklu z warunkami.
+Każdy z tych tagów oferuje określone opcje pracy z danymi, co czyni je niezbędnymi narzędziami do dynamicznego i uporządkowanego wyświetlania informacji w szablonach Latte.
+
+
+Filtr i funkcja `group` .[#toc-filter-and-function-group]
+=========================================================
+
+Wyobraźmy sobie tabelę bazy danych `items` z elementami podzielonymi na kategorie:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Jabłko
+| 2 | 1 | Banana
+| 3 | 2 | PHP
+| 4 | 3 | Zielony
+| 5 | 3 | Czerwony
+| 6 | 3 | Niebieski
+
+Prosta lista wszystkich elementów przy użyciu szablonu Latte wyglądałaby następująco:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Jeśli jednak chcemy, aby przedmioty były zorganizowane w grupy według kategorii, musimy podzielić je tak, aby każda kategoria miała własną listę. Wynik wyglądałby wtedy następująco:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Zadanie to można łatwo i elegancko rozwiązać za pomocą `|group`. Jako parametr podajemy `categoryId`, co oznacza, że elementy zostaną podzielone na mniejsze tablice w oparciu o wartość `$item->categoryId` (gdyby `$item` była tablicą, użylibyśmy `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Filtr może być również użyty jako funkcja w Latte, dając nam alternatywną składnię: `{foreach group($items, categoryId) ...}`.
+
+Jeśli chcesz pogrupować elementy według bardziej złożonych kryteriów, możesz użyć funkcji w parametrze filtra. Na przykład grupowanie elementów według długości ich nazwy wyglądałoby następująco:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Należy zauważyć, że `$categoryItems` nie jest zwykłą tablicą, ale obiektem, który zachowuje się jak iterator. Aby uzyskać dostęp do pierwszego elementu w grupie, można użyć funkcji [`first()` |latte:functions#first] function.
+
+Ta elastyczność w grupowaniu danych sprawia, że `group` jest wyjątkowo przydatnym narzędziem do prezentacji danych w szablonach Latte.
+
+
+Zagnieżdżone pętle .[#toc-nested-loops]
+---------------------------------------
+
+Załóżmy, że mamy tabelę bazy danych z inną kolumną `subcategoryId`, która definiuje podkategorie dla każdego elementu. Chcemy wyświetlić każdą główną kategorię na osobnej liście `<ul>` a każdą podkategorię na osobnej zagnieżdżonej liście `<ol>` liście:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Połączenie z bazą danych Nette .[#toc-connection-with-nette-database]
+---------------------------------------------------------------------
+
+Pokażmy, jak efektywnie wykorzystać grupowanie danych w połączeniu z Nette Database. Załóżmy, że pracujemy z tabelą `items` z początkowego przykładu, która jest połączona przez kolumnę `categoryId` z tabelą `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Fruits |
+| 2 | Języki |
+| 3 | Kolory |
+
+Wczytujemy dane z tabeli `items` za pomocą polecenia Nette Database Explorer `$items = $db->table('items')`. Podczas iteracji po tych danych mamy możliwość nie tylko dostępu do atrybutów takich jak `$item->name` i `$item->categoryId`, ale dzięki połączeniu z tabelą `categories`, także do powiązanego z nią wiersza poprzez `$item->category`. To połączenie może wykazać interesujące zastosowania:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+W tym przypadku używamy filtra `|group` do grupowania według połączonego wiersza `$item->category`, a nie tylko według kolumny `categoryId`. Daje nam to `ActiveRow` danej kategorii w kluczu zmiennej, co pozwala nam bezpośrednio wyświetlić jej nazwę za pomocą `{$category->name}`. Jest to praktyczny przykład tego, jak grupowanie może uprościć szablony i ułatwić obsługę danych.
+
+
+Filtr `|batch` .[#toc-filter-batch]
+===================================
+
+Filtr umożliwia podzielenie listy elementów na grupy o z góry określonej liczbie elementów. Ten filtr jest idealny w sytuacjach, gdy chcesz przedstawić dane w kilku mniejszych grupach, na przykład dla lepszej przejrzystości lub wizualnej organizacji na stronie.
+
+Wyobraźmy sobie, że mamy listę elementów i chcemy wyświetlić je na listach, z których każda zawiera maksymalnie trzy elementy. Użycie filtra `|batch` jest w takim przypadku bardzo praktyczne:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+W tym przykładzie lista `$items` jest podzielona na mniejsze grupy, z których każda (`$batch`) zawiera maksymalnie trzy elementy. Każda grupa jest następnie wyświetlana na osobnej `<ul>` liście.
+
+Jeśli ostatnia grupa nie zawiera wystarczającej liczby elementów, aby osiągnąć pożądaną liczbę, drugi parametr filtra pozwala określić, czym ta grupa zostanie uzupełniona. Jest to idealne rozwiązanie do estetycznego wyrównania elementów, w przypadku których niekompletny wiersz może wyglądać na nieuporządkowany.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Tag `{iterateWhile}` .[#toc-tag-iteratewhile]
+=============================================
+
+Zademonstrujemy te same zadania, którymi zajmowaliśmy się z filtrem `|group` przy użyciu tagu `{iterateWhile}`. Główna różnica między tymi dwoma podejściami polega na tym, że `group` najpierw przetwarza i grupuje wszystkie dane wejściowe, podczas gdy `{iterateWhile}` kontroluje postęp cykli z warunkami, więc iteracja odbywa się sekwencyjnie.
+
+Najpierw rysujemy tabelę z kategoriami za pomocą iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Podczas gdy `{foreach}` oznacza zewnętrzną część cyklu, tj. rysowanie list dla każdej kategorii, znacznik `{iterateWhile}` oznacza część wewnętrzną, tj. poszczególne elementy.
+Warunek w znaczniku end mówi, że powtarzanie będzie kontynuowane tak długo, jak bieżący i następny element należą do tej samej kategorii (`$iterator->nextValue` jest [następnym elementem |/tags#$iterator]).
+
+Gdyby warunek był zawsze spełniony, wszystkie elementy byłyby rysowane w wewnętrznym cyklu:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Wynik będzie wyglądał następująco:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Jaki jest pożytek z iterateWhile w ten sposób? Gdy tabela jest pusta i nie zawiera żadnych elementów, nie jest wypisywana pusta wartość `<ul></ul>` jest drukowany.
+
+Jeśli określimy warunek w otwierającym tagu `{iterateWhile}`, zachowanie ulegnie zmianie: warunek (i przejście do następnego elementu) jest wykonywany na początku wewnętrznego cyklu, a nie na końcu.
+Tak więc, podczas gdy zawsze wchodzisz na `{iterateWhile}` bez warunków, wchodzisz na `{iterateWhile $cond}` tylko wtedy, gdy warunek `$cond` jest spełniony. W tym samym czasie następny element jest zapisywany w `$item`.
+
+Jest to przydatne na przykład w sytuacji, gdy chcemy wyrenderować pierwszy element w każdej kategorii w inny sposób, na przykład w następujący sposób:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Modyfikujemy oryginalny kod w taki sposób, że najpierw renderujemy pierwszy element, a następnie w wewnętrznym cyklu `{iterateWhile}` renderujemy pozostałe elementy z tej samej kategorii:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+W ramach jednego cyklu możemy utworzyć wiele wewnętrznych pętli, a nawet je zagnieżdżać. W ten sposób można na przykład grupować podkategorie.
+
+Załóżmy, że tabela ma jeszcze jedną kolumnę `subcategoryId`, a oprócz tego każda kategoria znajduje się w osobnej kolumnie. `<ul>`a każda podkategoria w osobnej `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/pl/cookbook/iteratewhile.texy b/latte/pl/cookbook/iteratewhile.texy
deleted file mode 100644
index f4c86b6b2c..0000000000
--- a/latte/pl/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Wszystko, co kiedykolwiek chciałeś wiedzieć o {iterateWhile}.
-*************************************************************
-
-.[perex]
-Znacznik `{iterateWhile}` jest przydatny do wszelkiego rodzaju sztuczek w pętlach foreach.
-
-Załóżmy, że mamy następującą tabelę bazy danych, w której przedmioty są skategoryzowane:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Renderowanie elementów w pętli foreach jako listy jest oczywiście proste:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Ale co jeśli chcielibyśmy, aby każda kategoria była na osobnej liście? Innymi słowy, rozwiązujemy problem, jak pogrupować elementy na liście liniowej w pętli foreach. Dane wyjściowe powinny wyglądać tak:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Zobaczymy jak łatwo i elegancko można rozwiązać to zadanie używając iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Podczas gdy `{foreach}` oznacza zewnętrzną część pętli, czyli renderowanie list dla każdej kategorii, znacznik `{iterateWhile}` oznacza część wewnętrzną, czyli poszczególne elementy.
-Warunek w znaczniku end mówi, że iteracja będzie trwała tak długo, jak długo bieżący i następny element należą do tej samej kategorii (`$iterator->nextValue` jest [następnym |/tags#iterator] elementem).
-
-Gdyby warunek był zawsze spełniony, wszystkie elementy byłyby renderowane w wewnętrznej pętli:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Wynik wyglądałby tak:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Jakie jest zastosowanie iterateWhile? Czym różni się ono od rozwiązania, które pokazaliśmy na samym początku tego tutorialu? Różnica polega na tym, że jeśli tablica jest pusta i nie zawiera żadnych elementów, nie zostanie wypisana pusta tablica `<ul></ul>`.
-
-
-Rozwiązanie bez `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-----------------------------------------------------------------------
-
-Gdybyśmy mieli rozwiązać to samo zadanie używając bardzo podstawowych systemów templatowania, na przykład w Twigu, Blade, czy czystym PHP, rozwiązanie wyglądałoby coś takiego:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* kategoria zmieniona *}
-
-		{* zamknij poprzedni, <ul> jeśli nie jest pierwszym elementem *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* otwórz nową listę *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* zamknij ostatnią listę *}
-	</ul>
-{/if}
-```
-
-Jednak ten kod jest niezrozumiały i nieintuicyjny. Związek pomiędzy otwierającymi i zamykającymi znacznikami HTML nie jest wcale jasny. Nie widać na pierwszy rzut oka, czy jest jakiś błąd. I wymaga zmiennych pomocniczych, takich jak `$prevCatId`.
-
-W przeciwieństwie do tego, rozwiązanie `{iterateWhile}` jest czyste, jasne, nie potrzebuje zmiennych pomocniczych i jest bloatproof.
-
-
-Warunek w tagu otwierającym .[#toc-condition-in-the-closing-tag]
-----------------------------------------------------------------
-
-Jeśli określisz warunek w znaczniku otwierającym `{iterateWhile}`, to zachowanie się zmieni: warunek (i przejście do następnego elementu) jest wykonywany na początku pętli wewnętrznej, a nie na końcu.
-O ile więc `{iterateWhile}` bez warunku jest wpisywany zawsze, to `{iterateWhile $cond}` jest wpisywany dopiero po spełnieniu warunku `$cond`. I w tym samym czasie na stronę `$item` wchodzi kolejny element.
-
-Co jest przydatne np. jeśli chcemy wyrenderować pierwszy element w każdej kategorii w inny sposób, np:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Zmodyfikuj oryginalny kod, najpierw renderując pierwszy element, a następnie renderując pozostałe elementy z tej samej kategorii w wewnętrznej pętli strony `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Pętle zagnieżdżone .[#toc-nested-loops]
----------------------------------------
-
-Możemy tworzyć wiele pętli wewnętrznych w ramach jednej pętli, a nawet je zagnieżdżać. W ten sposób można by grupować np. podkategorie itp.
-
-Załóżmy, że w tabeli `subCatId` jest jeszcze jedna kolumna i oprócz tego, że każda kategoria jest w osobnej `<ul>`każda podkategoria w osobnym `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtr |wszystkie .[#toc-filter-batch]
--------------------------------------
-
-Filtr `batch` obsługuje również grupowanie elementów liniowych w partie o stałej liczbie elementów:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Można go zastąpić iterateWhile w następujący sposób:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/pl/cookbook/passing-variables.texy b/latte/pl/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..e587c03969
--- /dev/null
+++ b/latte/pl/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Przekazywanie zmiennych między szablonami
+*****************************************
+
+Ten przewodnik wyjaśnia, w jaki sposób zmienne są przekazywane między szablonami w Latte przy użyciu różnych tagów, takich jak `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` i innych. Dowiesz się również, jak pracować ze zmiennymi w tagach `{block}` i `{define}` oraz jaki jest cel tagu `{parameters}`.
+
+
+Rodzaje zmiennych .[#toc-types-of-variables]
+--------------------------------------------
+Zmienne w Latte można podzielić na trzy kategorie w zależności od tego, jak i gdzie są zdefiniowane:
+
+**Zmienne wejściowe** to te, które są przekazywane do szablonu z zewnątrz, na przykład ze skryptu PHP lub przy użyciu tagu takiego jak `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Zmienne otaczające** to zmienne istniejące w miejscu określonego tagu. Obejmują one wszystkie zmienne wejściowe i inne zmienne utworzone przy użyciu tagów takich jak `{var}`, `{default}` lub w pętli `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Zmienne jawne** to zmienne bezpośrednio określone w tagu i wysłane do szablonu docelowego.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Znacznik `{block}` służy do definiowania bloków kodu wielokrotnego użytku, które można dostosowywać lub rozszerzać w dziedziczonych szablonach. Otaczające zmienne zdefiniowane przed blokiem są dostępne wewnątrz bloku, ale wszelkie zmiany zmiennych są odzwierciedlane tylko w tym bloku.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Znacznik `{define}` jest używany do tworzenia bloków, które są renderowane tylko wtedy, gdy są wywoływane za pomocą `{include}`. Zmienne dostępne wewnątrz tych bloków zależą od tego, czy w definicji określono parametry. Jeśli parametry są określone, tylko te parametry są dostępne. Jeśli nie, dostępne są wszystkie zmienne wejściowe szablonu, w którym zdefiniowane są bloki.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Znacznik `{parameters}` służy do jawnego deklarowania oczekiwanych zmiennych wejściowych na początku szablonu. W ten sposób można łatwo udokumentować oczekiwane zmienne i ich typy danych. Możliwe jest również zdefiniowanie wartości domyślnych.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Znacznik `{include file}` służy do wstawiania całego szablonu. Szablon ten przekazuje zarówno zmienne wejściowe szablonu, w którym tag jest używany, jak i jawnie zdefiniowane zmienne. Szablon docelowy może jednak ograniczyć zakres za pomocą `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Podczas wstawiania bloku zdefiniowanego w tym samym szablonie, wszystkie otaczające i jawnie zdefiniowane zmienne są do niego przekazywane:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+W tym przykładzie zmienne `$name` i `$age` są przekazywane do bloku `blockName`. To samo zachowanie dotyczy `{include parent}`.
+
+Podczas wstawiania bloku z innego szablonu przekazywane są tylko zmienne wejściowe i jawnie zdefiniowane zmienne. Zmienne otaczające nie są automatycznie dostępne.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` lub `{extends}`
+--------------------------
+Znaczniki te definiują układ, do którego przekazywane są zmienne wejściowe szablonu podrzędnego i zmienne utworzone w kodzie przed blokami:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Szablon `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Znacznik `{embed}` jest podobny do znacznika `{include}`, ale umożliwia osadzanie bloków w szablonie. W przeciwieństwie do `{include}`, przekazywane są tylko jawnie zadeklarowane zmienne:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+W tym przykładzie szablon `menu.latte` ma dostęp tylko do zmiennej `$items`.
+
+I odwrotnie, bloki wewnątrz `{embed}` mają dostęp do wszystkich otaczających zmiennych:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Znacznik `{import}` służy do ładowania bloków z innych szablonów. Do zaimportowanych bloków przekazywane są zarówno zmienne wejściowe, jak i jawnie zadeklarowane zmienne.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Znacznik `{sandbox}` izoluje szablon w celu bezpiecznego przetwarzania. Zmienne są przekazywane wyłącznie jawnie.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/pl/creating-extension.texy b/latte/pl/creating-extension.texy
index 16e3fb6bb3..c82776c374 100644
--- a/latte/pl/creating-extension.texy
+++ b/latte/pl/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// funkcja parsowania, która na razie tworzy tylko węzeł
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Jeśli tworzysz nowy tag dla Latte, zaleca się utworzenie dla niego dedykowanej klasy węzła, która będzie reprezentować go w drzewie AST (patrz klasa `ForeachNode` w powyższym przykładzie). W niektórych przypadkach przydatna może okazać się trywialna klasa węzła pomocniczego [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], która pozwala przekazać ciało metody `print()` i listę węzłów udostępnionych przez metodę `getIterator()` jako parametry konstruktora:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Kompilator przechodzi .[#toc-compiler-passes]
 =============================================
 
diff --git a/latte/pl/develop.texy b/latte/pl/develop.texy
index bb2dbd5253..353a90b36e 100644
--- a/latte/pl/develop.texy
+++ b/latte/pl/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Lokalizacja .[#toc-locale]{data-version:3.0.18}
+===============================================
+
+Latte pozwala ustawić ustawienia regionalne, które wpływają na formatowanie liczb, dat i sortowanie. Jest on ustawiany przy użyciu metody `setLocale()`. Identyfikator ustawień regionalnych jest zgodny ze standardem znaczników językowych IETF, który wykorzystuje rozszerzenie PHP `intl`. Składa się z kodu języka i ewentualnie kodu kraju, na przykład `en_US` dla języka angielskiego w Stanach Zjednoczonych, `de_DE` dla języka niemieckiego w Niemczech itp.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Ustawienie locale wpływa na filtry [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] i [bytes |filters#bytes].
+
+.[note]
+Wymaga rozszerzenia PHP `intl`. Ustawienie w Latte nie wpływa na globalne ustawienie locale w PHP.
+
+
 Tryb ścisły .[#toc-strict-mode]{data-version:3.0.8}
 ===================================================
 
@@ -274,16 +290,25 @@ Jeśli używasz niestandardowych znaczników, utwórz również swój niestandar
 // wprowadź rzeczywistą ścieżkę do pliku autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// dodaj tutaj indywidualne rozszerzenia
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// dodaj tutaj swoje indywidualne rozszerzenia
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternatywnie, można przekazać własny obiekt `Latte\Engine` do aplikacji Linter:
+
+```php
+$latte = new Latte\Engine;
+// tutaj konfigurujemy obiekt $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Ładowanie szablonów z łańcucha .[#toc-loading-templates-from-a-string]
 ======================================================================
diff --git a/latte/pl/extending-latte.texy b/latte/pl/extending-latte.texy
index 9c6fc477ff..76b093805f 100644
--- a/latte/pl/extending-latte.texy
+++ b/latte/pl/extending-latte.texy
@@ -68,6 +68,16 @@ Jak widać, funkcja otrzymuje lewą stronę filtra przed fajką `|` jako první
 
 Oczywiście funkcja reprezentująca filtr może przyjąć dowolną liczbę parametrów, obsługiwane są również parametry variadyczne.
 
+Jeśli filtr zwraca ciąg znaków w HTML, można go oznaczyć, aby Latte nie wykonywało automatycznego (a więc podwójnego) escapingu. Pozwala to uniknąć konieczności określania `|noescape` w szablonie.
+Najprostszym sposobem jest zawinięcie łańcucha w obiekt `Latte\Runtime\Html`, innym sposobem są [filtry kontekstowe |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+W takim przypadku filtr musi zapewnić prawidłowe uciekanie danych.
+
 
 Filtry z wykorzystaniem klasy .[#toc-filters-using-the-class]
 -------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// změníme content-type na HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/pl/filters.texy b/latte/pl/filters.texy
index 26522886f7..06318f6e6c 100644
--- a/latte/pl/filters.texy
+++ b/latte/pl/filters.texy
@@ -11,14 +11,16 @@ Możemy używać funkcji w szablonach, aby pomóc w edycji lub przeformatowaniu
 | `bytes` | [rozmiar formatu w bajtach |#bytes]
 | `clamp` | [ogranicza wartość do podanego zakresu |#clamp]
 | `dataStream` | [konwersja dla protokołu Data URI |#dataStream]
-| `date` | [formatuje datę |#date]
+| `date` | [formatuje datę i godzinę |#date]
 | `explode` | [dzieli łańcuch na pola zgodnie z delimiterem |#explode]
 | `first` | [zwraca pierwszy element tablicy lub znak łańcucha|#first]
+| `group` | [grupuje dane według różnych kryteriów |#group]
 | `implode` | [łączy pola w ciąg znaków|#implode]
 | `indent` | [przesuwa tekst od lewej strony o podaną liczbę tabulatorów |#indent]
 | `join` | [konkatenuje tablicę w ciąg znaków|#implode]
 | `last` | [zwraca ostatni element tablicy lub znak łańcucha|#last]
 | `length` | [zwraca długość łańcucha w znakach lub tablicy |#length]
+| `localDate` | [formatuje datę i godzinę zgodnie z ustawieniami regionalnymi |#localDate]
 | `number` | [formatuje liczbę |#number]
 | `padLeft` | [uzupełnia ciąg od lewej do pożądanej długości |#padLeft]
 | `padRight` | [uzupełnia ciąg od prawej do pożądanej długości |#padRight]
@@ -118,8 +120,8 @@ Filtry .[#toc-filters]
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filtr, który upraszcza wyprowadzenie danych liniowych do tabeli. Zwraca tablicę pól o określonej liczbie elementów. Jeśli określisz drugi parametr, jest on używany do wypełnienia brakujących elementów w ostatnim wierszu.
 
 ```latte
@@ -152,6 +154,8 @@ Wydruki:
 </table>
 ```
 
+Zobacz także tag [group |#group] i [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Wstawia podziały linii HTML przed wszystkimi liniami nowymi.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formatuje rozmiar w bajtach do postaci czytelnej dla człowieka.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formatuje rozmiar w bajtach do postaci czytelnej dla człowieka. Jeśli ustawione są [ustawienia regionalne |develop#locale], używane są odpowiednie separatory dziesiętne i tysięczne.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formatuje rozmiar w bajtach do postaci czytelnej dla człowieka.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Zaokrągla liczbę do określonej precyzji.
 
 ```latte
@@ -203,8 +207,8 @@ Wymusza sanityzację adresów URL. Sprawdza czy zmienna zawiera adres URL strony
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Wydruki:
@@ -217,8 +221,8 @@ Wydruki:
 Zobacz również [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Zwraca wartość zaciśniętą na inkluzywnym zakresie min i max.
 
 ```latte
@@ -228,14 +232,14 @@ Zwraca wartość zaciśniętą na inkluzywnym zakresie min i max.
 Istnieje również jako [funkcja |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Konwertuje zawartość na schemat URI danych. Może być używany do wstawiania obrazów do HTML lub CSS bez potrzeby łączenia plików zewnętrznych.
 
 Załóżmy, że mamy obrazek w zmiennej `$img = Image::fromFile('obrazek.gif')`, to
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Drukuje na przykład:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Wymaga rozszerzenia PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Zwraca datę w podanym formacie przy użyciu opcji funkcji PHP [php:strftime] lub [php:date]. Filtr pobiera datę jako timestamp UNIX, łańcuch znaków lub obiekt typu `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formatuje datę i godzinę zgodnie z maską używaną przez funkcję PHP [php:date]. Filtr akceptuje datę w formacie znacznika czasu UNIX, jako ciąg znaków lub jako obiekt `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Zobacz także [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Ucieka od zmiennej, która ma być użyta jako parametr w URL.
 Zobacz również [zapytanie |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Rozdziela łańcuch przez podany delimiter i zwraca tablicę łańcuchów. Alias dla `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Zwraca pierwszy element tablicy lub znak łańcucha:
 Zobacz także [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Zaokrągla liczbę do określonej dokładności.
 
 ```latte
@@ -330,8 +335,27 @@ Konwertuje pierwszą literę wartości na duże. Wymaga rozszerzenia PHP `mbstri
 Zobacz także [capitalize |#capitalize], [lower |#lower], [upper |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Filtr grupuje dane według różnych kryteriów.
+
+W tym przykładzie wiersze w tabeli są pogrupowane według kolumny `categoryId`. Wynikiem jest tablica tablic, w której kluczem jest wartość w kolumnie `categoryId`. Przeczytaj [szczegółowe instrukcje |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Zobacz także [batch |#batch], funkcję [group |functions#group] i znacznik [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Zwraca łańcuch będący konkatenacją łańcuchów w tablicy. Alias dla `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Możesz również użyć aliasu `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Wcina tekst od lewej strony o określoną liczbę tabulatorów lub innych znaków, które podajemy w drugim opcjonalnym argumencie. Puste linie nie są wcięte.
 
 ```latte
@@ -396,6 +420,68 @@ Zwraca długość łańcucha lub tablicy.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formatuje datę i godzinę zgodnie z [ustawieniami regionalnymi |develop#locale], zapewniając spójne i zlokalizowane wyświetlanie danych czasu w różnych językach i regionach. Filtr akceptuje datę jako znacznik czasu UNIX, ciąg znaków lub obiekt `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Jeśli użyjesz filtra bez żadnych parametrów, wyświetli on datę w długim formacie, jak wyjaśniono dalej.
+
+**a) Użycie formatu**
+
+Parametr `format` opisuje, które składniki czasu powinny być wyświetlane. Używa kodów literowych, gdzie liczba powtórzeń wpływa na szerokość wyjścia:
+
+| Rok | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Miesiąc | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `sie` / `sierpień`
+| Dzień | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `niedz.` / `niedziela`
+| Godzina | `j` / `H` / `h` | preferowana / 24-godzinna / 12-godzinna
+| Minuta | `m` / `mm` | `5` / `05` <small>(2 cyfry w połączeniu z sekundami)</small>
+| Sekunda | `s` / `ss` | `8` / `08` <small>(2 cyfry w połączeniu z minutami)</small>
+
+Kolejność kodów w formacie nie ma znaczenia, ponieważ kolejność komponentów będzie wyświetlana zgodnie z konwencjami regionalnymi. Dlatego format jest niezależny od ustawień regionalnych. Na przykład, format `yyyyMMMMd` w locale `en_US` wyświetla `April 15, 2024`, podczas gdy w locale `cs_CZ` wyświetla `15. dubna 2024`:
+
+| locale:  | pl-PL | en_US
+|---
+| `format: 'dMy'` | 10.08.2024 | 8/10/2024
+| `format: 'yM'` | 08.2024 | 8/2024
+| `format: 'yyyyMMMM'` | sierpień 2024 | August 2024
+| `format: 'MMMM'` | sierpień | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 PM | 5:54 PM
+
+
+**b) Korzystanie z gotowych stylów**
+
+Parametry `date` i `time` określają poziom szczegółowości wyświetlania daty i godziny. Można wybrać jeden z kilku poziomów: `full`, `long`, `medium`, `short`. Można wyświetlać tylko datę, tylko godzinę lub obie te wartości:
+
+| locale:  | pl-PL | en_US
+|---
+| `date: short` | 23.01.1978 | 1/23/78
+| `date: medium` | 23 sty 1978 | Jan 23, 1978
+| `date: long` | 23 stycznia 1978 | January 23, 1978
+| `date: full` | poniedziałek, 23 stycznia 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.1978, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 sty 1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 stycznia 1978 08:30 | January 23, 1978 at 8:30 AM
+
+W przypadku daty można również użyć prefiksu `relative-` (np. `relative-short`), co w przypadku dat bliskich teraźniejszości spowoduje wyświetlenie `yesterday`, `today` lub `tomorrow`; w przeciwnym razie zostanie wyświetlony w standardowy sposób.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Zobacz też [data |#date].
+
+
 lower .[filter]
 ---------------
 Konwertuje wartość na małe litery. Wymaga rozszerzenia PHP `mbstring`.
@@ -416,8 +502,8 @@ Jeśli link używa innego schematu, takiego jak `javascript:` lub `data:`, i jes
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Wydruki:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 Niewłaściwe użycie filtra `noescape` może prowadzić do luki XSS! Nigdy nie używaj go, jeśli nie jesteś **absolutnie pewien** tego, co robisz i że drukowany ciąg pochodzi z zaufanego źródła.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formatuje liczbę do podanej liczby miejsc dziesiętnych. Można również określić znak kropki dziesiętnej i separatora tysięcy.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formatuje liczbę do określonej liczby miejsc dziesiętnych. Jeśli ustawione są [ustawienia regionalne |develop#locale], używane są odpowiednie separatory dziesiętne i tysięczne.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Formatuje liczbę do podanej liczby miejsc dziesiętnych. Można również okre
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Parametr `format` pozwala zdefiniować wygląd liczb dokładnie według własnych potrzeb. Wymaga ustawionych [ustawień regionalnych |develop#locale]. Format składa się z kilku znaków specjalnych, których pełny opis można znaleźć w dokumentacji "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> cyfra obowiązkowa, wyświetlana zawsze, nawet jeśli jest zerem
+- `#` cyfra opcjonalna, wyświetlana tylko wtedy, gdy liczba ma cyfrę w tym miejscu
+- `@` cyfra znacząca, pomaga wyświetlić liczbę z określoną liczbą cyfr znaczących
+- `.` oznacza miejsce, w którym powinien znajdować się separator dziesiętny (przecinek lub kropka, w zależności od ustawień regionalnych)
+- `,` używany do oddzielania grup cyfr, zwykle tysięcy
+- `%` mnoży liczbę przez 100 i dodaje znak procentu
+
+Przyjrzyjmy się kilku przykładom. W pierwszym przykładzie dwa miejsca po przecinku są obowiązkowe; w drugim są opcjonalne. Trzeci przykład pokazuje wypełnianie zerami po obu stronach, a czwarty wyświetla tylko istniejące cyfry:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Znaczące cyfry określają, ile cyfr, niezależnie od przecinka dziesiętnego, powinno być wyświetlanych, zaokrąglając liczbę w razie potrzeby:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Prosty sposób wyświetlania liczby jako procentu. Liczba jest mnożona przez 100 i dodawany jest znak `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Możemy zdefiniować inny format dla liczb dodatnich i ujemnych, oddzielonych znakiem `;`. W ten sposób, na przykład, liczby dodatnie mogą być wyświetlane ze znakiem `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Należy pamiętać, że rzeczywisty wygląd liczb może się różnić w zależności od ustawień regionalnych. Na przykład w niektórych krajach przecinek jest używany zamiast kropki jako separator dziesiętny. Ten filtr automatycznie to uwzględnia, więc nie musisz się tym martwić.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Przekłada łańcuch o określonej długości z innym łańcuchem od lewej.
 
@@ -472,7 +606,7 @@ Przekłada łańcuch o określonej długości z innym łańcuchem od lewej.
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Wyrównuje ciąg do pewnej długości z innym ciągiem od prawej.
 
@@ -514,8 +648,8 @@ Zwraca losowy element tablicy lub znak łańcucha:
 Zobacz również [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Powtarza łańcuch x razy.
 
 ```latte
@@ -523,7 +657,7 @@ Powtarza łańcuch x razy.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Zastępuje wszystkie wystąpienia szukanego łańcucha łańcuchem zastępczym.
 
@@ -538,7 +672,7 @@ Można dokonać wielu zamian jednocześnie:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Zastępuje wszystkie wystąpienia zgodnie z wyrażeniem regularnym.
 
@@ -559,8 +693,8 @@ Odwraca podany łańcuch lub tablicę.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Zaokrągla liczbę do określonej precyzji.
 
 ```latte
@@ -573,7 +707,7 @@ Zaokrągla liczbę do określonej precyzji.
 Zobacz także [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Wyodrębnia fragment tablicy lub ciągu znaków.
 
@@ -591,9 +725,9 @@ Jeśli podana jest długość i jest ona dodatnia, to sekwencja będzie miała d
 Filtr domyślnie zmieni kolejność i wyzeruje klucze tablicy liczb całkowitych. To zachowanie można zmienić ustawiając preserveKeys na true. Klucze łańcuchowe są zawsze zachowywane, niezależnie od tego parametru.
 
 
-sort  .[filter]
----------------
-Filtr, który sortuje tablicę i zachowuje asocjację indeksów.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Filtr sortuje elementy tablicy lub iteratora, zachowując ich klucze asocjacyjne. Gdy ustawione są [ustawienia regionalne |develop#locale], sortowanie odbywa się zgodnie z ich regułami, chyba że określono niestandardową funkcję porównania.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Tablica posortowana w odwrotnej kolejności.
 {/foreach}
 ```
 
-Możesz przekazać własną funkcję porównania jako parametr:
+Można określić niestandardową funkcję porównania do sortowania (przykład pokazuje, jak odwrócić sortowanie od największego do najmniejszego):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Filtr `|sort` umożliwia również sortowanie elementów według klucza:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Jeśli chcesz posortować tabelę według określonej kolumny, możesz użyć parametru `by`. Wartość `'name'` w przykładzie określa, że sortowanie zostanie wykonane według `$row->name` lub `$row['name']`w zależności od tego, czy `$row` jest tablicą czy obiektem:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Można również zdefiniować funkcję zwrotną, która określa wartość do sortowania:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Parametr `byKey` może być używany w ten sam sposób.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Konwertuje HTML na zwykły tekst. To znaczy, usuwa znaczniki HTML i konwertuje e
 Wynikowy zwykły tekst może naturalnie zawierać znaki reprezentujące znaczniki HTML, na przykład `'&lt;p&gt;'|stripHtml` jest konwertowany na `<p>`. Nigdy nie wyprowadzaj wynikowego tekstu za pomocą `|noescape`, ponieważ może to prowadzić do luki w zabezpieczeniach.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Wyodrębnia fragment łańcucha. Ten filtr został zastąpiony przez filtr [slice |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ Wyodrębnia fragment łańcucha. Ten filtr został zastąpiony przez filtr [slic
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Tłumaczy wyrażenia na inne języki. Aby udostępnić ten filtr, musisz skonfigurować [translator |develop#TranslatorExtension]. Możesz również użyć [tagów do tłumaczenia |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Tłumaczy wyrażenia na inne języki. Aby udostępnić ten filtr, musisz skonfig
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Strip leading and trailing characters, by default whitespace.
 
 ```latte
@@ -675,7 +835,7 @@ Strip leading and trailing characters, by default whitespace.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Skraca łańcuch do maksymalnej podanej długości, ale stara się zachować całe słowa. Jeśli łańcuch jest obcięty, dodaje na końcu elipsę (można to zmienić drugim parametrem).
 
diff --git a/latte/pl/functions.texy b/latte/pl/functions.texy
index 982fd3cd98..0f7ae368e7 100644
--- a/latte/pl/functions.texy
+++ b/latte/pl/functions.texy
@@ -9,6 +9,8 @@ Oprócz zwykłych funkcji PHP, w szablonach możemy używać także następując
 | `divisibleBy`| [sprawdza, czy zmienna jest podzielna przez liczbę |#divisibleBy]
 | `even` | [sprawdza, czy podana liczba jest parzysta |#even]
 | `first` | [zwraca pierwszy element tablicy lub znak łańcucha|#first]
+| `group` | [grupuje dane według różnych kryteriów |#group]
+| `hasBlock` | [wykrywa istnienie bloku |#hasBlock]
 | `last` | [zwraca ostatni element tablicy lub znak łańcucha|#last]
 | `odd` | [sprawdza, czy podana liczba jest nieparzysta |#odd]
 | `slice` | [wyciąga część tablicy lubłańcucha |#slice]
@@ -73,8 +75,8 @@ Sprawdza, czy podana liczba jest parzysta.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Zwraca pierwszy element tablicy lub znak łańcucha:
 
 ```latte
@@ -85,6 +87,36 @@ Zwraca pierwszy element tablicy lub znak łańcucha:
 Zobacz także [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Ta funkcja grupuje dane według różnych kryteriów.
+
+W tym przykładzie wiersze w tabeli są grupowane według kolumny `categoryId`. Wynikiem jest tablica pól, w której kluczem jest wartość w kolumnie `categoryId`. Przeczytaj [szczegółowe instrukcje |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Zobacz także [grupę |filters#group] filtrów.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Sprawdza, czy blok o podanej nazwie istnieje:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Zobacz także [sprawdzanie istnienia |template-inheritance#Checking Block Existence] bloku.
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Zwraca ostatni element tablicy lub znak łańcucha:
@@ -106,8 +138,8 @@ Sprawdza, czy podana liczba jest nieparzysta.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Wyodrębnia część tablicy lub łańcucha.
 
 ```latte
diff --git a/latte/pl/recipes.texy b/latte/pl/recipes.texy
index c95813ae11..a0cbc407c6 100644
--- a/latte/pl/recipes.texy
+++ b/latte/pl/recipes.texy
@@ -9,7 +9,7 @@ Napisz szablony w edytorze lub IDE, który ma wsparcie dla Latte. Będzie to o w
 
 - NetBeans IDE ma wbudowaną obsługę
 - PhpStorm: zainstaluj [wtyczkę Latte |https://plugins.jetbrains.com/plugin/7457-latte] w `Settings > Plugins > Marketplace`
-- Kod VS: wyszukiwanie w markerplace dla wtyczki "Nette Latte + Neon"
+- VS Code: wyszukaj markerplace dla [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] lub [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
 - Sublime Text 3: w Package Control znajdź i zainstaluj pakiet `Nette` i wybierz Latte w `View > Syntax`
 - W starych edytorach użyj podświetlenia Smarty dla plików .latte
 
diff --git a/latte/pl/safety-first.texy b/latte/pl/safety-first.texy
index e862574247..a3cae08534 100644
--- a/latte/pl/safety-first.texy
+++ b/latte/pl/safety-first.texy
@@ -351,7 +351,7 @@ Latte automatycznie sprawdza, czy zmienna użyta w atrybutach `src` lub `href` z
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">klikni</a>
+<a href={$link}>click here</a>
 ```
 
 Wydruki:
diff --git a/latte/pl/syntax.texy b/latte/pl/syntax.texy
index 60e450adc9..4d4bd4e523 100644
--- a/latte/pl/syntax.texy
+++ b/latte/pl/syntax.texy
@@ -98,7 +98,7 @@ Zostanie wydrukowany:
 Możesz też użyć przedrostka `tag-`, aby zastosować tę funkcjonalność do samych znaczników HTML:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Która wychodzi w zależności od zmiennej `$url`:
@@ -155,6 +155,20 @@ Lub bezpośrednio na wartość (w połączeniu z tagiem [`{=expr}` | https://lat
 ```
 
 
+Dynamiczne znaczniki HTML .[#toc-dynamic-html-tags]
+===================================================
+
+Latte obsługuje dynamiczne znaczniki HTML, które są przydatne, gdy potrzebujesz elastyczności w nazwach znaczników:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Na przykład, powyższy kod może wygenerować `<h1>Heading</h1>` lub `<h2>Heading</h2>` w zależności od wartości zmiennej `$level`. Dynamiczne znaczniki HTML w Latte muszą być zawsze sparowane. Ich alternatywą jest [n:tag |tags#n:tag].
+
+Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy wynikowa nazwa tagu jest prawidłowa i nie zawiera niepożądanych lub złośliwych wartości. Zapewnia również, że końcowa nazwa tagu jest zawsze taka sama jak nazwa tagu otwierającego.
+
+
 Uwagi .[#toc-comments]
 ======================
 
diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy
index a37e64df2e..9a368314fc 100644
--- a/latte/pl/tags.texy
+++ b/latte/pl/tags.texy
@@ -16,6 +16,7 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [ifset condition |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [test, czy nastąpiła zmiana |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [warunek przełączenia |#switch-case-default]
+| `n:else` | [alternatywna zawartość dla warunków |#n:else]
 
 .[table-latte-tags language-latte]
 |## Cykle
@@ -97,8 +98,8 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy
 |</m> `{link}` | [drukuje link |application:creating-links#In-the-Presenter-Template]
 | `{plink}` | [drukuje link do prezentera |application:creating-links#In-the-Presenter-Template]
 | `{control}` | [renderuje komponent |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [snippet, który może być wysłany przez AJAX |application:ajax#Tag-snippet]
-| `{snippetArea}` | clipping cover
+| `{snippet}`... `{/snippet}` | [snippet, który może być wysłany przez AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [clipping cover |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [buforuje część szablonu |caching:#Caching-in-Latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy
 | `{input}` | [renderuje element formularza |forms:rendering#label-input]
 | `{inputError}` | [drukuje komunikat o błędzie elementu formularza |forms:rendering#inputError]
 | `n:name` | [animuje element formularza |forms:rendering#n:name]
-| `{formPrint}` | [projekt kod latte dla formularza |forms:rendering#formPrint]
-| `{formPrintClass}` | [zaprojektuj kod PHP dla klasy z danymi formularza |forms:in-presenter#Mapping-to-Classes]
-| `{formContext}`... `{/formContext}` | [częściowy rysunek formy |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [renderowanie pojemnika na formularze |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Czy wiesz, że możesz przedrostek `tag-` do n:atrybutów ? Wtedy warunek będzi
 Boże.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Jeśli warunek `{if} ... {/if}` zostanie zapisany w postaci [atrybutu n: |syntax#n:attributes], istnieje możliwość określenia alternatywnej gałęzi za pomocą `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Atrybut `n:else` może być również użyty w połączeniu z [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]oraz [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Zobacz także. [`{ifset block}` |template-inheritance#Checking-Block-Existence]
 Użyj warunku `{ifset $var}`, aby określić, czy zmienna (lub wiele zmiennych) istnieje i ma wartość non-*null*. Właściwie to jest to samo, co `if (isset($var))` w PHP. Jak każdy znacznik par, może być również napisany jako [n:atrybut |syntax#n-attributes], więc weźmy to jako przykład:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ To całkiem poręczne, prawda?
 `{iterateWhile}`
 ----------------
 
-Upraszcza grupowanie danych liniowych podczas iteracji w pętli foreach poprzez iterację w pętli zagnieżdżonej do momentu spełnienia warunku. [Przeczytaj instrukcję |cookbook/iteratewhile].
+Upraszcza grupowanie danych liniowych podczas iteracji w pętli foreach poprzez iterację w pętli zagnieżdżonej do momentu spełnienia warunku. [Przeczytaj szczegółowe instrukcje |cookbook/grouping].
 
 Może również elegancko zastąpić `{first}` i `{last}` w powyższym przykładzie:
 
@@ -489,6 +501,8 @@ Może również elegancko zastąpić `{first}` i `{last}` w powyższym przykład
 {/foreach}
 ```
 
+Zobacz także filtry [wsadowe |filters#batch] i [grupowe |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Jeśli jest to `$heading === null`, tag jest drukowany bez zmian. `<h1>`. W prze
 <h3 class="main">...</h3>
 ```
 
+Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy nowa nazwa tagu jest poprawna i nie zawiera żadnych niepożądanych lub złośliwych wartości.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/pl/template-inheritance.texy b/latte/pl/template-inheritance.texy
index 6e7ef1a424..7ad283d542 100644
--- a/latte/pl/template-inheritance.texy
+++ b/latte/pl/template-inheritance.texy
@@ -132,7 +132,7 @@ Oto kilka wskazówek dotyczących pracy z dziedziczeniem układów:
 
 - Jeśli używasz `{layout}` w szablonie , musi to być pierwszy tag szablonu w tym szablonie.
 
-- Układ może być [wyszukiwany automatycznie |develop#automatic-layout-lookup] (jak w [prezenterach |application:templates#search-for-templates]). W takim przypadku, jeśli szablon nie powinien mieć układu, wskaże to za pomocą znacznika `{layout none}`.
+- Układ może być [wyszukiwany automatycznie |develop#automatic-layout-lookup] (jak w [prezenterach |application:templates#Template Lookup]). W takim przypadku, jeśli szablon nie powinien mieć układu, wskaże to za pomocą znacznika `{layout none}`.
 
 - Znacznik `{layout}` ma alias `{extends}`.
 
@@ -396,6 +396,14 @@ Nazwa bloku może być zmienną lub dowolnym wyrażeniem PHP. W tym przypadku do
 {/ifset}
 ```
 
+Istnienie bloków jest również zwracane przez funkcję [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Porady .[#toc-tips]
 -------------------
@@ -415,7 +423,7 @@ Kilka wskazówek dotyczących pracy z klockami:
 Ponowne wykorzystanie poziome `{import}` .{toc: Horizontal Reuse}
 =================================================================
 
-Poziome ponowne użycie jest trzecim mechanizmem wielokrotnego użycia i dziedziczenia w Latte. Pozwala na wczytywanie bloków z innych szablonów. Jest to podobne do tworzenia pliku PHP z funkcjami pomocniczymi.
+Horyzontalne ponowne użycie jest trzecim mechanizmem ponownego użycia i dziedziczenia w Latte. Pozwala on na ładowanie bloków z innych szablonów. Jest to podobne do tworzenia pliku z funkcjami pomocniczymi w PHP, a następnie ładowania go za pomocą `require`.
 
 Dziedziczenie układu szablonu jest jedną z najpotężniejszych funkcji Latte, ale jest ograniczone do prostego dziedziczenia - szablon może rozszerzyć tylko jeden inny szablon. Ponowne użycie horyzontalne jest sposobem na osiągnięcie wielokrotnego dziedziczenia.
 
@@ -447,7 +455,7 @@ Znacznik `{import}` powinien być pierwszym znacznikiem szablonu po `{layout}`.
 
 W szablonie możesz użyć dowolnej ilości oświadczeń `{import}`. Jeśli dwa importowane szablony definiują ten sam blok, wygrywa pierwszy. Jednak szablon główny ma najwyższy priorytet i może zastąpić każdy zaimportowany blok.
 
-Do wszystkich nadrzędnych bloków można uzyskać dostęp sekwencyjny, wstawiając je jako [blok |#Parent-Block] nadrzędny:
+Zawartość nadpisanych bloków można zachować, wstawiając blok w taki sam sposób, jak [blok nadrzędny |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/pt/@left-menu.texy b/latte/pt/@left-menu.texy
index 09fa4aa164..d2eaf7cf67 100644
--- a/latte/pt/@left-menu.texy
+++ b/latte/pt/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Como Começar |Guide]
 - [Por que usar modelos? |why-use]
-- Conceitos
+- Conceitos ⚗️
 	- [Segurança em primeiro lugar |Safety First]
 	- [Herança do modelo |Template Inheritance]
 	- [Tipo Sistema |Type System]
 	- [Sandbox |Sandbox]
 
-- Para projetistas
+- Para projetistas 🎨
 	- [Sintaxe |Syntax]
 	- [Etiquetas |Tags]
 	- [Filtros |Filters]
 	- [Funções |Functions]
 	- [Dicas e truques |recipes]
 
-- Para os desenvolvedores
+- Para os desenvolvedores 🧮
 	- [Práticas para os desenvolvedores |develop]
 	- [Ampliação do Latte |Extending Latte]
 	- [Criando uma extensão |creating-extension]
 
-- [Livro de receitas |cookbook/@home]
+- [Livro de receitas 💡|cookbook/@home]
 	- [Migração de galho |cookbook/migration-from-twig]
 	- [... mais |cookbook/@home]
 
diff --git a/latte/pt/cookbook/@home.texy b/latte/pt/cookbook/@home.texy
index d668db4db1..4e3f6c3c89 100644
--- a/latte/pt/cookbook/@home.texy
+++ b/latte/pt/cookbook/@home.texy
@@ -4,7 +4,9 @@ Cookbook
 .[perex]
 Exemplos de códigos e receitas para a realização de tarefas comuns com Latte.
 
-- [Tudo o que você sempre quis saber sobre {alfabetizar-assim} |iteratewhile]
+- [Diretrizes para desenvolvedores |/develop]
+- [Passagem de variáveis entre modelos |passing-variables]
+- [Tudo o que você sempre quis saber sobre agrupamento |grouping]
 - [Como escrever consultas SQL em Latte? |how-to-write-sql-queries-in-latte]
 - [Migração do PHP |migration-from-php]
 - [Migração de galho |migration-from-twig]
diff --git a/latte/pt/cookbook/grouping.texy b/latte/pt/cookbook/grouping.texy
new file mode 100644
index 0000000000..32e5ddd99b
--- /dev/null
+++ b/latte/pt/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Tudo o que você sempre quis saber sobre agrupamento
+***************************************************
+
+.[perex]
+Ao trabalhar com dados em modelos, você frequentemente se depara com a necessidade de agrupá-los ou exibi-los especificamente de acordo com determinados critérios. Para essa finalidade, o Latte oferece várias ferramentas poderosas.
+
+O filtro e a função `|group` permitem o agrupamento eficiente de dados com base em critérios especificados, enquanto o filtro `|batch` facilita a divisão de dados em lotes fixos e a tag `{iterateWhile}` oferece a possibilidade de controle de ciclo mais complexo com condições.
+Cada uma dessas tags oferece opções específicas para trabalhar com dados, tornando-as ferramentas indispensáveis para a exibição dinâmica e estruturada de informações nos modelos Latte.
+
+
+Filtro e função `group` .[#toc-filter-and-function-group]
+=========================================================
+
+Imagine uma tabela de banco de dados `items` com itens divididos em categorias:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Maçã
+| 2 | 1 | Banana
+| 3 | 2 | PHP
+| 4 | 3 | Verde
+| 5 | 3 | Vermelho
+| 6 | 3 | Azul
+
+Uma lista simples de todos os itens usando um modelo Latte teria a seguinte aparência:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Entretanto, se quisermos que os itens sejam organizados em grupos por categoria, precisaremos dividi-los de modo que cada categoria tenha sua própria lista. O resultado seria o seguinte:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+A tarefa pode ser resolvida de forma fácil e elegante usando `|group`. Especificamos `categoryId` como parâmetro, o que significa que os itens serão divididos em matrizes menores com base no valor de `$item->categoryId` (se `$item` fosse uma matriz, usaríamos `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+O filtro também pode ser usado como uma função no Latte, o que nos dá uma sintaxe alternativa: `{foreach group($items, categoryId) ...}`.
+
+Se você quiser agrupar itens de acordo com critérios mais complexos, poderá usar uma função no parâmetro filter. Por exemplo, o agrupamento de itens pelo tamanho do nome teria a seguinte aparência:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+É importante observar que `$categoryItems` não é uma matriz comum, mas um objeto que se comporta como um iterador. Para acessar o primeiro item do grupo, você pode usar a função [`first()` |latte:functions#first] função.
+
+Essa flexibilidade no agrupamento de dados torna o `group` uma ferramenta excepcionalmente útil para apresentar dados em modelos Latte.
+
+
+Loops aninhados .[#toc-nested-loops]
+------------------------------------
+
+Digamos que tenhamos uma tabela de banco de dados com outra coluna `subcategoryId` que define subcategorias para cada item. Queremos exibir cada categoria principal em uma lista `<ul>` e cada subcategoria em uma lista aninhada `<ol>` lista aninhada:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Conexão com o banco de dados Nette .[#toc-connection-with-nette-database]
+-------------------------------------------------------------------------
+
+Vamos mostrar como usar efetivamente o agrupamento de dados em combinação com o Nette Database. Suponha que estejamos trabalhando com a tabela `items` do exemplo inicial, que está conectada por meio da coluna `categoryId` a esta tabela `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Frutas |
+| 2 | Idiomas |
+| 3 | Cores |
+
+Carregamos os dados da tabela `items` usando o comando `$items = $db->table('items')` do Nette Database Explorer. Durante a iteração desses dados, temos a oportunidade não apenas de acessar atributos como `$item->name` e `$item->categoryId`, mas, graças à conexão com a tabela `categories`, também à linha relacionada nela por meio de `$item->category`. Essa conexão pode demonstrar usos interessantes:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Nesse caso, usamos o filtro `|group` para agrupar pela linha conectada `$item->category`, não apenas pela coluna `categoryId`. Isso nos dá o `ActiveRow` da categoria dada na chave variável, o que nos permite exibir diretamente seu nome usando `{$category->name}`. Esse é um exemplo prático de como o agrupamento pode simplificar os modelos e facilitar o manuseio de dados.
+
+
+Filtro `|batch` .[#toc-filter-batch]
+====================================
+
+O filtro permite que você divida uma lista de elementos em grupos com um número predeterminado de elementos. Esse filtro é ideal para situações em que você deseja apresentar dados em vários grupos menores, por exemplo, para maior clareza ou organização visual na página.
+
+Imagine que temos uma lista de itens e queremos exibi-los em listas, cada uma contendo no máximo três itens. O uso do filtro `|batch` é muito prático nesse caso:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+Neste exemplo, a lista `$items` é dividida em grupos menores, cada grupo (`$batch`) contendo até três itens. Cada grupo é então exibido em uma lista `<ul>` lista separada.
+
+Se o último grupo não contiver elementos suficientes para atingir o número desejado, o segundo parâmetro do filtro permite que você defina com o que esse grupo será complementado. Isso é ideal para alinhar esteticamente elementos em que uma linha incompleta pode parecer desordenada.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Tag `{iterateWhile}` .[#toc-tag-iteratewhile]
+=============================================
+
+Demonstraremos as mesmas tarefas que abordamos com o filtro `|group` usando a tag `{iterateWhile}`. A principal diferença entre as duas abordagens é que `group` primeiro processa e agrupa todos os dados de entrada, enquanto `{iterateWhile}` controla o progresso dos ciclos com condições, de modo que a iteração ocorre sequencialmente.
+
+Primeiro, desenhamos uma tabela com categorias usando iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Enquanto `{foreach}` marca a parte externa do ciclo, ou seja, desenhar listas para cada categoria, a tag `{iterateWhile}` marca a parte interna, ou seja, itens individuais.
+A condição na tag end diz que a repetição continuará enquanto o elemento atual e o próximo pertencerem à mesma categoria (`$iterator->nextValue` é o [próximo item |/tags#$iterator]).
+
+Se a condição fosse sempre atendida, todos os elementos seriam desenhados no ciclo interno:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+O resultado terá a seguinte aparência:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Qual é a utilidade do iterateWhile dessa forma? Quando a tabela estiver vazia e não contiver elementos, nenhum `<ul></ul>` é impresso.
+
+Se especificarmos a condição na tag de abertura `{iterateWhile}`, o comportamento muda: a condição (e a transição para o próximo elemento) é executada no início do ciclo interno, não no final.
+Assim, enquanto você sempre entra em `{iterateWhile}` sem condições, você entra em `{iterateWhile $cond}` somente quando a condição `$cond` é atendida. E, ao mesmo tempo, o próximo elemento é gravado em `$item`.
+
+Isso é útil, por exemplo, em uma situação em que queremos renderizar o primeiro elemento em cada categoria de forma diferente, assim:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Modificamos o código original de modo que primeiro renderizamos o primeiro item e, em seguida, no ciclo interno `{iterateWhile}`, renderizamos os outros itens da mesma categoria:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Em um ciclo, podemos criar vários loops internos e até mesmo aninhá-los. Dessa forma, as subcategorias poderiam ser agrupadas, por exemplo.
+
+Suponha que a tabela tenha outra coluna `subcategoryId` e que, além de cada categoria estar em uma coluna separada, cada subcategoria esteja em uma coluna separada. `<ul>`cada subcategoria em um `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/pt/cookbook/iteratewhile.texy b/latte/pt/cookbook/iteratewhile.texy
deleted file mode 100644
index ca62ed411c..0000000000
--- a/latte/pt/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Tudo o que você sempre quis saber sobre {alfabetizar-assim}
-***********************************************************
-
-.[perex]
-A etiqueta `{iterateWhile}` é adequada para vários truques em ciclos anteriores.
-
-Suponha que tenhamos a seguinte tabela de banco de dados, onde os itens são divididos em categorias:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Naturalmente, desenhar itens em um laço na frente como uma lista é fácil:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Mas o que fazer se você quiser apresentar cada categoria em uma lista separada? Em outras palavras, como resolver a tarefa de agrupar itens de uma lista linear em um ciclo foreach. A saída deve se parecer com isto:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Mostraremos a facilidade e a elegância com que a tarefa pode ser resolvida com iteração:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Enquanto `{foreach}` marca a parte externa do ciclo, ou seja, o desenho de listas para cada categoria, as tags `{iterateWhile}` indicam a parte interna, ou seja, os itens individuais.
-A condição na etiqueta final diz que a repetição continuará enquanto o elemento atual e o próximo elemento pertencerem à mesma categoria (`$iterator->nextValue` é o [próximo item |/tags#$iterator]).
-
-Se a condição for sempre preenchida, então todos os elementos são desenhados no ciclo interno:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-O resultado será o seguinte:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-De que serve tal uso da iteração enquanto? De que forma difere da solução que mostramos logo no início deste tutorial? A diferença é que se a tabela estiver vazia e não contiver nenhum elemento, ela não irá tornar vazia `<ul></ul>`.
-
-
-Solução Sem `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-------------------------------------------------------------------
-
-Se resolvêssemos a mesma tarefa com construções completamente básicas de sistemas de modelos, por exemplo em Twig, Blade ou PHP puro, a solução seria algo parecido com isto:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* abriremos uma nova lista *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-No entanto, este código é incompreensível e pouco intuitivo. A conexão entre as tags HTML de abertura e fechamento não é clara em absoluto. Não é clara à primeira vista, se houver um erro. E requer variáveis auxiliares como `$prevCatId`.
-
-Em contraste, a solução com `{iterateWhile}` é limpa, clara, não necessita de variáveis auxiliares e é infalível.
-
-
-Condição na Etiqueta de Fechamento .[#toc-condition-in-the-closing-tag]
------------------------------------------------------------------------
-
-Se especificarmos uma condição na etiqueta de abertura `{iterateWhile}`, o comportamento muda: a condição (e o avanço para o próximo elemento) é executada no início do ciclo interno, não no final.
-Assim, enquanto `{iterateWhile}` sem condição é sempre inserido, `{iterateWhile $cond}` é inserido somente quando a condição `$cond` é cumprida. Ao mesmo tempo, o seguinte elemento é escrito para `$item`.
-
-Isto é útil, por exemplo, em uma situação em que você quer renderizar o primeiro elemento de cada categoria de uma maneira diferente, como por exemplo:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Vamos modificar o código original, primeiro desenhamos um item e depois itens adicionais da mesma categoria no laço interno `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Laços aninhados .[#toc-nested-loops]
-------------------------------------
-
-Podemos criar vários loops internos em um ciclo e até mesmo aninhá-los. Desta forma, por exemplo, as subcategorias poderiam ser agrupadas.
-
-Suponha que haja outra coluna na tabela `subCatId` e que, além de cada categoria estar em uma `<ul>`cada subcategoria estará em uma subcategoria separada `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtro |batch .[#toc-filter-batch]
-----------------------------------
-
-O agrupamento de itens lineares também é fornecido por um filtro `batch`, em lotes com um número fixo de elementos:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Ela pode ser substituída por iteração, enquanto que, como se segue:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/pt/cookbook/passing-variables.texy b/latte/pt/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..8f922f1144
--- /dev/null
+++ b/latte/pt/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Passagem de variáveis entre modelos
+***********************************
+
+Este guia explica como as variáveis são passadas entre modelos no Latte usando várias tags, como `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}`, entre outras. Você também aprenderá a trabalhar com variáveis nas tags `{block}` e `{define}` e a finalidade da tag `{parameters}`.
+
+
+Tipos de variáveis .[#toc-types-of-variables]
+---------------------------------------------
+As variáveis no Latte podem ser divididas em três categorias com base em como e onde são definidas:
+
+**Variáveis de entrada** são aquelas que são passadas para o modelo de fora, por exemplo, de um script PHP ou usando uma tag como `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Variáveis circundantes** são variáveis existentes no local de uma tag específica. Elas incluem todas as variáveis de entrada e outras variáveis criadas usando tags como `{var}`, `{default}`, ou dentro de um loop `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Variáveis explícitas** são aquelas especificadas diretamente em uma tag e enviadas ao modelo de destino.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+A tag `{block}` é usada para definir blocos de código reutilizáveis que podem ser personalizados ou estendidos em modelos herdados. As variáveis circundantes definidas antes do bloco estão disponíveis dentro do bloco, mas quaisquer alterações nas variáveis são refletidas somente dentro desse bloco.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+A tag `{define}` é usada para criar blocos que são renderizados somente quando chamados usando `{include}`. As variáveis disponíveis nesses blocos dependem do fato de os parâmetros terem sido especificados na definição. Se os parâmetros forem especificados, somente esses parâmetros estarão acessíveis. Caso contrário, todas as variáveis de entrada do modelo em que os blocos estão definidos estarão acessíveis.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+A tag `{parameters}` é usada para declarar explicitamente as variáveis de entrada esperadas no início do modelo. Dessa forma, você pode documentar facilmente as variáveis esperadas e seus tipos de dados. Também é possível definir valores padrão.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+A tag `{include file}` é usada para inserir um modelo inteiro. Esse modelo recebe tanto as variáveis de entrada do modelo em que a tag é usada quanto as variáveis definidas explicitamente. No entanto, o modelo de destino pode limitar o escopo usando `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Ao inserir um bloco definido no mesmo modelo, todas as variáveis circundantes e explicitamente definidas são passadas para ele:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+Neste exemplo, as variáveis `$name` e `$age` são passadas para o bloco `blockName`. O mesmo comportamento se aplica a `{include parent}`.
+
+Ao inserir um bloco de outro modelo, somente as variáveis de entrada e as variáveis explicitamente definidas são transmitidas. As variáveis ao redor não estão automaticamente disponíveis.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` ou `{extends}`
+-------------------------
+Essas tags definem um layout para o qual são passadas as variáveis de entrada do modelo filho e as variáveis criadas no código antes dos blocos:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Template `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+A tag `{embed}` é semelhante à tag `{include}`, mas permite incorporar blocos ao modelo. Ao contrário da `{include}`, somente as variáveis declaradas explicitamente são transmitidas:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+Neste exemplo, o modelo `menu.latte` tem acesso apenas à variável `$items`.
+
+Por outro lado, os blocos dentro de `{embed}` têm acesso a todas as variáveis ao redor:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+A tag `{import}` é usada para carregar blocos de outros modelos. Tanto as variáveis de entrada quanto as explicitamente declaradas são passadas para os blocos importados.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+A tag `{sandbox}` isola o modelo para processamento seguro. As variáveis são passadas exclusivamente de forma explícita.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/pt/creating-extension.texy b/latte/pt/creating-extension.texy
index 327d9059d7..8c31cc2c3f 100644
--- a/latte/pt/creating-extension.texy
+++ b/latte/pt/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// a parsing function that just creates a node for now
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Se estiver criando uma nova tag para o Latte, é aconselhável criar uma classe de nó dedicada a ela, que a representará na árvore AST (veja a classe `ForeachNode` no exemplo acima). Em alguns casos, você pode achar útil a classe de nó auxiliar trivial [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], que permite que você passe o corpo do método `print()` e a lista de nós tornados acessíveis pelo método `getIterator()` como parâmetros do construtor:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Passes de Compilador .[#toc-compiler-passes]
 ============================================
 
diff --git a/latte/pt/develop.texy b/latte/pt/develop.texy
index 88d9e11d82..e2ba521258 100644
--- a/latte/pt/develop.texy
+++ b/latte/pt/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Local .[#toc-locale]{data-version:3.0.18}
+=========================================
+
+O Latte permite que você defina a localidade, o que afeta a formatação de números, datas e classificação. Ele é definido usando o método `setLocale()`. O identificador de localidade segue o padrão de tag de idioma da IETF, que usa a extensão PHP `intl`. Ele consiste em um código de idioma e possivelmente um código de país, por exemplo, `en_US` para inglês nos Estados Unidos, `de_DE` para alemão na Alemanha, etc.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+A configuração de localidade afeta os filtros [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] e [bytes |filters#bytes].
+
+.[note]
+Requer a extensão PHP `intl`. A configuração no Latte não afeta a configuração global de localidade no PHP.
+
+
 Modo estrito .[#toc-strict-mode]{data-version:3.0.8}
 ====================================================
 
@@ -274,16 +290,25 @@ Se você usa etiquetas personalizadas, crie também seu Linter personalizado, po
 // digite o caminho real para o arquivo autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// adicione extensões individuais aqui
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// adicione suas extensões individuais aqui
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Como alternativa, você pode passar seu próprio objeto `Latte\Engine` para o Linter:
+
+```php
+$latte = new Latte\Engine;
+// Aqui configuramos o objeto $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Carregando modelos a partir de uma corda .[#toc-loading-templates-from-a-string]
 ================================================================================
diff --git a/latte/pt/extending-latte.texy b/latte/pt/extending-latte.texy
index a20cb5cfc3..5e4fd40609 100644
--- a/latte/pt/extending-latte.texy
+++ b/latte/pt/extending-latte.texy
@@ -68,6 +68,16 @@ Como você pode ver, a função recebe o lado esquerdo do filtro antes do tubo `
 
 Naturalmente, a função que representa o filtro pode aceitar qualquer número de parâmetros, e parâmetros variáveis também são suportados.
 
+Se o filtro retornar uma cadeia de caracteres em HTML, você poderá marcá-la para que o Latte não a escape automaticamente (e, portanto, duplamente). Isso evita a necessidade de especificar `|noescape` no modelo.
+A maneira mais fácil é envolver a cadeia de caracteres em um objeto `Latte\Runtime\Html`. A outra maneira é usar o [Contextual Filters |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+Nesse caso, o filtro deve garantir o escape correto dos dados.
+
 
 Filtros que utilizam a classe .[#toc-filters-using-the-class]
 -------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// mudar o tipo de conteúdo para HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/pt/filters.texy b/latte/pt/filters.texy
index 29bc3d8f7d..e495dd16be 100644
--- a/latte/pt/filters.texy
+++ b/latte/pt/filters.texy
@@ -11,14 +11,16 @@ Os filtros são funções que mudam ou formatam os dados para um formulário que
 | `bytes` | [formatos em bytes |#bytes]
 | `clamp` | [valor dos grampos para a faixa |#clamp]
 | `dataStream` | [Conversão do protocolo Data URI |#datastream]
-| `date` | [formatos data |#date]
+| `date` | [formata a data e a hora |#date]
 | `explode` | [divide um fio pelo delimitador dado |#explode]
 | `first` | [devolve o primeiro elemento de matriz ou caráter de cadeia |#first]
+| `group` | [agrupa dados de acordo com vários critérios |#group]
 | `implode` | [junta um conjunto a um cordão |#implode]
 | `indent` | [traça o texto da esquerda com o número de abas |#indent]
 | `join` | [junta um conjunto a um cordão |#implode]
 | `last` | [retorna o último elemento de matriz ou caráter de cadeia |#last]
 | `length` | [devolve o comprimento de um fio ou matriz |#length]
+| `localDate` | [formata a data e a hora de acordo com a localidade |#localDate]
 | `number` | [número de formatos |#number]
 | `padLeft` | [completa o cordel a dado comprimento a partir da esquerda |#padLeft]
 | `padRight` | [completa o cordel a dado comprimento a partir da direita |#padRight]
@@ -118,8 +120,8 @@ Filtros .[#toc-filters]
 =======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filtro que simplifica a listagem de dados lineares na forma de uma tabela. Ele retorna uma matriz com o determinado número de itens. Se você fornecer um segundo parâmetro, este é usado para preencher os itens em falta na última linha.
 
 ```latte
@@ -152,6 +154,8 @@ Impressões:
 </table>
 ```
 
+Consulte também a tag [group |#group] e [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Insere quebras de linha HTML antes de todas as novas linhas.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formata um tamanho em bytes de forma legível para o ser humano.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formata o tamanho em bytes em um formato legível por humanos. Se a [localidade |develop#locale] estiver definida, serão usados os separadores decimais e de milhar correspondentes.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formata um tamanho em bytes de forma legível para o ser humano.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Arredonda um número até uma determinada precisão.
 
 ```latte
@@ -203,8 +207,8 @@ Impõe a higienização do URL. Verifica se a variável contém uma URL da web (
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Impressões:
@@ -217,8 +221,8 @@ Impressões:
 Veja também [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Retorna o valor fixado para a faixa inclusiva de min e max.
 
 ```latte
@@ -228,14 +232,14 @@ Retorna o valor fixado para a faixa inclusiva de min e max.
 Também existe como [função |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Converte o conteúdo para o esquema URI de dados. Pode ser usado para inserir imagens em HTML ou CSS sem a necessidade de vincular arquivos externos.
 
 Vamos ter uma imagem em uma variável `$img = Image::fromFile('obrazek.gif')`, então
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Impressões, por exemplo:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Requer extensão PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Retorna uma data no formato dado usando as opções de [php:strftime] ou [php:date] funções PHP. O filtro recebe uma data como um carimbo de tempo UNIX, uma string ou um objeto do tipo `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formata a data e a hora de acordo com a máscara usada pela função PHP [php:date]. O filtro aceita a data no formato de carimbo de data/hora do UNIX, como uma cadeia de caracteres ou como um objeto `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Consulte também [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Escapa a uma variável para ser usada como parâmetro na URL.
 Veja também [consulta |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Divide um fio pelo delimitador dado e retorna um conjunto de fios. Alias para `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Devolve o primeiro elemento de matriz ou caráter de corda:
 Ver também [último |#last], [aleatório |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Arredonda um número para uma determinada precisão.
 
 ```latte
@@ -330,8 +335,27 @@ Converte uma primeira letra de valor em maiúsculas. Requer extensão PHP `mbstr
 Veja também [capitalizar |#capitalize], [inferior |#lower], [superior |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+O filtro agrupa os dados de acordo com diferentes critérios.
+
+Neste exemplo, as linhas da tabela são agrupadas pela coluna `categoryId`. O resultado é uma matriz de matrizes em que a chave é o valor da coluna `categoryId`. Leia as [instruções detalhadas |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Consulte também [batch |#batch], a função [group |functions#group] e a tag [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Retorna um fio que é a concatenação das cordas na matriz. Alias para `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Você também pode usar um pseudônimo `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Indica um texto da esquerda por um determinado número de abas ou outros caracteres que especificamos no segundo argumento opcional. As linhas em branco não são indentadas.
 
 ```latte
@@ -396,6 +420,68 @@ Retorna o comprimento de um fio ou matriz.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formata a data e a hora de acordo com a [localidade |develop#locale], garantindo a exibição consistente e localizada dos dados de hora em diferentes idiomas e regiões. O filtro aceita a data como um carimbo de data/hora UNIX, uma cadeia de caracteres ou um objeto `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Se você usar o filtro sem nenhum parâmetro, ele emitirá a data no nível de formato longo, conforme explicado mais adiante.
+
+**a) Usando o formato**
+
+O parâmetro `format` descreve quais componentes de tempo devem ser exibidos. Ele usa códigos de letras, em que o número de repetições afeta a largura da saída:
+
+| Year | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Mês | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `ago.` / `agosto`
+| Dia | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `domingo` / `domingo`
+| Hora | `j` / `H` / `h` | preferencial / 24 horas / 12 horas
+| Minuto | `m` / `mm` | `5` / `05` <small>(2 dígitos quando combinado com segundos)</small>
+| Segundo | `s` / `ss` | `8` / `08` <small>(2 dígitos quando combinados com os minutos)</small>
+
+A ordem dos códigos no formato não importa, pois a ordem dos componentes será exibida de acordo com as convenções da localidade. Portanto, o formato é independente da localidade. Por exemplo, o formato `yyyyMMMMd` na localidade `en_US` gera `April 15, 2024`, enquanto na localidade `cs_CZ` gera `15. dubna 2024`:
+
+| locale:  | pt-PT | en_US
+|---
+| `format: 'dMy'` | 10/08/2024 | 8/10/2024
+| `format: 'yM'` | 08/2024 | 8/2024
+| `format: 'yyyyMMMM'` | agosto de 2024 | August 2024
+| `format: 'MMMM'` | agosto | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 da tarde | 5:54 PM
+
+
+**b) Uso de estilos predefinidos**
+
+Os parâmetros `date` e `time` determinam o nível de detalhe da exibição de data e hora. Você pode escolher entre vários níveis: `full`, `long`, `medium`, `short`. Você pode exibir apenas a data, apenas a hora ou ambas:
+
+| locale:  | pt-PT | en_US
+|---
+| `date: short` | 23/01/78 | 1/23/78
+| `date: medium` | 23/01/1978 | Jan 23, 1978
+| `date: long` | 23 de janeiro de 1978 | January 23, 1978
+| `date: full` | segunda-feira, 23 de janeiro de 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23/01/78, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23/01/1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 de janeiro de 1978 às 08:30 | January 23, 1978 at 8:30 AM
+
+Para a data, você também pode usar o prefixo `relative-` (por exemplo, `relative-short`), que para datas próximas ao presente exibirá `yesterday`, `today`, ou `tomorrow`; caso contrário, será exibido da maneira padrão.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Consulte também [date |#date].
+
+
 lower .[filter]
 ---------------
 Converte um valor para minúsculas. Requer extensão PHP `mbstring`.
@@ -416,8 +502,8 @@ Se o link usa um esquema diferente, como `javascript:` ou `data:`, e você tem c
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Impressões:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 O mau uso do filtro `noescape` pode levar a uma vulnerabilidade XSS! Nunca o use a menos que você esteja **absolutamente seguro** do que está fazendo e que o fio que você está imprimindo vem de uma fonte confiável.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formata um número para um determinado número de casas decimais. Você também pode especificar um caractere do separador de casas decimais e de milhares.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formata um número com um número especificado de casas decimais. Se a [localidade |develop#locale] estiver definida, serão usados os separadores decimais e de milhar correspondentes.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Formata um número para um determinado número de casas decimais. Você também
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+O parâmetro `format` permite que você defina a aparência dos números exatamente de acordo com suas necessidades. Ele requer uma [localidade |develop#locale] definida. O formato consiste em vários caracteres especiais, cuja descrição completa pode ser encontrada na documentação "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> dígito obrigatório, sempre exibido, mesmo que seja zero
+- `#` dígito opcional, exibido somente se o número tiver um dígito naquele local
+- `@` dígito significativo, ajuda a exibir o número com um determinado número de dígitos significativos
+- `.` marca onde o separador decimal deve estar (vírgula ou ponto, dependendo da localidade)
+- `,` usado para separar grupos de dígitos, geralmente milhares
+- `%` multiplica o número por 100 e adiciona o sinal de porcentagem
+
+Vamos dar uma olhada em alguns exemplos. No primeiro exemplo, duas casas decimais são obrigatórias; no segundo, são opcionais. O terceiro exemplo mostra o preenchimento com zeros em ambos os lados, e o quarto exibe apenas os dígitos existentes:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Os dígitos significativos determinam quantos dígitos, independentemente do ponto decimal, devem ser exibidos, arredondando o número, se necessário:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Uma maneira fácil de exibir um número como porcentagem. O número é multiplicado por 100 e o sinal `%` é adicionado:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Podemos definir um formato diferente para números positivos e negativos, separados por um caractere `;`. Dessa forma, por exemplo, os números positivos podem ser exibidos com um sinal `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Lembre-se de que a aparência real dos números pode variar de acordo com as configurações de localidade. Por exemplo, em alguns países, uma vírgula é usada em vez de um ponto como separador decimal. Esse filtro considera isso automaticamente, portanto, você não precisa se preocupar com isso.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Coloca um cordel a um certo comprimento com outro cordel da esquerda.
 
@@ -472,7 +606,7 @@ Coloca um cordel a um certo comprimento com outro cordel da esquerda.
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Coloca um cordel a um certo comprimento com outro cordel da direita.
 
@@ -514,8 +648,8 @@ Devolve elemento aleatório de matriz ou caráter de corda:
 Ver também [primeiro |#first], [último |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Repete a seqüência x-vezes.
 
 ```latte
@@ -523,7 +657,7 @@ Repete a seqüência x-vezes.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Substitui todas as ocorrências da cadeia de busca pela cadeia de substituição.
 
@@ -538,7 +672,7 @@ Substituições múltiplas podem ser feitas de uma só vez:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Substitui todas as ocorrências de acordo com a expressão regular.
 
@@ -559,8 +693,8 @@ Inverte seqüência ou matriz dada.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Arredonda um número para uma dada precisão.
 
 ```latte
@@ -573,7 +707,7 @@ Arredonda um número para uma dada precisão.
 Veja também [ceil |#ceil], [chão |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Extrai uma fatia de uma matriz ou um fio.
 
@@ -591,9 +725,9 @@ Se o comprimento for dado e for positivo, então a seqüência terá até muitos
 O filtro reordenará e redefinirá as chaves da matriz inteira por padrão. Este comportamento pode ser alterado ajustando preserveKeys para true. As chaves de string são sempre preservadas, independentemente deste parâmetro.
 
 
-sort  .[filter]
----------------
-Filtro que ordena uma matriz e mantém a associação de índices.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+O filtro classifica os elementos de uma matriz ou iterador, preservando suas chaves associativas. Quando uma [localidade |develop#locale] é definida, a classificação segue suas regras, a menos que uma função de comparação personalizada seja especificada.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Array ordenados em ordem inversa.
 {/foreach}
 ```
 
-Você pode passar sua própria função de comparação como um parâmetro:
+Você pode especificar uma função de comparação personalizada para a classificação (o exemplo mostra como inverter a classificação do maior para o menor):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+O filtro `|sort` também permite que você classifique os elementos por chave:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Se você precisar classificar uma tabela por uma coluna específica, poderá usar o parâmetro `by`. O valor `'name'` no exemplo especifica que a classificação será feita por `$row->name` ou `$row['name']`dependendo do fato de `$row` ser uma matriz ou um objeto:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Você também pode definir uma função de retorno de chamada que determina o valor a ser classificado:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+O parâmetro `byKey` pode ser usado da mesma forma.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Converte HTML em texto simples. Ou seja, remove as tags HTML e converte entidade
 O texto simples resultante pode naturalmente conter caracteres que representam tags HTML, por exemplo `'&lt;p&gt;'|stripHtml` é convertido para `<p>`. Nunca envie o texto resultante com `|noescape`, pois isso pode levar a uma vulnerabilidade de segurança.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Extrai uma fatia de um fio. Este filtro foi substituído por uma [fatia de |#slice] filtro.
 
 ```latte
@@ -655,8 +815,8 @@ Extrai uma fatia de um fio. Este filtro foi substituído por uma [fatia de |#sli
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Ela traduz expressões para outros idiomas. Para tornar o filtro disponível, é necessário [instalar um tradutor |develop#TranslatorExtension]. Você também pode usar as [tags para a tradução |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Ela traduz expressões para outros idiomas. Para tornar o filtro disponível, é
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Tire os personagens que lideram e seguem, por padrão, o espaço em branco.
 
 ```latte
@@ -675,7 +835,7 @@ Tire os personagens que lideram e seguem, por padrão, o espaço em branco.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Encurta um fio até o comprimento máximo dado, mas tenta preservar palavras inteiras. Se a cadeia for truncada, acrescenta elipses no final (isto pode ser alterado pelo segundo parâmetro).
 
diff --git a/latte/pt/functions.texy b/latte/pt/functions.texy
index bd63907721..83fad541c2 100644
--- a/latte/pt/functions.texy
+++ b/latte/pt/functions.texy
@@ -9,6 +9,8 @@ Além das funções comuns do PHP, você também pode usá-las em modelos.
 | `divisibleBy`| [verifica se uma variável é divisível por um número |#divisibleBy]
 | `even` | [verifica se o número dado é igual |#even]
 | `first` | [devolve o primeiro elemento de matriz ou caráter de cadeia |#first]
+| `group` | [agrupa dados de acordo com vários critérios |#group]
+| `hasBlock` | [detecta a existência de um bloco |#hasBlock]
 | `last` | [retorna o último elemento de matriz ou caráter de cadeia |#last]
 | `odd` | [verifica se o número dado é ímpar |#odd]
 | `slice` | [extrai uma fatia de uma matriz ou um fio |#slice]
@@ -73,8 +75,8 @@ Verifica se o número dado é igual.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Devolve o primeiro elemento de matriz ou caráter de corda:
 
 ```latte
@@ -85,6 +87,36 @@ Devolve o primeiro elemento de matriz ou caráter de corda:
 Ver também [por último |#last], [filtrar primeiro |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Essa função agrupa dados de acordo com diferentes critérios.
+
+Neste exemplo, as linhas da tabela são agrupadas pela coluna `categoryId`. O resultado é uma matriz de campos em que a chave é o valor da coluna `categoryId`. Leia as [instruções detalhadas |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Consulte também [grupo de |filters#group] filtros.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Verifica se o bloco com o nome especificado existe:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Consulte também [verificação de existência de bloco |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Retorna o último elemento de matriz ou caráter de corda:
@@ -106,8 +138,8 @@ Verifica se o número dado é estranho.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Extrai uma fatia de uma matriz ou um fio.
 
 ```latte
diff --git a/latte/pt/recipes.texy b/latte/pt/recipes.texy
index fa24fa5399..1e66873211 100644
--- a/latte/pt/recipes.texy
+++ b/latte/pt/recipes.texy
@@ -9,7 +9,7 @@ Escreva os modelos em um editor ou IDE que tenha suporte para Latte. Será muito
 
 - NetBeans IDE tem suporte integrado
 - PhpStorm: instale o [plugin Latte |https://plugins.jetbrains.com/plugin/7457-latte] `Settings > Plugins > Marketplace`
-- Código VS: busca no marcador de busca do plugin "Nette Latte + Neon
+- Código VS: procure no markerplace pelo plug-in [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ou [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Texto Sublime 3: em Package Control find and install `Nette` e selecione Latte in `View > Syntax`
 - em editores antigos usam Smarty highlighting para arquivos .latte
 
diff --git a/latte/pt/safety-first.texy b/latte/pt/safety-first.texy
index e9b0a37e5c..572c4a3732 100644
--- a/latte/pt/safety-first.texy
+++ b/latte/pt/safety-first.texy
@@ -351,7 +351,7 @@ Latte verifica automaticamente se a variável utilizada nos atributos `src` ou `
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Escreve:
diff --git a/latte/pt/syntax.texy b/latte/pt/syntax.texy
index 17a85222fd..e9c51124b7 100644
--- a/latte/pt/syntax.texy
+++ b/latte/pt/syntax.texy
@@ -98,7 +98,7 @@ Impressões:
 Ou usando o prefixo `tag-`, a funcionalidade é aplicada apenas nas tags HTML:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Dependendo do valor da variável `$url`, isto será impresso:
@@ -155,6 +155,20 @@ Ou diretamente sobre o valor (em combinação com [`{=expr}` | https://latte.net
 ```
 
 
+Tags HTML dinâmicas .[#toc-dynamic-html-tags]
+=============================================
+
+O Latte oferece suporte a tags HTML dinâmicas, que são úteis quando você precisa de flexibilidade nos nomes das tags:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Por exemplo, o código acima pode gerar `<h1>Heading</h1>` ou `<h2>Heading</h2>` dependendo do valor da variável `$level`. As tags HTML dinâmicas no Latte devem ser sempre emparelhadas. Sua alternativa é a [n:tag |tags#n:tag].
+
+Como o Latte é um sistema de modelos seguro, ele verifica se o nome da tag resultante é válido e não contém valores indesejados ou maliciosos. Ele também garante que o nome da tag final seja sempre o mesmo que o nome da tag de abertura.
+
+
 Comentários .[#toc-comments]
 ============================
 
diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy
index ded11b8ed1..8bce51f23a 100644
--- a/latte/pt/tags.texy
+++ b/latte/pt/tags.texy
@@ -16,6 +16,7 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte.
 | `{ifset}`... `{elseifset}`... `{/ifset}`... | [condição se começar |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [testar se houve uma mudança |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [interruptor de condição |#switch-case-default]
+| `n:else` | [conteúdo alternativo para condições |#n:else]
 
 .[table-latte-tags language-latte]
 |## Loops
@@ -97,8 +98,8 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte.
 | `{link}` | [imprime um link |application:creating-links#In the Presenter Template]
 | `{plink}` | [imprime um link para um apresentador |application:creating-links#In the Presenter Template]
 | `{control}` | [imprime um componente |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [um trecho de modelo que pode ser enviado pela AJAX |application:ajax#tag-snippet]
-| `{snippetArea}` | envelope de snippets
+| `{snippet}`... `{/snippet}` | [um trecho de modelo que pode ser enviado pela AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [envelope de snippets |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [caches uma seção modelo |caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte.
 | `{input}` | [imprime um elemento de entrada do formulário |forms:rendering#label-input]
 | `{inputError}` | [imprime mensagem de erro para o elemento de entrada do formulário |forms:rendering#inputError]
 | `n:name` | [ativa um elemento de entrada HTML |forms:rendering#n:name]
-| `{formPrint}` | [gera o projeto do formulário Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [imprime a classe PHP para dados de formulário |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [versão parcial da forma |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [tornando o recipiente do formulário |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Você sabe que pode adicionar o prefixo `tag-` aos n:attributes? Então a condi
 Legal.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Se você escrever a condição `{if} ... {/if}` na forma de um [atributo n:attribute |syntax#n:attributes], terá a opção de especificar um ramo alternativo usando `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+O atributo `n:else` também pode ser usado em conjunto com [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], e [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Veja também [`{ifset block}` |template-inheritance#checking-block-existence]
 Use a condição `{ifset $var}` para determinar se uma variável (ou múltiplas variáveis) existe e tem um valor não-nulo. Na verdade é o mesmo que `if (isset($var))` em PHP. Como qualquer tag de par, isto pode ser escrito na forma de [n:atributo |syntax#n:attributes], então vamos mostrá-lo no exemplo:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Isso é muito prático, não é?
 `{iterateWhile}`
 ----------------
 
-Ele simplifica o agrupamento de dados lineares durante a iteração em um laço frontal, realizando a iteração em um laço aninhado, desde que a condição seja atendida. [Leia as instruções no livro de receitas |cookbook/iteratewhile].
+Simplifica o agrupamento de dados lineares durante a iteração em um loop foreach, iterando em um loop aninhado até que uma condição seja satisfeita. [Leia as instruções detalhadas |cookbook/grouping].
 
 Também pode substituir elegantemente `{first}` e `{last}` no exemplo acima:
 
@@ -489,6 +501,8 @@ Também pode substituir elegantemente `{first}` e `{last}` no exemplo acima:
 {/foreach}
 ```
 
+Consulte também filtros de [lote |filters#batch] e [de grupo |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Se `$heading === null`, o `<h1>` é impresso sem alterações. Caso contrário,
 <h3 class="main">...</h3>
 ```
 
+Como o Latte é um sistema de modelos seguro, ele verifica se o novo nome da tag é válido e não contém valores indesejados ou maliciosos.
+
 
 n:secontente .[#toc-n-ifcontent]
 --------------------------------
diff --git a/latte/pt/template-inheritance.texy b/latte/pt/template-inheritance.texy
index 387f5a8b90..2752e1b8bc 100644
--- a/latte/pt/template-inheritance.texy
+++ b/latte/pt/template-inheritance.texy
@@ -132,7 +132,7 @@ Aqui estão algumas dicas para trabalhar com a herança de layout:
 
 - Se você usar `{layout}` em um template, ele deve ser a primeira etiqueta do template nesse template.
 
-- O layout pode ser [pesquisado automaticamente |develop#automatic-layout-lookup] (como nos [apresentadores |application:templates#search-for-templates]). Nesse caso, se o modelo não tiver um layout, ele indicará isso com a tag `{layout none}`.
+- O layout pode ser [pesquisado automaticamente |develop#automatic-layout-lookup] (como nos [apresentadores |application:templates#Template Lookup]). Nesse caso, se o modelo não tiver um layout, ele indicará isso com a tag `{layout none}`.
 
 - A tag `{layout}` tem o pseudônimo `{extends}`.
 
@@ -396,6 +396,14 @@ Você pode usar uma variável ou qualquer expressão em PHP como o nome do bloco
 {/ifset}
 ```
 
+A existência de blocos também é retornada pela função [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Dicas .[#toc-tips]
 ------------------
@@ -415,7 +423,7 @@ Aqui estão algumas dicas para trabalhar com blocos:
 Reutilização Horizontal `{import}` .{toc: Horizontal Reuse}
 ===========================================================
 
-A reutilização horizontal é um terceiro mecanismo de reusabilidade e herança em Latte. Ele permite carregar blocos de outros modelos. É semelhante à criação de um arquivo PHP com funções de ajuda ou uma característica.
+A reutilização horizontal é o terceiro mecanismo de reutilização e herança no Latte. Ele permite carregar blocos de outros modelos. É semelhante a criar um arquivo com funções auxiliares em PHP e depois carregá-lo usando `require`.
 
 Embora a herança de layout de modelo seja um dos recursos mais avançados do Latte, ela é limitada à herança simples - um modelo só pode estender um outro modelo. A reutilização horizontal é uma forma de obter herança múltipla.
 
@@ -447,7 +455,7 @@ A tag `{import}` deve ser a primeira tag modelo após `{layout}`. O nome do temp
 
 Você pode usar tantas declarações `{import}` quantas quiser em qualquer modelo dado. Se dois gabaritos importados definirem o mesmo bloco, o primeiro ganha. Entretanto, a maior prioridade é dada ao modelo principal, que pode sobrescrever qualquer bloco importado.
 
-Todos os blocos sobrepostos podem ser incluídos gradualmente, inserindo-os como [bloco pai |#parent block]:
+O conteúdo dos blocos sobrescritos pode ser preservado inserindo-se o bloco da mesma forma que um [bloco pai |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/ro/@left-menu.texy b/latte/ro/@left-menu.texy
index fd0ebd9728..1a9b29d8a5 100644
--- a/latte/ro/@left-menu.texy
+++ b/latte/ro/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Noțiuni introductive |Guide]
 - [De ce să folosiți șabloane? |why-use]
-- Concepte
+- Concepte ⚗️
 	- [Siguranța mai întâi |Safety First]
 	- [Moștenirea șablonului |Template Inheritance]
 	- [Sistemul de tipuri |Type System]
 	- [Sandbox |Sandbox]
 
-- Pentru proiectanți
+- Pentru proiectanți 🎨
 	- [Sintaxa |Syntax]
 	- [Etichete |Tags]
 	- [Filtre |Filters]
 	- [Funcții |Functions]
 	- [Sfaturi și trucuri |recipes]
 
-- Pentru dezvoltatori
+- Pentru dezvoltatori 🧮
 	- [Practici pentru dezvoltatori |develop]
 	- [Extinderea Latte |Extending Latte]
 	- [Crearea unei extensii |creating-extension]
 
-- [Carte de bucate |cookbook/@home]
+- [Carte de bucate 💡|cookbook/@home]
 	- [Migrarea de la Twig |cookbook/migration-from-twig]
 	- [... mai mult |cookbook/@home]
 
diff --git a/latte/ro/cookbook/@home.texy b/latte/ro/cookbook/@home.texy
index 6eaa0a78b2..e7379f1d1f 100644
--- a/latte/ro/cookbook/@home.texy
+++ b/latte/ro/cookbook/@home.texy
@@ -4,7 +4,9 @@ Carte de bucate
 .[perex]
 Exemple de coduri și rețete pentru realizarea unor sarcini obișnuite cu Latte.
 
-- [Tot ce ați vrut întotdeauna să știți despre {iterateWhile} |iteratewhile]
+- [Orientări pentru dezvoltatori |/develop]
+- [Transmiterea variabilelor între șabloane |passing-variables]
+- [Tot ce ați vrut întotdeauna să știți despre grupare |grouping]
 - [Cum să scrieți interogări SQL în Latte? |how-to-write-sql-queries-in-latte]
 - [Migrarea de la PHP |migration-from-php]
 - [Migrarea de la Twig |migration-from-twig]
diff --git a/latte/ro/cookbook/grouping.texy b/latte/ro/cookbook/grouping.texy
new file mode 100644
index 0000000000..8f604424d3
--- /dev/null
+++ b/latte/ro/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Tot ceea ce ați vrut să știți întotdeauna despre grupare
+********************************************************
+
+.[perex]
+Atunci când lucrați cu date în șabloane, vă confruntați adesea cu necesitatea de a le grupa sau de a le afișa în mod specific în funcție de anumite criterii. În acest scop, Latte oferă mai multe instrumente puternice.
+
+Filtrul și funcția `|group` permit gruparea eficientă a datelor pe baza unor criterii specificate, în timp ce filtrul `|batch` facilitează împărțirea datelor în loturi fixe, iar eticheta `{iterateWhile}` oferă posibilitatea unui control mai complex al ciclului cu condiții.
+Fiecare dintre aceste etichete oferă opțiuni specifice de lucru cu datele, ceea ce le face instrumente indispensabile pentru afișarea dinamică și structurată a informațiilor în șabloanele Latte.
+
+
+Filtru și funcție `group` .[#toc-filter-and-function-group]
+===========================================================
+
+Imaginați-vă un tabel de bază de date `items` cu articole împărțite în categorii:
+
+| id | categoryId | categoryId | name
+|------------------
+| 1 | 1 | 1 | Apple
+2 | 1 | 1 | Banană
+3 | 2 | 2 | PHP
+4 | 3 | 3 | Verde
+| 5 | 3 | Roșu
+6 | 3 | 3 | Albastru
+
+O listă simplă a tuturor elementelor folosind un șablon Latte ar arăta astfel:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Cu toate acestea, dacă am dori ca articolele să fie organizate în grupuri pe categorii, trebuie să le împărțim astfel încât fiecare categorie să aibă propria listă. Rezultatul ar arăta astfel:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Sarcina poate fi rezolvată ușor și elegant folosind `|group`. Specificăm `categoryId` ca parametru, ceea ce înseamnă că elementele vor fi împărțite în array-uri mai mici pe baza valorii `$item->categoryId` (dacă `$item` ar fi un array, am folosi `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Filtrul poate fi utilizat și ca o funcție în Latte, oferindu-ne o sintaxă alternativă: `{foreach group($items, categoryId) ...}`.
+
+Dacă doriți să grupați elemente în funcție de criterii mai complexe, puteți utiliza o funcție în parametrul de filtrare. De exemplu, gruparea elementelor în funcție de lungimea numelui lor ar arăta în felul următor:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Este important să rețineți că `$categoryItems` nu este o matrice obișnuită, ci un obiect care se comportă ca un iterator. Pentru a accesa primul element din grup, puteți utiliza funcția [`first()` |latte:functions#first] funcție.
+
+Această flexibilitate în gruparea datelor face din `group` un instrument extrem de util pentru prezentarea datelor în șabloanele Latte.
+
+
+Bucle imbricate .[#toc-nested-loops]
+------------------------------------
+
+Să presupunem că avem un tabel de bază de date cu o altă coloană `subcategoryId` care definește subcategoriile pentru fiecare articol. Dorim să afișăm fiecare categorie principală într-o coloană separată `<ul>` și fiecare subcategorie într-o listă separată, iar fiecare subcategorie într-o `<ol>` listă separată:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Conexiune cu baza de date Nette .[#toc-connection-with-nette-database]
+----------------------------------------------------------------------
+
+Să arătăm cum să folosim în mod eficient gruparea datelor în combinație cu Nette Database. Să presupunem că lucrăm cu tabelul `items` din exemplul inițial, care este conectat prin coloana `categoryId` la acest tabel `categories`:
+
+categoryId | categoryId | name |
+|------------|------------|
+1 | Fructe | Fructe |
+| 2 | Limbi |
+| 3 | Culori |
+
+Încărcăm datele din tabelul `items` folosind comanda Nette Database Explorer `$items = $db->table('items')`. În timpul iterației asupra acestor date, avem posibilitatea nu numai de a accesa atribute precum `$item->name` și `$item->categoryId`, ci, datorită conexiunii cu tabelul `categories`, și rândul aferent din acesta prin intermediul `$item->category`. Această conexiune poate demonstra utilizări interesante:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+În acest caz, folosim filtrul `|group` pentru a grupa după rândul conectat `$item->category`, nu doar după coloana `categoryId`. Acest lucru ne oferă `ActiveRow` din categoria dată în cheia variabilă, ceea ce ne permite să afișăm direct numele acesteia folosind `{$category->name}`. Acesta este un exemplu practic al modului în care gruparea poate simplifica șabloanele și facilita manipularea datelor.
+
+
+Filtru `|batch` .[#toc-filter-batch]
+====================================
+
+Filtrul vă permite să împărțiți o listă de elemente în grupuri cu un număr prestabilit de elemente. Acest filtru este ideal pentru situațiile în care doriți să prezentați datele în mai multe grupuri mai mici, de exemplu, pentru o mai bună claritate sau organizare vizuală în pagină.
+
+Imaginați-vă că avem o listă de elemente și dorim să le afișăm în liste, fiecare conținând maximum trei elemente. Utilizarea filtrului `|batch` este foarte practică într-un astfel de caz:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+În acest exemplu, lista `$items` este împărțită în grupuri mai mici, fiecare grup (`$batch`) conținând cel mult trei elemente. Fiecare grup este apoi afișat într-o fereastră separată `<ul>` listă separată.
+
+În cazul în care ultimul grup nu conține suficiente elemente pentru a ajunge la numărul dorit, al doilea parametru al filtrului vă permite să definiți cu ce va fi completat acest grup. Acest lucru este ideal pentru alinierea estetică a elementelor în cazul în care un rând incomplet ar putea părea dezordonat.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Etichetă `{iterateWhile}` .[#toc-tag-iteratewhile]
+==================================================
+
+Vom demonstra aceleași sarcini pe care le-am abordat cu filtrul `|group` folosind eticheta `{iterateWhile}`. Principala diferență între cele două abordări este că `group` procesează și grupează mai întâi toate datele de intrare, în timp ce `{iterateWhile}` controlează progresul ciclurilor cu condiții, astfel încât iterația are loc secvențial.
+
+Mai întâi, desenăm un tabel cu categorii folosind iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+În timp ce `{foreach}` marchează partea exterioară a ciclului, adică desenarea listelor pentru fiecare categorie, eticheta `{iterateWhile}` marchează partea interioară, adică elementele individuale.
+Condiția din tag-ul end spune că repetiția va continua atâta timp cât elementul curent și cel următor aparțin aceleiași categorii (`$iterator->nextValue` este [următorul element |/tags#$iterator]).
+
+Dacă această condiție ar fi întotdeauna îndeplinită, toate elementele ar fi desenate în ciclul interior:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Rezultatul va arăta astfel:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Care este utilizarea iterateWhile în acest mod? Atunci când tabelul este gol și nu conține niciun element, nu este necesară o operațiune de tip "empty `<ul></ul>` este tipărit.
+
+Dacă specificăm condiția în deschiderea etichetei `{iterateWhile}`, comportamentul se schimbă: condiția (și tranziția la următorul element) se realizează la începutul ciclului interior, nu la sfârșitul acestuia.
+Astfel, în timp ce întotdeauna se introduce `{iterateWhile}` fără condiții, se introduce `{iterateWhile $cond}` numai atunci când este îndeplinită condiția `$cond`. Și, în același timp, următorul element este scris în `$item`.
+
+Acest lucru este util, de exemplu, în situația în care dorim să redăm primul element din fiecare categorie în mod diferit, astfel:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Modificăm codul original astfel încât să redăm mai întâi primul element și apoi, în ciclul interior `{iterateWhile}`, să redăm celelalte elemente din aceeași categorie:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+În cadrul unui ciclu, putem crea mai multe bucle interioare și chiar le putem anina. În acest fel, subcategoriile ar putea fi grupate, de exemplu.
+
+Să presupunem că tabelul are o altă coloană `subcategoryId`, și pe lângă faptul că fiecare categorie se află într-o coloană separată `<ul>`, fiecare subcategorie într-o coloană separată `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/ro/cookbook/iteratewhile.texy b/latte/ro/cookbook/iteratewhile.texy
deleted file mode 100644
index 130ce06353..0000000000
--- a/latte/ro/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Tot ce ați vrut să știți despre {iterateWhile}
-**********************************************
-
-.[perex]
-Eticheta `{iterateWhile}` este potrivită pentru diverse trucuri în ciclurile foreach.
-
-Să presupunem că avem următorul tabel de bază de date, în care articolele sunt împărțite în categorii:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Desigur, este ușor să desenezi elementele dintr-o buclă foreach sub forma unei liste:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Dar ce să faceți dacă doriți să redați fiecare categorie într-o listă separată? Cu alte cuvinte, cum să rezolvați sarcina de a grupa elementele dintr-o listă liniară într-un ciclu foreach. Rezultatul ar trebui să arate astfel:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Vă vom arăta cât de ușor și elegant poate fi rezolvată această sarcină cu iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-În timp ce `{foreach}` marchează partea exterioară a ciclului, adică întocmirea listelor pentru fiecare categorie, etichetele `{iterateWhile}` indică partea interioară, adică elementele individuale.
-Condiția din tag-ul end spune că repetiția va continua atâta timp cât elementul curent și cel următor aparțin aceleiași categorii (`$iterator->nextValue` este [elementul următor |/tags#$iterator]).
-
-Dacă condiția este întotdeauna îndeplinită, atunci toate elementele sunt desenate în ciclul interior:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Rezultatul va arăta astfel:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-La ce este bună o astfel de utilizare a iterateWhile? Prin ce diferă de soluția pe care am arătat-o la începutul acestui tutorial? Diferența constă în faptul că, dacă tabelul este gol și nu conține niciun element, nu se va afișa gol `<ul></ul>`.
-
-
-Soluție fără `{iterateWhile}` .[#toc-solution-without-iteratewhile]
--------------------------------------------------------------------
-
-Dacă am rezolva aceeași sarcină cu sisteme de șabloane complet de bază, de exemplu în Twig, Blade sau PHP pur, soluția ar arăta cam așa:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* categoria s-a schimbat *}
-
-		{* închidem pagina anterioară <ul>, dacă nu este primul element *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* vom deschide o nouă listă *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* închidem ultima listă *}
-	</ul>
-{/if}
-```
-
-Cu toate acestea, acest cod este de neînțeles și neintuitiv. Legătura dintre etichetele HTML de deschidere și închidere nu este deloc clară. Nu este clar la prima vedere dacă este vorba de o greșeală. Și este nevoie de variabile auxiliare precum `$prevCatId`.
-
-În schimb, soluția cu `{iterateWhile}` este curată, clară, nu are nevoie de variabile auxiliare și este infailibilă.
-
-
-Condiția din eticheta de închidere .[#toc-condition-in-the-closing-tag]
------------------------------------------------------------------------
-
-Dacă specificăm o condiție în tag-ul de deschidere `{iterateWhile}`, comportamentul se schimbă: condiția (și avansarea la elementul următor) este executată la începutul ciclului interior, nu la sfârșitul acestuia.
-Astfel, în timp ce `{iterateWhile}` fără condiție este introdus întotdeauna, `{iterateWhile $cond}` este introdus doar atunci când este îndeplinită condiția `$cond`. În același timp, următorul element este scris în `$item`.
-
-Acest lucru este util, de exemplu, în situația în care doriți să redați primul element din fiecare categorie într-un mod diferit, cum ar fi:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Să modificăm codul original, desenăm primul element și apoi elementele suplimentare din aceeași categorie în bucla interioară `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Bucle imbricate .[#toc-nested-loops]
-------------------------------------
-
-Putem crea mai multe bucle interioare într-un ciclu și chiar le putem anina. În acest fel, de exemplu, se pot grupa subcategorii.
-
-Să presupunem că există o altă coloană în tabelul `subCatId` și, pe lângă faptul că fiecare categorie se află într-o coloană separată `<ul>`, fiecare subcategorie va fi într-o coloană separată `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtru |batch .[#toc-filter-batch]
-----------------------------------
-
-Gruparea elementelor liniare este, de asemenea, asigurată de un filtru `batch`, în loturi cu un număr fix de elemente:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Acesta poate fi înlocuit cu iterateWhile după cum urmează:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/ro/cookbook/passing-variables.texy b/latte/ro/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..8c02237e23
--- /dev/null
+++ b/latte/ro/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Transmiterea variabilelor între șabloane
+****************************************
+
+Acest ghid explică modul în care sunt transmise variabilele între șabloane în Latte, folosind diverse etichete, cum ar fi `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` și altele. De asemenea, veți învăța cum să lucrați cu variabilele din etichetele `{block}` și `{define}` și care este scopul etichetei `{parameters}`.
+
+
+Tipuri de variabile .[#toc-types-of-variables]
+----------------------------------------------
+Variabilele din Latte pot fi împărțite în trei categorii în funcție de modul și locul în care sunt definite:
+
+**Variabilele de intrare** sunt cele care sunt trecute în șablon din exterior, de exemplu, dintr-un script PHP sau folosind un tag ca `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Variabilele înconjurătoare** sunt variabilele care există în locația unei anumite etichete. Acestea includ toate variabilele de intrare și alte variabile create cu ajutorul unor etichete precum `{var}`, `{default}`, sau în cadrul unei bucle `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Variabilele explicite** sunt cele specificate direct în cadrul unei etichete și trimise la șablonul țintă.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Eticheta `{block}` este utilizată pentru a defini blocuri de cod reutilizabile care pot fi personalizate sau extinse în șabloanele moștenite. Variabilele înconjurătoare definite înainte de bloc sunt disponibile în interiorul blocului, dar orice modificare a variabilelor se reflectă numai în cadrul blocului respectiv.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Eticheta `{define}` este utilizată pentru a crea blocuri care sunt redate numai atunci când sunt apelate folosind `{include}`. Variabilele disponibile în interiorul acestor blocuri depind de specificarea sau nu a unor parametri în definiție. În cazul în care sunt specificați parametrii, numai acei parametri sunt accesibili. În caz contrar, sunt accesibile toate variabilele de intrare din șablonul în care sunt definite blocurile.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Eticheta `{parameters}` este utilizată pentru a declara în mod explicit variabilele de intrare așteptate la începutul șablonului. În acest fel, puteți documenta cu ușurință variabilele așteptate și tipurile de date ale acestora. De asemenea, este posibil să se definească valori implicite.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Eticheta `{include file}` este utilizată pentru a insera un șablon întreg. Acestui șablon i se transmit atât variabilele de intrare ale șablonului în care se utilizează eticheta, cât și variabilele definite în mod explicit. Cu toate acestea, șablonul țintă poate limita domeniul de aplicare folosind `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Atunci când se inserează un bloc definit în același șablon, toate variabilele înconjurătoare și cele definite în mod explicit îi sunt transmise:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+În acest exemplu, variabilele `$name` și `$age` sunt transmise blocului `blockName`. Același comportament se aplică și la `{include parent}`.
+
+Atunci când se inserează un bloc dintr-un alt șablon, se transmit numai variabilele de intrare și variabilele definite explicit. Variabilele înconjurătoare nu sunt disponibile în mod automat.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` sau `{extends}`
+--------------------------
+Aceste etichete definesc un aspect la care sunt transmise variabilele de intrare ale șablonului copil și variabilele create în cod înainte de blocuri:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Șablon `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Eticheta `{embed}` este similară cu `{include}`, dar permite încorporarea de blocuri în șablon. Spre deosebire de `{include}`, sunt transmise doar variabilele declarate explicit:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+În acest exemplu, șablonul `menu.latte` are acces doar la variabila `$items`.
+
+În schimb, blocurile din interiorul `{embed}` au acces la toate variabilele din jur:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Eticheta `{import}` este utilizată pentru a încărca blocuri din alte șabloane. Atât variabilele de intrare, cât și cele declarate explicit sunt transmise blocurilor importate.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Eticheta `{sandbox}` izolează șablonul pentru o procesare sigură. Variabilele sunt transmise exclusiv în mod explicit.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/ro/creating-extension.texy b/latte/ro/creating-extension.texy
index 51bf98fc2d..7b0f52342c 100644
--- a/latte/ro/creating-extension.texy
+++ b/latte/ro/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// o funcție de parsare care creează doar un nod pentru moment
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Dacă creați o nouă etichetă pentru Latte, este recomandabil să creați o clasă de nod dedicată pentru aceasta, care o va reprezenta în arborele AST (a se vedea clasa `ForeachNode` din exemplul de mai sus). În unele cazuri, s-ar putea să vi se pară utilă clasa de noduri auxiliare triviale [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], care vă permite să treceți ca parametri de constructor corpul metodei `print()` și lista de noduri accesibile prin metoda `getIterator()`:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Compilatorul trece .[#toc-compiler-passes]
 ==========================================
 
diff --git a/latte/ro/develop.texy b/latte/ro/develop.texy
index 08a790a567..2be2225225 100644
--- a/latte/ro/develop.texy
+++ b/latte/ro/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Local .[#toc-locale]{data-version:3.0.18}
+=========================================
+
+Latte vă permite să setați localele, care afectează formatarea numerelor, a datelor și sortarea. Aceasta este setată utilizând metoda `setLocale()`. Identificatorul locale urmează standardul IETF language tag, care utilizează extensia PHP `intl`. Acesta constă dintr-un cod de limbă și, eventual, un cod de țară, de exemplu, `en_US` pentru limba engleză în Statele Unite, `de_DE` pentru limba germană în Germania etc.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Setarea locale afectează filtrele [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] și [bytes |filters#bytes].
+
+.[note]
+Necesită extensia PHP `intl`. Setarea din Latte nu afectează setarea locală globală din PHP.
+
+
 Modul strict .[#toc-strict-mode]{data-version:3.0.8}
 ====================================================
 
@@ -274,16 +290,25 @@ Dacă utilizați etichete personalizate, creați și Linterul personalizat, de e
 // introduceți calea reală către fișierul autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// adăugați extensii individuale aici
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// adăugați extensiile individuale aici
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternativ, puteți transmite propriul obiect `Latte\Engine` către Linter:
+
+```php
+$latte = new Latte\Engine;
+// aici configurăm obiectul $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Încărcarea șabloanelor dintr-un șir de caractere .[#toc-loading-templates-from-a-string]
 ========================================================================================
diff --git a/latte/ro/extending-latte.texy b/latte/ro/extending-latte.texy
index 2d456f3147..855d311eae 100644
--- a/latte/ro/extending-latte.texy
+++ b/latte/ro/extending-latte.texy
@@ -68,6 +68,16 @@ După cum puteți vedea, funcția primește partea stângă a filtrului înainte
 
 Bineînțeles, funcția care reprezintă filtrul poate accepta orice număr de parametri, fiind suportați și parametrii variadici.
 
+În cazul în care filtrul returnează un șir de caractere în HTML, îl puteți marca astfel încât Latte să nu-l evadeze automat (și, prin urmare, dublu). Astfel se evită necesitatea de a specifica `|noescape` în șablon.
+Cea mai simplă modalitate este să înfășurați șirul într-un obiect `Latte\Runtime\Html`, cealaltă modalitate este [Filtre contextuale |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+În acest caz, filtrul trebuie să asigure o scăpare corectă a datelor.
+
 
 Filtre care utilizează clasa .[#toc-filters-using-the-class]
 ------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// schimbăm tipul de conținut în HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/ro/filters.texy b/latte/ro/filters.texy
index 3570525f3c..5d907dd1f0 100644
--- a/latte/ro/filters.texy
+++ b/latte/ro/filters.texy
@@ -11,14 +11,16 @@ Filtrele sunt funcții care modifică sau formatează datele în forma dorită.
 | `bytes` | [formatează dimensiunea în bytes |#bytes]
 | `clamp` | [fixează valoarea în intervalul |#clamp]
 | `dataStream` | [Conversia protocolului URI de date |#datastream]
-| `date` | [formatează data |#date]
+| `date` | [formatează data și ora |#date]
 | `explode` | [separă un șir de caractere prin delimitatorul dat |#explode]
 | `first` | [returnează primul element al unui array sau caracterul unui șir de caractere |#first]
+| `group` | [grupează datele în funcție de diverse criterii |#group]
 | `implode` | [unește un array cu un șir de caractere|#implode]
 | `indent` | [indentează textul de la stânga cu un număr de tabulări |#indent]
 | `join` | [unește un array cu un șir de caractere|#implode]
 | `last` | [returnează ultimul element al unui array sau caracter al unui șir de caractere|#last]
 | `length` | [returnează lungimea unui șir sau a unui array |#length]
+| `localDate` | [formatează data și ora în funcție de locale |#localDate]
 | `number` | [formatează numere |#number]
 | `padLeft` | [completează șirul de caractere la o lungime dată din stânga |#padLeft]
 | `padRight` | [completează șirul la lungimea dată dinspre dreapta |#padRight]
@@ -118,8 +120,8 @@ Filtre .[#toc-filters]
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filtru care simplifică listarea datelor liniare sub formă de tabel. Acesta returnează o matrice de tablouri cu numărul dat de elemente. Dacă furnizați un al doilea parametru, acesta este utilizat pentru a completa elementele lipsă de pe ultimul rând.
 
 ```latte
@@ -152,6 +154,8 @@ Se tipărește:
 </table>
 ```
 
+A se vedea, de asemenea, [grupul |#group] și eticheta [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Inserează întreruperi de linie HTML înainte de toate liniile noi.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Formatează o dimensiune în bytes în formă lizibilă pentru oameni.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Formatează dimensiunea în octeți într-o formă lizibilă de către om. Dacă este setată [localitatea |develop#locale], sunt utilizate separatoarele corespunzătoare de zecimale și de mii.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Formatează o dimensiune în bytes în formă lizibilă pentru oameni.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Rotunjește un număr până la o precizie dată.
 
 ```latte
@@ -203,8 +207,8 @@ Aplică igienizarea URL-urilor. Verifică dacă variabila conține un URL web (a
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Imprimă:
@@ -217,8 +221,8 @@ Imprimă:
 A se vedea și [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Returnează valoarea fixată în intervalul inclusiv dintre min și max.
 
 ```latte
@@ -228,14 +232,14 @@ Returnează valoarea fixată în intervalul inclusiv dintre min și max.
 Există, de asemenea, ca [funcție |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Convertește conținutul în schema URI de date. Poate fi utilizat pentru a insera imagini în HTML sau CSS fără a fi nevoie să se facă legătura cu fișiere externe.
 
 Să avem o imagine într-o variabilă `$img = Image::fromFile('obrazek.gif')`, atunci
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Se imprimă de exemplu:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Necesită extensia PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Returnează o dată în formatul dat folosind opțiunile funcțiilor PHP [php:strftime] sau [php:date]. Filtrul obține o dată sub forma unui timestamp UNIX, a unui șir de caractere sau a unui obiect de tip `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Formatează data și ora în conformitate cu masca utilizată de funcția PHP [php:date]. Filtrul acceptă data în format UNIX timestamp, ca șir de caractere sau ca obiect `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+A se vedea și [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Scapă o variabilă pentru a fi utilizată ca parametru în URL.
 A se vedea, de asemenea, [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Împarte un șir de caractere după delimitatorul dat și returnează un tablou de șiruri de caractere. Alias pentru `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Returnează primul element al unui array sau caracterul unui șir de caractere:
 A se vedea, de asemenea, [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Rotunjește un număr până la o precizie dată.
 
 ```latte
@@ -330,8 +335,27 @@ Convertește prima literă a unei valori în majusculă. Necesită extensia PHP
 A se vedea, de asemenea, [capitalize |#capitalize], [lower |#lower], [upper |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Filtrul grupează datele în funcție de diferite criterii.
+
+În acest exemplu, rândurile din tabel sunt grupate în funcție de coloana `categoryId`. Rezultatul este un tablou de tablouri în care cheia este valoarea din coloana `categoryId`. Citiți [instrucțiunile detaliate |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+A se vedea, de asemenea, [batch |#batch], funcția [group |functions#group] și eticheta [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Returnează un șir de caractere care este concatenarea șirurilor din matrice. Alias pentru `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Puteți utiliza și un alias `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Indentează un text de la stânga cu un anumit număr de tabulauri sau alte caractere pe care îl specificăm în al doilea argument opțional. Liniile goale nu sunt indentate.
 
 ```latte
@@ -396,6 +420,68 @@ Returnează lungimea unui șir de caractere sau a unei matrice.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Formatează data și ora în funcție de [locale |develop#locale], asigurând afișarea consecventă și localizată a datelor de timp în diferite limbi și regiuni. Filtrul acceptă data ca timestamp UNIX, șir sau obiect `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Dacă utilizați filtrul fără niciun parametru, acesta va afișa data în format lung, după cum se explică în continuare.
+
+**a) Utilizarea formatului**
+
+Parametrul `format` descrie componentele de timp care ar trebui afișate. Acesta utilizează coduri de litere, unde numărul de repetiții afectează lățimea ieșirii:
+
+| An | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Luna | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `aug.` / `august`
+| Zi | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `dum.` / `duminică`
+| Ora | `j` / `H` / `h` | preferat / 24 de ore / 12 ore
+| Minute | `m` / `mm` | `5` / `05` <small>(2 cifre atunci când sunt combinate cu secundele)</small>
+| Second | `s` / `ss` | `8` / `08` <small>(2 cifre atunci când sunt combinate cu minutele)</small>
+
+Ordinea codurilor în format nu contează, deoarece ordinea componentelor va fi afișată în conformitate cu convențiile locale. Prin urmare, formatul este independent de locale. De exemplu, formatul `yyyyMMMMd` în localul `en_US` afișează `April 15, 2024`, în timp ce în localul `cs_CZ` afișează `15. dubna 2024`:
+
+| locale:  | ro-RO | en_US
+|---
+| `format: 'dMy'` | 10.08.2024 | 8/10/2024
+| `format: 'yM'` | 08.2024 | 8/2024
+| `format: 'yyyyMMMM'` | august 2024 | August 2024
+| `format: 'MMMM'` | august | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 p.m. | 5:54 PM
+
+
+**b) Utilizarea stilurilor prestabilite**
+
+Parametrii `date` și `time` determină nivelul de detaliu pentru afișarea datei și orei. Puteți alege din mai multe niveluri: `full`, `long`, `medium`, `short`. Puteți afișa doar data, doar ora sau ambele:
+
+| locale:  | ro-RO | en_US
+|---
+| `date: short` | 23.01.1978 | 1/23/78
+| `date: medium` | 23 ian. 1978 | Jan 23, 1978
+| `date: long` | 23 ianuarie 1978 | January 23, 1978
+| `date: full` | luni, 23 ianuarie 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 CET | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.1978, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 ian. 1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 ianuarie 1978 la 08:30 | January 23, 1978 at 8:30 AM
+
+Pentru dată, puteți utiliza, de asemenea, prefixul `relative-` (de exemplu, `relative-short`), care pentru datele apropiate de prezent va afișa `yesterday`, `today` sau `tomorrow`; în caz contrar, se va afișa în mod standard.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+A se vedea și [data |#date].
+
+
 lower .[filter]
 ---------------
 Convertește o valoare în minuscule. Necesită extensia PHP `mbstring`.
@@ -416,8 +502,8 @@ Dacă link-ul utilizează o schemă diferită, cum ar fi `javascript:` sau `data
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Tipărituri:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 Folosirea abuzivă a filtrului `noescape` poate duce la o vulnerabilitate XSS! Nu îl utilizați niciodată decât dacă sunteți **absolut sigur** de ceea ce faceți și dacă șirul pe care îl imprimați provine dintr-o sursă de încredere.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Formatează un număr cu un anumit număr de zecimale. De asemenea, puteți specifica un caracter al punctului zecimal și al separatorului de mii.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Formatează un număr la un număr specificat de zecimale. Dacă este setată [localitatea |develop#locale], se utilizează separatoarele de zecimale și de mii corespunzătoare.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Formatează un număr cu un anumit număr de zecimale. De asemenea, puteți spec
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Parametrul `format` vă permite să definiți aspectul numerelor exact în funcție de nevoile dumneavoastră. Acesta necesită o [localitate |develop#locale] stabilită. Formatul constă din mai multe caractere speciale, a căror descriere completă poate fi găsită în documentația "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> cifră obligatorie, afișată întotdeauna chiar dacă este zero
+- `#` cifră opțională, afișată numai dacă numărul are o cifră în acel loc
+- `@` cifră semnificativă, ajută la afișarea numărului cu un anumit număr de cifre semnificative
+- `.` marchează locul unde ar trebui să fie separatorul zecimal (virgulă sau punct, în funcție de localitate)
+- `,` utilizat pentru a separa grupuri de cifre, de obicei mii
+- `%` înmulțește numărul cu 100 și adaugă semnul procentului
+
+Să ne uităm la câteva exemple. În primul exemplu, două zecimale sunt obligatorii; în al doilea, ele sunt opționale. Al treilea exemplu prezintă o umplere cu zerouri pe ambele părți, iar al patrulea afișează doar cifrele existente:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Cifrele semnificative determină câte cifre, indiferent de punctul zecimal, ar trebui afișate, rotunjind numărul dacă este necesar:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+O modalitate ușoară de a afișa un număr ca procent. Numărul este înmulțit cu 100 și se adaugă semnul `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Putem defini un format diferit pentru numerele pozitive și negative, separate de un caracter `;`. În acest fel, de exemplu, numerele pozitive pot fi afișate cu un semn `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Rețineți că aspectul real al numerelor poate varia în funcție de setările locale. De exemplu, în unele țări, se utilizează o virgulă în loc de un punct ca separator zecimal. Acest filtru ține cont automat de acest lucru, deci nu trebuie să vă faceți griji.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Pads un șir de caractere la o anumită lungime cu un alt șir de caractere din stânga.
 
@@ -472,7 +606,7 @@ Pads un șir de caractere la o anumită lungime cu un alt șir de caractere din
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Adaugă un șir de caractere la o anumită lungime cu un alt șir din dreapta.
 
@@ -514,8 +648,8 @@ Returnează un element aleatoriu din matrice sau un caracter aleatoriu dintr-un
 A se vedea, de asemenea, [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Repetă șirul de x ori.
 
 ```latte
@@ -523,7 +657,7 @@ Repetă șirul de x ori.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Înlocuiește toate aparițiile șirului de căutare cu șirul de înlocuire.
 
@@ -538,7 +672,7 @@ Se pot face mai multe înlocuiri deodată:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Înlocuiește toate ocurențele în funcție de expresia regulată.
 
@@ -559,8 +693,8 @@ Inversează șirul sau matricea dată.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Rotunjește un număr la o precizie dată.
 
 ```latte
@@ -573,7 +707,7 @@ Rotunjește un număr la o precizie dată.
 A se vedea, de asemenea, [plafon |#ceil], [podea |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Extrage o porțiune dintr-un tablou sau un șir de caractere.
 
@@ -591,9 +725,9 @@ Filtrul slice funcționează ca funcția PHP `array_slice` pentru array-uri și
 Filter reordonează și resetează implicit cheile tabloului de numere întregi. Acest comportament poate fi modificat prin setarea preserveKeys la true. Cheile șirurilor de caractere sunt întotdeauna păstrate, indiferent de acest parametru.
 
 
-sort  .[filter]
----------------
-Filtru care sortează o matrice și menține asocierea indicilor.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Filtrul sortează elementele unui array sau iterator păstrând cheile lor asociative. Atunci când este setată o [localitate |develop#locale], sortarea urmează regulile acesteia, cu excepția cazului în care este specificată o funcție de comparație personalizată.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Array sortat în ordine inversă.
 {/foreach}
 ```
 
-Puteți trece propria funcție de comparație ca parametru:
+Puteți specifica o funcție de comparație personalizată pentru sortare (exemplul arată cum se inversează sortarea de la cel mai mare la cel mai mic):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Filtrul `|sort` vă permite, de asemenea, să sortați elementele după cheie:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Dacă aveți nevoie să sortați un tabel după o anumită coloană, puteți utiliza parametrul `by`. Valoarea `'name'` din exemplu specifică faptul că sortarea se va face după `$row->name` sau `$row['name']`, în funcție de faptul că `$row` este o matrice sau un obiect:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+De asemenea, puteți defini o funcție de apelare care să determine valoarea după care se va sorta:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Parametrul `byKey` poate fi utilizat în același mod.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Convertește HTML în text simplu. Adică, elimină etichetele HTML și converte
 Textul simplu rezultat poate conține, în mod natural, caractere care reprezintă etichete HTML, de exemplu `'&lt;p&gt;'|stripHtml` este convertit în `<p>`. Nu scoateți niciodată textul rezultat cu `|noescape`, deoarece acest lucru poate duce la o vulnerabilitate de securitate.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Extrage o porțiune dintr-un șir de caractere. Acest filtru a fost înlocuit cu un filtru de [felie |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ Extrage o porțiune dintr-un șir de caractere. Acest filtru a fost înlocuit cu
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Traduce expresii în alte limbi. Pentru ca filtrul să fie disponibil, trebuie să configurați [translator |develop#TranslatorExtension]. De asemenea, puteți utiliza [etichetele pentru traducere |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Traduce expresii în alte limbi. Pentru ca filtrul să fie disponibil, trebuie s
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Elimină caracterele de început și de sfârșit, implicit spațiile albe.
 
 ```latte
@@ -675,7 +835,7 @@ Elimină caracterele de început și de sfârșit, implicit spațiile albe.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Scurtează un șir de caractere până la lungimea maximă dată, dar încearcă să păstreze cuvintele întregi. În cazul în care șirul este trunchiat, adaugă elipse la sfârșit (acest lucru poate fi modificat prin intermediul celui de-al doilea parametru).
 
diff --git a/latte/ro/functions.texy b/latte/ro/functions.texy
index 66b2446f2a..0e1b9873db 100644
--- a/latte/ro/functions.texy
+++ b/latte/ro/functions.texy
@@ -9,6 +9,8 @@ Funcții Latte
 | `divisibleBy`| [verifică dacă o variabilă este divizibilă cu un număr |#divisibleBy]
 | `even` | [verifică dacă numărul dat este par |#even]
 | `first` | [returnează primul element al unui array sau caracterul unui șir de caractere|#first]
+| `group` | [grupează datele în funcție de diverse criterii |#group]
+| `hasBlock` | [detectează existența unui bloc |#hasBlock]
 | `last` | [returnează ultimul element al unui array sau caracter al unui șir de caractere|#last]
 | `odd` | [verifică dacă numărul dat este impar |#odd]
 | `slice` | [extrage o porțiune dintr-un tablou sau un șir de caractere |#slice]
@@ -73,8 +75,8 @@ Verifică dacă numărul dat este par.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Returnează primul element al unui tablou sau caracterul unui șir de caractere:
 
 ```latte
@@ -85,6 +87,36 @@ Returnează primul element al unui tablou sau caracterul unui șir de caractere:
 A se vedea, de asemenea, [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Această funcție grupează datele în funcție de diferite criterii.
+
+În acest exemplu, rândurile din tabel sunt grupate în funcție de coloana `categoryId`. Rezultatul este o matrice de câmpuri în care cheia este valoarea din coloana `categoryId`. Citiți [instrucțiunile detaliate |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+A se vedea, de asemenea, [grupul de |filters#group] filtre.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Verifică dacă blocul cu numele specificat există:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+A se vedea, de asemenea, [verificarea existenței blocului |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Returnează ultimul element al unui array sau caracter al unui șir de caractere:
@@ -106,8 +138,8 @@ Verifică dacă numărul dat este impar.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Extrage o porțiune dintr-un tablou sau un șir de caractere.
 
 ```latte
diff --git a/latte/ro/recipes.texy b/latte/ro/recipes.texy
index 88795d0716..7f9c6c67bf 100644
--- a/latte/ro/recipes.texy
+++ b/latte/ro/recipes.texy
@@ -9,7 +9,7 @@ Scrieți șabloane într-un editor sau IDE care are suport pentru Latte. Va fi m
 
 - NetBeans IDE are suport încorporat
 - PhpStorm: instalați [pluginul Latte |https://plugins.jetbrains.com/plugin/7457-latte] în `Settings > Plugins > Marketplace`
-- VS Code: căutați în markerplace pentru pluginul "Nette Latte + Neon"
+- VS Code: căutați markerplace pentru Nette [Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [+ Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] sau Nette [Latte șabloane |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
 - Sublime Text 3: în Package Control găsiți și instalați pachetul `Nette` și selectați Latte în `View > Syntax`
 - în vechile editoare utilizați evidențierea Smarty pentru fișierele .latte
 
diff --git a/latte/ro/safety-first.texy b/latte/ro/safety-first.texy
index fa2cb883f5..8025c926d4 100644
--- a/latte/ro/safety-first.texy
+++ b/latte/ro/safety-first.texy
@@ -351,7 +351,7 @@ Latte verifică automat dacă variabila utilizată în atributele `src` sau `hre
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Scrie:
diff --git a/latte/ro/syntax.texy b/latte/ro/syntax.texy
index 77ba5ec1f0..003b2d7016 100644
--- a/latte/ro/syntax.texy
+++ b/latte/ro/syntax.texy
@@ -98,7 +98,7 @@ Imprimă:
 Sau prin utilizarea prefixului `tag-`, funcționalitatea se aplică numai la etichetele HTML:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 În funcție de valoarea variabilei `$url`, se va imprima:
@@ -155,6 +155,20 @@ Sau direct pe valoare (în combinație cu [`{=expr}` | https://latte.nette.org/r
 ```
 
 
+Etichete HTML dinamice .[#toc-dynamic-html-tags]
+================================================
+
+Latte acceptă etichete HTML dinamice, care sunt utile atunci când aveți nevoie de flexibilitate în ceea ce privește numele etichetelor:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+De exemplu, codul de mai sus poate genera `<h1>Heading</h1>` sau `<h2>Heading</h2>` în funcție de valoarea variabilei `$level`. Etichetele HTML dinamice din Latte trebuie să fie întotdeauna asociate. Alternativa lor este [n:tag |tags#n:tag].
+
+Deoarece Latte este un sistem securizat de creare de șabloane, acesta verifică dacă numele tag-ului rezultat este valid și nu conține valori nedorite sau rău intenționate. De asemenea, se asigură că numele tag-ului final este întotdeauna același cu numele tag-ului de deschidere.
+
+
 Comentarii .[#toc-comments]
 ===========================
 
diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy
index 12fbf21767..0662ce926b 100644
--- a/latte/ro/tags.texy
+++ b/latte/ro/tags.texy
@@ -16,6 +16,7 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [condiție ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [testează dacă a avut loc o schimbare |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default]
+| `n:else` | [conținut alternativ pentru condiții |#n:else]
 
 .[table-latte-tags language-latte]
 |## Bucle
@@ -97,8 +98,8 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate.
 | `{link}` | [tipărește un link |application:creating-links#In the Presenter Template]
 | `{plink}` | [tipărește un link către un prezentator |application:creating-links#In the Presenter Template]
 | `{control}` | [tipărește o componentă |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [un fragment de șablon care poate fi trimis prin AJAX |application:ajax#tag-snippet]
-| `{snippetArea}` | plic de fragmente
+| `{snippet}`... `{/snippet}` | [un fragment de șablon care poate fi trimis prin AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [plic de fragmente |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [pune în cache o secțiune de șablon |caching:en#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate.
 | `{input}` | [tipărește un element de intrare în formular |forms:rendering#label-input]
 | `{inputError}` | [tipărește mesajul de eroare pentru elementul de intrare al formularului |forms:rendering#inputError]
 | `n:name` | [activează un element de intrare HTML |forms:rendering#n:name]
-| `{formPrint}` | [generează schița unui formular Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [tipărește clasa PHP pentru datele formularului |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [redarea parțială a formularului |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [redarea formularului container |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ La fel ca orice tag pair, o pereche de `{if} ... {/ if}` poate fi scrisă ca [n:
 Frumos.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Dacă scrieți condiția `{if} ... {/if}` sub forma unui [n:atribut |syntax#n:attributes], aveți opțiunea de a specifica o ramură alternativă folosind `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Atributul `n:else` poate fi, de asemenea, utilizat împreună cu [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], și [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ A se vedea și [`{ifset block}` |template-inheritance#checking-block-existence]
 Utilizați condiția `{ifset $var}` pentru a determina dacă o variabilă (sau mai multe variabile) există și dacă are o valoare diferită de cea nulă. De fapt, este același lucru cu `if (isset($var))` în PHP. La fel ca orice tag pair, aceasta poate fi scrisă sub forma [n:attribute |syntax#n:attributes], așa că haideți să o arătăm în exemplu:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Este destul de practic, nu-i așa?
 `{iterateWhile}`
 ----------------
 
-Aceasta simplifică gruparea datelor liniare în timpul iterației într-o buclă foreach prin efectuarea iterației într-o buclă imbricata, atâta timp cât condiția este îndeplinită. [Citiți instrucțiunile din cartea de bucate |cookbook/iteratewhile].
+Simplifică gruparea datelor liniare în timpul iterației într-o buclă foreach prin iterația într-o buclă imbricata până când este îndeplinită o condiție. [Citiți instrucțiunile detaliate |cookbook/grouping].
 
 De asemenea, poate înlocui în mod elegant `{first}` și `{last}` în exemplul de mai sus:
 
@@ -489,6 +501,8 @@ De asemenea, poate înlocui în mod elegant `{first}` și `{last}` în exemplul
 {/foreach}
 ```
 
+A se vedea, de asemenea, filtrele de [lot |filters#batch] și de [grup |filters#group].
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Dacă `$heading === null`, atributul `<h1>` este tipărit fără modificări. Î
 <h3 class="main">...</h3>
 ```
 
+Deoarece Latte este un sistem de modelare securizat, acesta verifică dacă noul nume de etichetă este valid și nu conține valori nedorite sau rău intenționate.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/ro/template-inheritance.texy b/latte/ro/template-inheritance.texy
index 07ed567969..b5a4618822 100644
--- a/latte/ro/template-inheritance.texy
+++ b/latte/ro/template-inheritance.texy
@@ -132,7 +132,7 @@ Iată câteva sfaturi pentru a lucra cu moștenirea aspectului:
 
 - Dacă utilizați `{layout}` într-un șablon, trebuie să fie prima etichetă de șablon din șablonul respectiv.
 
-- Layout-ul poate fi [căutat în mod automat |develop#automatic-layout-lookup] (la fel ca în [prezentări |application:templates#search-for-templates]). În acest caz, dacă șablonul nu ar trebui să aibă un layout, se va indica acest lucru cu eticheta `{layout none}`.
+- Layout-ul poate fi [căutat în mod automat |develop#automatic-layout-lookup] (la fel ca în [prezentări |application:templates#Template Lookup]). În acest caz, dacă șablonul nu ar trebui să aibă un layout, se va indica acest lucru cu eticheta `{layout none}`.
 
 - Eticheta `{layout}` are aliasul `{extends}`.
 
@@ -396,6 +396,14 @@ Puteți utiliza o variabilă sau orice expresie din PHP ca nume de bloc. În ace
 {/ifset}
 ```
 
+Existența blocurilor este, de asemenea, returnată de funcția [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Sfaturi .[#toc-tips]
 --------------------
@@ -415,7 +423,7 @@ Iată câteva sfaturi pentru a lucra cu blocuri:
 Reutilizare orizontală `{import}` .{toc: Horizontal Reuse}
 ==========================================================
 
-Reutilizarea orizontală este un al treilea mecanism de reutilizare și moștenire în Latte. Acesta vă permite să încărcați blocuri din alte șabloane. Este similar cu crearea unui fișier PHP cu funcții ajutătoare sau a unei trăsături.
+Reutilizarea orizontală este al treilea mecanism de reutilizare și moștenire în Latte. Acesta permite încărcarea blocurilor din alte șabloane. Este similar cu crearea unui fișier cu funcții ajutătoare în PHP și apoi încărcarea acestuia folosind `require`.
 
 Deși moștenirea aspectului șablonului este una dintre cele mai puternice caracteristici ale Latte, aceasta este limitată la moștenirea simplă - un șablon poate extinde doar un alt șablon. Reutilizarea orizontală este o modalitate de a obține moștenirea multiplă.
 
@@ -447,7 +455,7 @@ Eticheta `{import}` trebuie să fie prima etichetă de șablon după `{layout}`.
 
 Puteți utiliza oricâte declarații `{import}` doriți în cadrul unui șablon dat. În cazul în care două șabloane importate definesc același bloc, primul câștigă. Cu toate acestea, prioritatea cea mai mare este acordată șablonului principal, care poate suprascrie orice bloc importat.
 
-Toate blocurile suprascrise pot fi incluse treptat prin inserarea lor ca [bloc părinte |#parent block]:
+Conținutul blocurilor suprascrise poate fi păstrat prin inserarea blocului în același mod ca un [bloc părinte |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/ru/@left-menu.texy b/latte/ru/@left-menu.texy
index 98c9f92eca..1ab036217a 100644
--- a/latte/ru/@left-menu.texy
+++ b/latte/ru/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Начало работы |Guide]
 - [Зачем использовать шаблоны? |why-use]
-- Концепции
+- Концепции ⚗️
 	- [Безопасность превыше всего |Safety First]
 	- [Наследование шаблонов |Template Inheritance]
 	- [Система типов |Type System]
 	- [Песочница |Sandbox]
 
-- Для дизайнеров
+- Для дизайнеров 🎨
 	- [Синтаксис |Syntax]
 	- [Теги |Tags]
 	- [Фильтры |Filters]
 	- [Функции |Functions]
 	- [Советы и хитрости |recipes]
 
-- Для разработчиков
+- Для разработчиков 🧮
 	- [Практика для разработчиков |develop]
 	- [Расширение Latte |Extending Latte]
 	- [Создание расширения |creating-extension]
 
-- [Поваренная книга |cookbook/@home]
+- [Поваренная книга 💡|cookbook/@home]
 	- [Миграция с Twig |cookbook/migration-from-twig]
 	- [... подробнее |cookbook/@home]
 
diff --git a/latte/ru/cookbook/@home.texy b/latte/ru/cookbook/@home.texy
index 0c94c7cb6c..951d1fc8be 100644
--- a/latte/ru/cookbook/@home.texy
+++ b/latte/ru/cookbook/@home.texy
@@ -4,7 +4,9 @@
 .[perex]
 Примеры кодов и рецепты для выполнения обычных задач с помощью Latte.
 
-- [Все, что вы всегда хотели знать о {iterateWhile} |iteratewhile]
+- [Рекомендации для разработчиков |/develop]
+- [Передача переменных через шаблоны |passing-variables]
+- [Все, что вы всегда хотели знать о группировке |grouping]
 - [Как писать SQL-запросы в Latte? |how-to-write-sql-queries-in-latte]
 - [Миграция с PHP |migration-from-php]
 - [Миграция с Twig |migration-from-twig]
diff --git a/latte/ru/cookbook/grouping.texy b/latte/ru/cookbook/grouping.texy
new file mode 100644
index 0000000000..b61b5408d0
--- /dev/null
+++ b/latte/ru/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Все, что вы всегда хотели знать о группировке
+*********************************************
+
+.[perex]
+При работе с данными в шаблонах вы часто сталкиваетесь с необходимостью группировать их или отображать в соответствии с определенными критериями. Для этого Latte предлагает несколько мощных инструментов.
+
+Фильтр и функция `|group` позволяют эффективно группировать данные по заданным критериям, фильтр `|batch` облегчает разбивку данных на фиксированные партии, а тег `{iterateWhile}` предоставляет возможность более сложного управления циклами с помощью условий.
+Каждый из этих тегов предлагает особые возможности для работы с данными, что делает их незаменимыми инструментами для динамичного и структурированного отображения информации в шаблонах Latte.
+
+
+Фильтр и функция `group` .[#toc-filter-and-function-group]
+==========================================================
+
+Представьте себе таблицу базы данных `items` с элементами, разделенными на категории:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Яблоко
+| 2 | 1 | Банан
+| 3 | 2 | PHP
+| 4 | 3 | Зеленый
+| 5 | 3 | Красный
+| 6 | 3 | Синий
+
+Простой список всех элементов с использованием шаблона Latte будет выглядеть следующим образом:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Однако если мы хотим, чтобы элементы были организованы в группы по категориям, нам нужно разделить их так, чтобы для каждой категории был свой собственный список. Результат будет выглядеть следующим образом:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Эту задачу можно легко и элегантно решить с помощью `|group`. В качестве параметра мы указываем `categoryId`, что означает, что элементы будут разделены на меньшие массивы на основе значения `$item->categoryId` (если бы `$item` был массивом, мы бы использовали `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Фильтр также может быть использован как функция в Latte, что дает нам альтернативный синтаксис: `{foreach group($items, categoryId) ...}`.
+
+Если вы хотите сгруппировать элементы по более сложным критериям, вы можете использовать функцию в параметре filter. Например, группировка элементов по длине их имени будет выглядеть следующим образом:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Важно отметить, что `$categoryItems` - это не обычный массив, а объект, который ведет себя как итератор. Чтобы получить доступ к первому элементу в группе, можно использовать функцию [`first()` |latte:functions#first] функцию.
+
+Такая гибкость в группировке данных делает `group` исключительно полезным инструментом для представления данных в шаблонах Latte.
+
+
+Вложенные циклы .[#toc-nested-loops]
+------------------------------------
+
+Допустим, у нас есть таблица базы данных с еще одним столбцом `subcategoryId`, который определяет подкатегории для каждого товара. Мы хотим отобразить каждую основную категорию в отдельном `<ul>` списке, а каждую подкатегорию - в отдельном вложенном `<ol>` списке:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Соединение с базой данных Nette .[#toc-connection-with-nette-database]
+----------------------------------------------------------------------
+
+Давайте покажем, как эффективно использовать группировку данных в сочетании с Nette Database. Предположим, мы работаем с таблицей `items` из начального примера, которая связана через столбец `categoryId` с таблицей `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Фрукты |
+| 2 | Языки |
+| 3 | Цвета |
+
+Мы загружаем данные из таблицы `items` с помощью команды Nette Database Explorer `$items = $db->table('items')`. Во время итерации над этими данными мы имеем возможность не только обращаться к таким атрибутам, как `$item->name` и `$item->categoryId`, но и, благодаря связи с таблицей `categories`, к связанной строке в ней через `$item->category`. Эта связь может продемонстрировать интересное применение:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+В данном случае мы используем фильтр `|group` для группировки по связанной строке `$item->category`, а не только по столбцу `categoryId`. Это дает нам `ActiveRow` данной категории в ключе переменной, позволяя напрямую отображать ее название с помощью `{$category->name}`. Это практический пример того, как группировка может упростить шаблоны и облегчить работу с данными.
+
+
+Фильтр `|batch` .[#toc-filter-batch]
+====================================
+
+Фильтр позволяет разбить список элементов на группы с заранее определенным количеством элементов. Этот фильтр идеально подходит для ситуаций, когда необходимо представить данные в нескольких небольших группах, например, для большей наглядности или визуальной организации на странице.
+
+Представьте, что у нас есть список элементов и мы хотим отобразить их в виде списков, каждый из которых содержит не более трех элементов. В этом случае очень удобно использовать фильтр `|batch`:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+В этом примере список `$items` делится на более мелкие группы, каждая из которых (`$batch`) содержит не более трех элементов. Каждая группа отображается в отдельном `<ul>` списке.
+
+Если последняя группа не содержит достаточно элементов для достижения желаемого количества, второй параметр фильтра позволяет определить, чем будет дополнена эта группа. Это идеально подходит для эстетического выравнивания элементов, когда неполный ряд может выглядеть неупорядоченным.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Тег `{iterateWhile}` .[#toc-tag-iteratewhile]
+=============================================
+
+Мы продемонстрируем те же задачи, которые решали с помощью фильтра `|group`, используя тег `{iterateWhile}`. Основное различие между этими двумя подходами заключается в том, что `group` сначала обрабатывает и группирует все входные данные, а `{iterateWhile}` управляет ходом циклов с помощью условий, поэтому итерации происходят последовательно.
+
+Сначала мы рисуем таблицу с категориями с помощью iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Если `{foreach}` обозначает внешнюю часть цикла, то есть рисование списков для каждой категории, то тег `{iterateWhile}` обозначает внутреннюю часть, то есть отдельные элементы.
+Условие в теге end говорит, что повторение будет продолжаться до тех пор, пока текущий и следующий элемент принадлежат к одной и той же категории (`$iterator->nextValue` - [следующий элемент |/tags#$iterator]).
+
+Если бы условие выполнялось всегда, то во внутреннем цикле были бы нарисованы все элементы:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Результат будет выглядеть следующим образом:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Для чего нужен iterateWhile в этом случае? Когда таблица пуста и не содержит элементов, пустота не `<ul></ul>` не выводится.
+
+Если мы указываем условие в открывающем теге `{iterateWhile}`, поведение меняется: условие (и переход к следующему элементу) выполняется в начале внутреннего цикла, а не в конце.
+Таким образом, если в `{iterateWhile}` вы всегда переходите без условий, то в `{iterateWhile $cond}` вы переходите только при выполнении условия `$cond`. И в это же время в `$item` записывается следующий элемент.
+
+Это полезно, например, в ситуации, когда мы хотим отобразить первый элемент в каждой категории по-разному, например так:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Мы модифицируем исходный код таким образом, чтобы сначала отрисовывался первый элемент, а затем во внутреннем цикле `{iterateWhile}` отрисовывались остальные элементы из той же категории:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+В рамках одного цикла мы можем создать несколько внутренних циклов и даже вложить их друг в друга. Таким образом можно сгруппировать, например, подкатегории.
+
+Предположим, что в таблице есть еще один столбец `subcategoryId`, и помимо того, что каждая категория находится в отдельном столбце. `<ul>`, каждая подкатегория в отдельном `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/ru/cookbook/iteratewhile.texy b/latte/ru/cookbook/iteratewhile.texy
deleted file mode 100644
index 1ce9a8b0da..0000000000
--- a/latte/ru/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Все, что вы всегда хотели знать о {iterateWhile}
-************************************************
-
-.[perex]
-Тег `{iterateWhile}` подходит для различных трюков в циклах foreach.
-
-Предположим, у нас есть следующая таблица базы данных, в которой элементы разделены на категории:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Конечно, вывести элементы в цикле foreach в виде списка очень просто:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Но что делать, если вы хотите вывести каждую категорию в отдельный список? Другими словами, как решить задачу группировки элементов из линейного списка в цикле foreach. Вывод должен выглядеть следующим образом:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Мы покажем вам, как легко и элегантно можно решить эту задачу с помощью iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Если `{foreach}` обозначает внешнюю часть цикла, то есть составление списков для каждой категории, то теги `{iterateWhile}` указывают на внутреннюю часть, то есть на отдельные элементы.
-Условие в теге end говорит, что повторение будет продолжаться до тех пор, пока текущий и следующий элемент принадлежат одной категории (`$iterator->nextValue` - [следующий элемент |/tags#iterator]).
-
-Если условие всегда выполняется, то во внутреннем цикле рисуются все элементы:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Результат будет выглядеть следующим образом:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Чем полезно такое использование iterateWhile? Чем оно отличается от решения, которое мы показали в самом начале этого руководства? Разница в том, что если таблица пуста и не содержит элементов, то она не будет выводиться пустой `<ul></ul>`.
-
-
-Решение без `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-------------------------------------------------------------------
-
-Если бы мы решали ту же задачу с помощью совершенно базовых конструкций систем шаблонов, например, в Twig, Blade или чистом PHP, то решение выглядело бы примерно так:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-Однако этот код непонятен и неинтуитивен. Связь между открывающим и закрывающим HTML-тегами совершенно не ясна. С первого взгляда не ясно, есть ли ошибка. И для этого требуются вспомогательные переменные, такие как `$prevCatId`.
-
-В отличие от этого, решение с `{iterateWhile}` чистое, понятное, не требует вспомогательных переменных и является надежным.
-
-
-Условие в закрывающем теге .[#toc-condition-in-the-closing-tag]
----------------------------------------------------------------
-
-Если указать условие в открывающем теге `{iterateWhile}`, то поведение меняется: условие (и переход к следующему элементу) выполняется в начале внутреннего цикла, а не в конце.
-Таким образом, если `{iterateWhile}` без условия вводится всегда, то `{iterateWhile $cond}` вводится только при выполнении условия `$cond`. В то же время, следующий элемент записывается в `$item`.
-
-Это полезно, например, в ситуации, когда нужно по-разному отобразить первый элемент в каждой категории, например:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Изменим исходный код, мы отрисовываем первый элемент, а затем дополнительные элементы из той же категории во внутреннем цикле `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Вложенные циклы .[#toc-nested-loops]
-------------------------------------
-
-Мы можем создать несколько внутренних циклов в одном цикле и даже вложить их друг в друга. Таким образом, например, можно сгруппировать подкатегории.
-
-Предположим, что в таблице `subCatId` есть еще один столбец, и в дополнение к тому, что каждая категория будет находиться в отдельном столбце, каждая подкатегория будет находиться в отдельном столбце. `<ul>`, каждая подкатегория будет находиться в отдельной колонке `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Фильтр | пакетный .[#toc-filter-batch]
---------------------------------------
-
-Группировка линейных элементов также обеспечивается фильтром `batch`, в партии с фиксированным количеством элементов:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Его можно заменить на iterateWhile следующим образом:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/ru/cookbook/passing-variables.texy b/latte/ru/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..6b326bb01b
--- /dev/null
+++ b/latte/ru/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Передача переменных между шаблонами
+***********************************
+
+Это руководство объясняет, как передавать переменные между шаблонами в Latte с помощью различных тегов, таких как `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}`, и других. Вы также узнаете, как работать с переменными в тегах `{block}` и `{define}`, а также о назначении тега `{parameters}`.
+
+
+Типы переменных .[#toc-types-of-variables]
+------------------------------------------
+Переменные в Latte можно разделить на три категории в зависимости от того, как и где они определяются:
+
+**Входные переменные** - это те, которые передаются в шаблон извне, например, из PHP-скрипта или с помощью тега `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Окружающие переменные** - это переменные, существующие в месте расположения определенного тега. К ним относятся все входные переменные и другие переменные, созданные с помощью таких тегов, как `{var}`, `{default}`, или в цикле `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Явные переменные** - это переменные, непосредственно указанные в теге и отправленные в целевой шаблон.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Тег `{block}` используется для определения многократно используемых блоков кода, которые могут быть настроены или расширены в наследуемых шаблонах. Окружающие переменные, определенные до блока, доступны внутри блока, но любые изменения переменных отражаются только в этом блоке.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Тег `{define}` используется для создания блоков, которые отображаются только при вызове с помощью `{include}`. Переменные, доступные внутри этих блоков, зависят от того, указаны ли в определении параметры. Если параметры указаны, то доступны только эти параметры. Если нет, то доступны все входные переменные шаблона, в котором определены блоки.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Тег `{parameters}` используется для явного объявления ожидаемых входных переменных в начале шаблона. Таким образом, вы можете легко документировать ожидаемые переменные и их типы данных. Также можно определить значения по умолчанию.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Тег `{include file}` используется для вставки целого шаблона. Этому шаблону передаются как входные переменные шаблона, в котором используется тег, так и явно определенные переменные. Однако целевой шаблон может ограничить область применения с помощью `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+При вставке блока, определенного в том же шаблоне, ему передаются все окружающие и явно определенные переменные:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+В этом примере переменные `$name` и `$age` передаются блоку `blockName`. Аналогичное поведение применимо и к блоку `{include parent}`.
+
+При вставке блока из другого шаблона передаются только входные переменные и явно определенные переменные. Окружающие переменные автоматически не доступны.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` или `{extends}`
+--------------------------
+Эти теги определяют макет, в который передаются входные переменные дочернего шаблона и переменные, созданные в коде перед блоками:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Шаблон `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Тег `{embed}` аналогичен тегу `{include}`, но позволяет встраивать блоки в шаблон. В отличие от `{include}`, передаются только явно объявленные переменные:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+В данном примере шаблон `menu.latte` имеет доступ только к переменной `$items`.
+
+И наоборот, блоки внутри `{embed}` имеют доступ ко всем окружающим переменным:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Тег `{import}` используется для загрузки блоков из других шаблонов. Импортируемым блокам передаются как входные, так и явно объявленные переменные.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Тег `{sandbox}` изолирует шаблон для безопасной обработки. Переменные передаются исключительно в явном виде.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/ru/creating-extension.texy b/latte/ru/creating-extension.texy
index 23fd8a9051..e9722842db 100644
--- a/latte/ru/creating-extension.texy
+++ b/latte/ru/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// a parsing function that just creates a node for now
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Если вы создаете новый тег для Latte, то целесообразно создать для него специальный класс узла, который будет представлять его в дереве AST (см. класс `ForeachNode` в примере выше). В некоторых случаях может оказаться полезным тривиальный вспомогательный класс узла [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], который позволяет передать в качестве параметров конструктора тело метода `print()` и список узлов, доступных методом `getIterator()`:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Компилятор передает .[#toc-compiler-passes]
 ===========================================
 
diff --git a/latte/ru/develop.texy b/latte/ru/develop.texy
index d252d0bdd3..09b576545b 100644
--- a/latte/ru/develop.texy
+++ b/latte/ru/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Местность .[#toc-locale]{data-version:3.0.18}
+=============================================
+
+Latte позволяет установить локаль, которая влияет на форматирование чисел, дат и сортировку. Она задается с помощью метода `setLocale()`. Идентификатор локали соответствует стандарту языковых тегов IETF, который использует расширение PHP `intl`. Он состоит из кода языка и, возможно, кода страны, например, `en_US` для английского языка в США, `de_DE` для немецкого языка в Германии и т.д.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Настройка локали влияет на фильтры [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] и [bytes |filters#bytes].
+
+.[note]
+Требуется расширение PHP `intl`. Настройка в Latte не влияет на глобальную настройку локали в PHP.
+
+
 Строгий режим .[#toc-strict-mode]{data-version:3.0.8}
 =====================================================
 
@@ -274,14 +290,23 @@ vendor/bin/latte-lint <path>
 // введите фактический путь к файлу autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// добавить сюда отдельные расширения
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// добавьте сюда свои индивидуальные расширения
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
-exit($ok ? 0: 1);
+exit($ok ? 0 : 1);
+```
+
+В качестве альтернативы можно передать Линтеру свой собственный объект `Latte\Engine`:
+
+```php
+$latte = new Latte\Engine;
+// здесь мы настраиваем объект $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
 ```
 
 
diff --git a/latte/ru/extending-latte.texy b/latte/ru/extending-latte.texy
index cd592d0cdc..c032d8a9cb 100644
--- a/latte/ru/extending-latte.texy
+++ b/latte/ru/extending-latte.texy
@@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 
 Конечно, функция, представляющая фильтр, может принимать любое количество параметров, также поддерживаются переменные параметры.
 
+Если фильтр возвращает строку в HTML, то можно пометить ее так, чтобы Latte не делал автоматическую (и, соответственно, двойную) экранировку. Это избавляет от необходимости указывать `|noescape` в шаблоне.
+Самый простой способ - обернуть строку в объект `Latte\Runtime\Html`, другой способ - [Контекстные фильтры |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+В этом случае фильтр должен обеспечить корректное экранирование данных.
+
 
 Фильтры, использующие класс .[#toc-filters-using-the-class]
 -----------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// change content-type to HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/ru/filters.texy b/latte/ru/filters.texy
index 404481160b..8149108a78 100644
--- a/latte/ru/filters.texy
+++ b/latte/ru/filters.texy
@@ -11,14 +11,16 @@
 | `bytes` | [форматирует размер в байтах |#bytes]
 | `clamp` | [ограничивает значение диапазоном |#clamp]
 | `dataStream` | [преобразование протокола URI данных |#dataStream]
-| `date` | [форматирует дату |#date]
+| `date` | [Форматирование даты и времени |#date]
 | `explode` | [разделяет строку по заданному разделителю |#explode]
 | `first` | [возвращает первый элемент массива или символ строки |#first]
+| `group` | [группирует данные по различным критериям |#group].
 | `implode` | [соединяет массив со строкой |#implode]
 | `indent` | [отступы текста слева с количеством табуляций |#indent]
 | `join` | [присоединяет массив к строке |#implode]
 | `last` | [возвращает последний элемент массива или символ строки |#last]
 | `length` | [возвращает длину строки или массива |#length]
+| `localDate` | [Форматирование даты и времени в соответствии с локалью |#localDate]
 | `number` | [форматирует число |#number]
 | `padLeft` | [завершает строку до заданной длины слева |#padLeft]
 | `padRight` | [завершает строку до заданной длины справа |#padRight]
@@ -118,8 +120,8 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 =======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Фильтр, упрощающий вывод линейных данных в виде таблицы. Он возвращает массив массивов с заданным количеством элементов. Если указан второй параметр, он используется для заполнения недостающих элементов в последней строке.
 
 ```latte
@@ -152,6 +154,8 @@ batch(int length, mixed item): array .[filter]
 </table>
 ```
 
+См. также метки [group |#group] и [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ breakLines .[filter]
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Форматирует размер в байтах в человекочитаемую форму.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Форматирует размер в байтах в удобочитаемую форму. Если установлена [локаль |develop#locale], используются соответствующие десятичные и тысячные разделители.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ bytes(int precision = 2) .[filter]
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Округляет число с заданной точностью.
 
 ```latte
@@ -203,8 +207,8 @@ checkUrl .[filter]
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Печатает:
@@ -217,8 +221,8 @@ checkUrl .[filter]
 См. также [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Возвращает значение, зажатое в инклюзивный диапазон min и max.
 
 ```latte
@@ -228,14 +232,14 @@ clamp(int|float min, int|float max) .[filter]
 Также существует как [clamp |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Преобразует содержимое в схему URI данных. Может использоваться для вставки изображений в HTML или CSS без необходимости ссылки на внешние файлы.
 
 Пусть у вас есть изображение в переменной `$img = Image::fromFile('obrazek.gif')`, тогда
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Печатает, например:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Требуется расширение PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Возвращает дату в заданном формате, используя опции PHP-функций [php:strftime] или [php:date]. Фильтр получает дату в виде временной метки UNIX, строки или объекта типа `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Форматирует дату и время в соответствии с маской, используемой PHP-функцией [php:date]. Фильтр принимает дату в формате временной метки UNIX, как строку или как объект `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+См. также [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ escapeUrl .[filter]
 См. также [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Разделяет строку по заданному разделителю и возвращает массив строк. Псевдоним для `split`.
 
 ```latte
@@ -306,8 +311,8 @@ first .[filter]
 См. также [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Округляет число до заданной точности.
 
 ```latte
@@ -330,8 +335,27 @@ firstUpper .[filter]
 См. также [capitalize |#capitalize], [lower |#lower] регистр, [upper |#upper] регистр.
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Фильтр группирует данные по различным критериям.
+
+В этом примере строки таблицы сгруппированы по столбцу `categoryId`. На выходе получается массив массивов, где ключом является значение в столбце `categoryId`. Ознакомьтесь с [подробной инструкцией |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+См. также [batch |#batch], функцию [group |functions#group] и тег [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Возвращает строку, которая является конкатенацией строк в массиве. Псевдоним для `join`.
 
 ```latte
@@ -346,8 +370,8 @@ implode(string glue = '') .[filter]
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Отступы текста слева на заданное количество табуляций или других символов, которые мы указываем во втором необязательном аргументе. Пустые строки не отступают.
 
 ```latte
@@ -396,6 +420,68 @@ length .[filter]
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Форматирует дату и время в соответствии с [локалью |develop#locale], обеспечивая последовательное и локализованное отображение данных о времени на разных языках и в разных регионах. Фильтр принимает дату в виде временной метки UNIX, строки или объекта `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Если вы используете фильтр без параметров, он выведет дату в длинном формате, как объясняется далее.
+
+**а) Использование формата**
+
+Параметр `format` описывает, какие компоненты времени должны быть отображены. Он использует буквенные коды, причем количество повторений влияет на ширину вывода:
+
+| Год | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Месяц | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `авг.` / `август`
+| День | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `вс` / `воскресенье`
+| Час | `j` / `H` / `h` | предпочтительный / 24-часовой / 12-часовой
+| Минута | `m` / `mm` | `5` / `05` <small>(2 цифры в сочетании с секундами)</small>
+| Second | `s` / `ss` | `8` / `08` <small>(2 цифры в сочетании с минутами)</small>
+
+Порядок кодов в формате не имеет значения, так как порядок компонентов будет отображаться в соответствии с соглашениями локали. Таким образом, формат не зависит от локали. Например, формат `yyyyMMMMd` в локали `en_US` выводит `April 15, 2024`, а в локали `cs_CZ` - `15. dubna 2024`:
+
+| locale:  | ru-RU | en_US
+|---
+| `format: 'dMy'` | 10.08.2024 | 8/10/2024
+| `format: 'yM'` | 08.2024 | 8/2024
+| `format: 'yyyyMMMM'` | август 2024 г. | August 2024
+| `format: 'MMMM'` | август | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 PM | 5:54 PM
+
+
+**б) Использование предустановленных стилей**
+
+Параметры `date` и `time` определяют уровень детализации отображения даты и времени. Вы можете выбрать один из нескольких уровней: `full`, `long`, `medium`, `short`. Вы можете отображать только дату, только время или и то, и другое:
+
+| locale:  | ru-RU | en_US
+|---
+| `date: short` | 23.01.1978 | 1/23/78
+| `date: medium` | 23 янв. 1978 г. | Jan 23, 1978
+| `date: long` | 23 января 1978 г. | January 23, 1978
+| `date: full` | понедельник, 23 января 1978 г. | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 GMT+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.1978, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 янв. 1978 г., 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 января 1978 г. в 08:30 | January 23, 1978 at 8:30 AM
+
+Для даты можно также использовать префикс `relative-` (например, `relative-short`), который для дат, близких к текущей, отобразит `yesterday`, `today` или `tomorrow`; в противном случае отображение будет стандартным.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+См. также [дата |#date].
+
+
 lower .[filter]
 ---------------
 Преобразует значение в нижний регистр. Требуется расширение PHP `mbstring`.
@@ -416,8 +502,8 @@ nocheck .[filter]
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Печатные издания:
@@ -451,19 +537,67 @@ Unescaped: <b>hello</b>
 Неправильное использование фильтра `noescape` может привести к XSS-уязвимости! Никогда не используйте его, если вы не **абсолютно уверены** в том, что вы делаете, и что печатаемая строка получена из надежного источника.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Форматирует число до заданного количества знаков после запятой. Можно также указать символ десятичной точки и разделителя тысяч.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Форматирует число с указанным количеством знаков после запятой. Если задана [локаль |develop#locale], используются соответствующие десятичные и тысячные разделители.
 
 ```latte
-{1234.20 |number}              1,234
-{1234.20 |number:1}            1,234.2
-{1234.20 |number:2}            1,234.20
+{1234.20|number} 1,234
+{1234.20|number:1}            1,234.2
+{1234.20|number:2} 1,234.20
 {1234.20 |number:2, ',', ' '}  1 234,20
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Параметр `format` позволяет определить внешний вид чисел в точном соответствии с вашими потребностями. Для его использования требуется установленная [локаль |develop#locale]. Формат состоит из нескольких специальных символов, полное описание которых можно найти в документации "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> обязательная цифра, отображается всегда, даже если она равна нулю
+- `#` необязательная цифра, отображается только в том случае, если число имеет цифру на этом месте
+- `@` значащая цифра, помогает отобразить число с определенным количеством значащих цифр
+- `.` обозначает место, где должен находиться десятичный разделитель (запятая или точка, в зависимости от локали)
+- `,` используется для разделения групп цифр, обычно тысяч
+- `%` умножает число на 100 и добавляет знак процента
+
+Давайте рассмотрим несколько примеров. В первом примере два знака после запятой обязательны, во втором - необязательны. В третьем примере показаны прокладки с нулями с обеих сторон, а в четвертом - только существующие цифры:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Значимые цифры определяют, сколько цифр, независимо от десятичной точки, должно быть отображено, при необходимости округляя число:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Простой способ отобразить число в процентах. Число умножается на 100 и добавляется знак `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Мы можем задать разный формат для положительных и отрицательных чисел, разделенных знаком `;`. Таким образом, например, положительные числа могут отображаться со знаком `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Помните, что фактический вид чисел может меняться в зависимости от настроек локали. Например, в некоторых странах вместо точки в качестве десятичного разделителя используется запятая. Данный фильтр автоматически учитывает это, поэтому вам не нужно беспокоиться об этом.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Складывает строку определенной длины с другой строкой слева.
 
@@ -472,7 +606,7 @@ padLeft(int length, string pad = ' ') .[filter]
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Складывает строку определенной длины с другой строкой справа.
 
@@ -514,8 +648,8 @@ random .[filter]
 См. также [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Повторяет строку x раз.
 
 ```latte
@@ -523,7 +657,7 @@ repeat(int count) .[filter]
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Заменяет все вхождения строки поиска строкой замены.
 
@@ -538,7 +672,7 @@ replace(string|array search, string replace = '') .[filter]
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Заменяет все вхождения в соответствии с регулярным выражением.
 
@@ -559,8 +693,8 @@ reverse .[filter]
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Округляет число с заданной точностью.
 
 ```latte
@@ -573,7 +707,7 @@ round(int precision = 0) .[filter]
 См. также [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Извлекает фрагмент массива или строки.
 
@@ -591,9 +725,9 @@ slice(int start, int length = null, bool preserveKeys = false) .[filter]
 Filter по умолчанию переупорядочивает и сбрасывает ключи целочисленного массива. Это поведение можно изменить, установив preserveKeys в true. Строковые ключи всегда сохраняются, независимо от этого параметра.
 
 
-sort  .[filter]
----------------
-Фильтр, сортирующий массив и сохраняющий ассоциацию индексов.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Фильтр сортирует элементы массива или итератора с сохранением их ассоциативных ключей. Если задана [локаль |develop#locale], сортировка выполняется по ее правилам, если не указана пользовательская функция сравнения.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ sort  .[filter]
 {/foreach}
 ```
 
-В качестве параметра можно передать собственную функцию сравнения:
+Вы можете задать пользовательскую функцию сравнения для сортировки (в примере показана обратная сортировка от наибольшего к наименьшему):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Фильтр `|sort` также позволяет сортировать элементы по ключу:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Если вам нужно отсортировать таблицу по определенному столбцу, вы можете использовать параметр `by`. Значение `'name'` в примере указывает, что сортировка будет производиться по `$row->name` или `$row['name']`в зависимости от того, является ли `$row` массивом или объектом:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Вы также можете определить функцию обратного вызова, которая определяет значение для сортировки:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Параметр `byKey` можно использовать аналогичным образом.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ stripHtml .[filter]
 Полученный простой текст может естественно содержать символы, представляющие HTML-теги, например, `'&lt;p&gt;'|stripHtml` преобразуется в `<p>`. Никогда не выводите полученный текст с `|noescape`, так как это может привести к уязвимости системы безопасности.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Извлекает фрагмент строки. Этот фильтр был заменен фильтром [срезов |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ substr(int offset, int length = null) .[filter]
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Переводит выражения на другие языки. Чтобы сделать фильтр доступным, необходимо [настроить переводчик |develop#TranslatorExtension]. Вы также можете использовать [теги для перевода |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ translate(string message, ...args) .[filter]
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Вычеркивать ведущие и последующие символы, по умолчанию пробелы.
 
 ```latte
@@ -675,7 +835,7 @@ trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Сокращает строку до максимальной заданной длины, но старается сохранить целые слова. Если строка усечена, добавляет многоточие в конце (это можно изменить вторым параметром).
 
diff --git a/latte/ru/functions.texy b/latte/ru/functions.texy
index 27cbf161a6..f6ccc97b63 100644
--- a/latte/ru/functions.texy
+++ b/latte/ru/functions.texy
@@ -9,6 +9,8 @@
 | `divisibleBy`| [проверяет, делится ли переменная на число |#divisibleBy]
 | `even` | [проверяет, является ли данное число четным |#even]
 | `first` | [возвращает первый элемент массива или символ строки |#first]
+| `group` | [группирует данные по различным критериям |#group]
+| `hasBlock` | [обнаруживает существование блока |#hasBlock]
 | `last` | [возвращает последний элемент массива или символ строки |#last]
 | `odd` | [проверяет, является ли данное число нечетным |#odd]
 | `slice` | [извлекает фрагмент массива или строки |#slice]
@@ -73,8 +75,8 @@ even(int $value): bool .[method]
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Возвращает первый элемент массива или символ строки:
 
 ```latte
@@ -85,6 +87,36 @@ first(string|array $value): mixed .[method]
 См. также [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Эта функция группирует данные по различным критериям.
+
+В данном примере строки таблицы группируются по столбцу `categoryId`. На выходе получается массив полей, где ключом является значение в столбце `categoryId`. Ознакомьтесь с [подробной инструкцией |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+См. также [группу |filters#group] фильтров.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Проверяет, существует ли блок с указанным именем:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+См. также [Проверка существования блока |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Возвращает последний элемент массива или символ строки:
@@ -106,8 +138,8 @@ odd(int $value): bool .[method]
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Извлекает фрагмент массива или строки.
 
 ```latte
diff --git a/latte/ru/recipes.texy b/latte/ru/recipes.texy
index b978c389a8..35e0d01526 100644
--- a/latte/ru/recipes.texy
+++ b/latte/ru/recipes.texy
@@ -9,7 +9,7 @@
 
 - NetBeans IDE имеет встроенную поддержку
 - PhpStorm: установите [плагин Latte |https://plugins.jetbrains.com/plugin/7457-latte] в `Settings > Plugins > Marketplace`
-- VS Code: найдите в маркерплейсе плагин "Nette Latte + Neon"
+- VS Code: поиск маркерплейса для плагина [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] или [шаблонов Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Sublime Text 3: в Package Control найдите и установите пакет `Nette` и выберите Latte in `View > Syntax`
 - в старых редакторах используйте подсветку Smarty для файлов .latte
 
diff --git a/latte/ru/safety-first.texy b/latte/ru/safety-first.texy
index b2da171ab4..35b52cdb20 100644
--- a/latte/ru/safety-first.texy
+++ b/latte/ru/safety-first.texy
@@ -351,7 +351,7 @@ Latte автоматически проверяет, содержит ли пе
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Пишет:
diff --git a/latte/ru/syntax.texy b/latte/ru/syntax.texy
index 436d486851..a0408ab285 100644
--- a/latte/ru/syntax.texy
+++ b/latte/ru/syntax.texy
@@ -98,7 +98,7 @@ Prints:
 Или с помощью префикса `tag-` функциональность применяется только к HTML-тегам:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 В зависимости от значения переменной `$url` будет выведено следующее:
@@ -155,6 +155,20 @@ Latte позволяет вызывать фильтры с помощью зн
 ```
 
 
+Динамические HTML-теги .[#toc-dynamic-html-tags]
+================================================
+
+Latte поддерживает динамические HTML-теги, которые полезны, когда требуется гибкость в названиях тегов:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Например, приведенный выше код может генерировать `<h1>Heading</h1>` или `<h2>Heading</h2>` в зависимости от значения переменной `$level`. Динамические HTML-теги в Latte всегда должны быть парными. Их альтернативой является [n:tag |tags#n:tag].
+
+Поскольку Latte является безопасной системой шаблонизации, она проверяет, что результирующее имя тега является корректным и не содержит нежелательных или вредоносных значений. Также проверяется, что имя конечного тега всегда совпадает с именем открывающего тега.
+
+
 Комментарии .[#toc-comments]
 ============================
 
diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy
index 5b12995d91..f2c3e2a97b 100644
--- a/latte/ru/tags.texy
+++ b/latte/ru/tags.texy
@@ -16,6 +16,7 @@
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [условие ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [проверка наличия изменений |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [условие switch |#switch-case-default]
+| `n:else` | [альтернативное содержание условий |#n:else]
 
 .[table-latte-tags language-latte]
 |## Loops
@@ -97,8 +98,8 @@
 | `{link}` | [печатает ссылку |application:creating-links#In-the-Presenter-Template]
 | `{plink}` | [печатает ссылку на ведущего |application:creating-links#In-the-Presenter-Template]
 | `{control}` | [печатает компонент |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [фрагмент шаблона, который может быть отправлен с помощью AJAX |application:ajax#Tag-snippet]
-| `{snippetArea}` | конверт сниппетов
+| `{snippet}`... `{/snippet}` | [фрагмент шаблона, который может быть отправлен с помощью AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [конверт сниппетов |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [кэширует раздел шаблона |caching:#Caching-in-Latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@
 | `{input}` | [печатает элемент ввода формы |forms:rendering#label-input]
 | `{inputError}` | [печатает сообщение об ошибке для элемента ввода формы |forms:rendering#inputError]
 | `n:name` | [активирует элемент ввода HTML |forms:rendering#n:name]
-| `{formPrint}` | [генерирует чертеж формы Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [печатает PHP класс для данных формы |forms:in-presenter#Mapping-to-Classes]
-| `{formContext}`... `{/formContext}` | [частичный рендеринг формы |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [рендеринг контейнера формы |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Age: {date('Y') - $birth}<br>
 Отлично.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Если условие `{if} ... {/if}` записано в виде [атрибута n:attribute |syntax#n:attributes], то у вас есть возможность указать альтернативную ветвь с помощью `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Атрибут `n:else` также может использоваться в сочетании с. [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], и [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Age: {date('Y') - $birth}<br>
 Используйте условие `{ifset $var}`, чтобы определить, существует ли переменная (или несколько переменных) и имеет ли она ненулевое значение. На самом деле это то же самое, что и `if (isset($var))` в PHP. Как и любой парный тег, этот может быть записан в виде [n:attribute |syntax#n-attributes], поэтому покажем его на примере:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Age: {date('Y') - $birth}<br>
 `{iterateWhile}`
 ----------------
 
-Упрощает группировку линейных данных во время итерации в цикле foreach, выполняя итерацию во вложенном цикле до тех пор, пока выполняется условие. [Читайте инструкции в книге рецептов |cookbook/iteratewhile].
+Упрощает группировку линейных данных во время итерации в цикле foreach, выполняя итерацию во вложенном цикле до тех пор, пока не будет выполнено условие. [Ознакомьтесь с подробными инструкциями |cookbook/grouping].
 
 Он также может элегантно заменить `{first}` и `{last}` в примере выше:
 
@@ -489,6 +501,8 @@ Age: {date('Y') - $birth}<br>
 {/foreach}
 ```
 
+См. также [пакетные |filters#batch] и [групповые |filters#group] фильтры.
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ n:tag
 <h3 class="main">...</h3>
 ```
 
+Поскольку Latte является безопасной системой шаблонизации, она проверяет, что имя нового тега является корректным и не содержит никаких нежелательных или вредоносных значений.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/ru/template-inheritance.texy b/latte/ru/template-inheritance.texy
index e229486d33..20c62c1102 100644
--- a/latte/ru/template-inheritance.texy
+++ b/latte/ru/template-inheritance.texy
@@ -132,7 +132,7 @@
 
 - Если вы используете `{layout}` в шаблоне, он должен быть первым тегом шаблона в этом шаблоне.
 
-- Макет может [искаться автоматически |develop#automatic-layout-lookup] (как в [презентаторах |application:templates#search-for-templates]). В этом случае, если шаблон не должен иметь макета, он укажет на это с помощью тега `{layout none}`.
+- Макет может [искаться автоматически |develop#automatic-layout-lookup] (как в [презентаторах |application:templates#Template Lookup]). В этом случае, если шаблон не должен иметь макета, он укажет на это с помощью тега `{layout none}`.
 
 - Тег `{layout}` имеет псевдоним `{extends}`.
 
@@ -396,6 +396,14 @@ Hi, I am Mary.
 {/ifset}
 ```
 
+Информация о существовании блоков также возвращается функцией [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Советы .[#toc-tips]
 -------------------
@@ -415,7 +423,7 @@ Hi, I am Mary.
 Горизонтальное повторное использование `{import}` .{toc: Horizontal Reuse}
 ==========================================================================
 
-Горизонтальное повторное использование - это третий механизм повторного использования и наследования в Latte. Он позволяет загружать блоки из других шаблонов. Это похоже на создание PHP-файла с вспомогательными функциями или трейтом.
+Горизонтальное повторное использование - это третий механизм повторного использования и наследования в Latte. Он позволяет загружать блоки из других шаблонов. Это похоже на создание файла с вспомогательными функциями в PHP и последующую его загрузку с помощью `require`.
 
 Хотя наследование макетов шаблонов является одной из наиболее мощных возможностей Latte, оно ограничено простым наследованием - шаблон может расширять только один другой шаблон. Горизонтальное повторное использование - это способ достижения множественного наследования.
 
@@ -447,7 +455,7 @@ Hi, I am Mary.
 
 Вы можете использовать столько выражений `{import}`, сколько хотите, в любом данном шаблоне. Если два импортированных шаблона определяют один и тот же блок, побеждает первый. Однако наивысший приоритет отдается главному шаблону, который может перезаписать любой импортированный блок.
 
-Все переопределенные блоки можно включать постепенно, вставляя их в качестве [родительского блока |#Parent-Block]:
+Содержимое перезаписываемых блоков можно сохранить, вставив блок так же, как и [родительский блок |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/sl/@left-menu.texy b/latte/sl/@left-menu.texy
index ba4b8060d8..d54a3d14e9 100644
--- a/latte/sl/@left-menu.texy
+++ b/latte/sl/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Začetek |Guide]
 - [Zakaj uporabljati predloge? |why-use]
-- Pojmi
+- Pojmi ⚗️
 	- [Najprej varnost |Safety First]
 	- [Dedovanje predlog |Template Inheritance]
 	- [Sistem tipov |Type System]
 	- [Peskovnik |Sandbox]
 
-- Za oblikovalce
+- Za oblikovalce 🎨
 	- [Sintaksa |Syntax]
 	- [Oznake |Tags]
 	- [Filtri |Filters]
 	- [Funkcije |Functions]
 	- [Nasveti in triki |recipes]
 
-- Za razvijalce
+- Za razvijalce 🧮
 	- [Prakse za razvijalce |develop]
 	- [Razširitev Latte |Extending Latte]
 	- [Ustvarjanje razširitve |creating-extension]
 
-- [Kuharska knjiga |cookbook/@home]
+- [Kuharska knjiga 💡|cookbook/@home]
 	- [Migracija iz Twiga |cookbook/migration-from-twig]
 	- [... več |cookbook/@home]
 
diff --git a/latte/sl/cookbook/@home.texy b/latte/sl/cookbook/@home.texy
index d6d749e0e4..8285235217 100644
--- a/latte/sl/cookbook/@home.texy
+++ b/latte/sl/cookbook/@home.texy
@@ -4,7 +4,9 @@ Kuharska knjiga
 .[perex]
 Primeri kod in receptov za opravljanje običajnih opravil s programom Latte.
 
-- [Vse, kar ste vedno želeli vedeti o {iterateWhile} |iteratewhile]
+- [Smernice za razvijalce |/develop]
+- [Posredovanje spremenljivk med predlogami |passing-variables]
+- [Vse, kar ste vedno želeli vedeti o združevanju v skupine |grouping]
 - [Kako pisati poizvedbe SQL v Latte |how-to-write-sql-queries-in-latte]?
 - [Migracija iz PHP |migration-from-php]
 - [Migracija iz sistema Twig |migration-from-twig]
diff --git a/latte/sl/cookbook/grouping.texy b/latte/sl/cookbook/grouping.texy
new file mode 100644
index 0000000000..7184bd97c9
--- /dev/null
+++ b/latte/sl/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Vse, kar ste vedno želeli vedeti o združevanju v skupine
+********************************************************
+
+.[perex]
+Pri delu s podatki v predlogah pogosto naletite na potrebo po njihovem združevanju v skupine ali posebnem prikazu glede na določena merila. V ta namen Latte ponuja več zmogljivih orodij.
+
+Filter in funkcija `|group` omogočata učinkovito grupiranje podatkov na podlagi določenih meril, filter `|batch` olajša razdelitev podatkov v fiksne serije, oznaka `{iterateWhile}` pa ponuja možnost kompleksnejšega cikličnega nadzora s pogoji.
+Vsaka od teh oznak ponuja posebne možnosti za delo s podatki, zaradi česar sta nepogrešljivi orodji za dinamičen in strukturiran prikaz informacij v predlogah Latte.
+
+
+Filter in funkcija `group` .[#toc-filter-and-function-group]
+============================================================
+
+Predstavljajte si tabelo podatkovne zbirke `items` s predmeti, razdeljenimi v kategorije:
+
+| id | categoryId | name
+|------------------
+| 1 | 1 | Apple
+| 2 | 1 | Banana
+| 3 | 2 | PHP
+| 4 | 3 | zelena
+| 5 | 3 | rdeča
+| 6 | 3 | Modra
+
+Preprost seznam vseh elementov s predlogo Latte bi bil videti takole:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Če pa bi želeli, da so predmeti razvrščeni v skupine po kategorijah, jih moramo razdeliti tako, da ima vsaka kategorija svoj seznam. Rezultat bi bil potem videti takole:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Nalogo lahko enostavno in elegantno rešimo z uporabo spletne strani `|group`. Kot parameter navedemo `categoryId`, kar pomeni, da bodo elementi razdeljeni v manjša polja na podlagi vrednosti `$item->categoryId` (če bi bil `$item` polje, bi uporabili `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Filter lahko uporabimo tudi kot funkcijo v Latte, kar nam omogoča alternativno sintakso: `{foreach group($items, categoryId) ...}`.
+
+Če želite elemente razvrstiti v skupine glede na bolj zapletena merila, lahko v parametru filter uporabite funkcijo. Če bi na primer elemente grupirali glede na dolžino njihovega imena, bi bilo to videti takole:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Pomembno je opozoriti, da `$categoryItems` ni navadno polje, temveč objekt, ki se obnaša kot iterator. Za dostop do prvega elementa v skupini lahko uporabite [`first()` |latte:functions#first] funkcijo.
+
+Zaradi te prilagodljivosti pri grupiranju podatkov je `group` izjemno uporabno orodje za predstavitev podatkov v predlogah Latte.
+
+
+Vgnezdene zanke .[#toc-nested-loops]
+------------------------------------
+
+Recimo, da imamo tabelo v zbirki podatkov z drugim stolpcem `subcategoryId`, ki opredeljuje podkategorije za vsak element. Vsako glavno kategorijo želimo prikazati v ločenem `<ul>` seznamu, vsako podkategorijo pa v ločeni ugnezdeni zanki. `<ol>` seznamu:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Povezava s podatkovno bazo Nette .[#toc-connection-with-nette-database]
+-----------------------------------------------------------------------
+
+Pokažimo, kako učinkovito uporabiti združevanje podatkov v kombinaciji s podatkovno bazo Nette. Predpostavimo, da delamo s tabelo `items` iz začetnega primera, ki je prek stolpca `categoryId` povezana s to tabelo `categories`:
+
+| categoryId | name |
+|------------|------------|
+| 1 | Sadje |
+| 2 | Jeziki |
+| 3 | Barve |
+
+Podatke iz preglednice `items` naložimo z ukazom raziskovalca podatkov Nette Database Explorer `$items = $db->table('items')`. Med iteracijo nad temi podatki imamo možnost ne le dostopa do atributov, kot sta `$item->name` in `$item->categoryId`, temveč zaradi povezave s tabelo `categories` tudi do povezane vrstice v njej prek `$item->category`. Ta povezava lahko pokaže zanimive načine uporabe:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+V tem primeru uporabimo filter `|group` za združevanje po povezani vrstici `$item->category`, ne le po stolpcu `categoryId`. Tako dobimo `ActiveRow` dane kategorije v spremenljivki ključ, kar nam omogoča neposreden prikaz njenega imena z uporabo `{$category->name}`. To je praktični primer, kako lahko združevanje v skupine poenostavi predloge in olajša obdelavo podatkov.
+
+
+Filter `|batch` .[#toc-filter-batch]
+====================================
+
+Filter omogoča razdelitev seznama elementov v skupine z vnaprej določenim številom elementov. Ta filter je idealen v primerih, ko želite podatke predstaviti v več manjših skupinah, na primer zaradi boljše preglednosti ali vizualne organizacije na strani.
+
+Predstavljajte si, da imamo seznam elementov in jih želimo prikazati v seznamih, od katerih vsak vsebuje največ tri elemente. Uporaba filtra `|batch` je v takem primeru zelo praktična:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+V tem primeru je seznam `$items` razdeljen na manjše skupine, pri čemer vsaka skupina (`$batch`) vsebuje največ tri elemente. Vsaka skupina se nato prikaže v ločenem `<ul>` seznamu.
+
+Če zadnja skupina ne vsebuje dovolj elementov, da bi dosegli želeno število, lahko z drugim parametrom filtra določite, s čim bo ta skupina dopolnjena. To je idealno za estetsko poravnavo elementov, kjer bi nepopolna vrstica lahko bila videti neurejena.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Oznaka `{iterateWhile}` .[#toc-tag-iteratewhile]
+================================================
+
+Ista opravila, ki smo jih obravnavali s filtrom `|group`, bomo prikazali z uporabo oznake `{iterateWhile}`. Glavna razlika med pristopoma je, da `group` najprej obdela in združi vse vhodne podatke, medtem ko `{iterateWhile}` nadzoruje potek ciklov s pogoji, zato iteracija poteka zaporedno.
+
+Najprej narišemo tabelo s kategorijami z uporabo iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+Medtem ko `{foreach}` označuje zunanji del cikla, tj. risanje seznamov za vsako kategorijo, oznaka `{iterateWhile}` označuje notranji del, tj. posamezne elemente.
+Pogoj v končni oznaki pove, da se bo ponavljanje nadaljevalo, dokler trenutni in naslednji element pripadata isti kategoriji (`$iterator->nextValue` je [naslednji element |/tags#$iterator]).
+
+Če bi bil pogoj vedno izpolnjen, bi bili v notranjem ciklu narisani vsi elementi:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Rezultat bo videti takole:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Kako se na ta način uporablja iterateWhile? Ko je tabela prazna in ne vsebuje elementov, ni praznih `<ul></ul>` se izpiše.
+
+Če pogoj določimo v začetni oznaki `{iterateWhile}`, se obnašanje spremeni: pogoj (in prehod na naslednji element) se izvede na začetku notranjega cikla in ne na koncu.
+Tako, medtem ko vedno vnesemo `{iterateWhile}` brez pogojev, vnesemo `{iterateWhile $cond}` šele, ko je izpolnjen pogoj `$cond`. Hkrati se naslednji element zapiše v `$item`.
+
+To je uporabno na primer v primeru, ko želimo prvi element v vsaki kategoriji prikazati drugače, na primer takole:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Prvotno kodo spremenimo tako, da najprej prikažemo prvi element, nato pa v notranjem ciklu `{iterateWhile}` prikažemo druge elemente iz iste kategorije:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Znotraj enega cikla lahko ustvarimo več notranjih zank in jih celo ugnezdimo. Na ta način lahko na primer združimo podkategorije.
+
+Recimo, da ima tabela še en stolpec `subcategoryId`, in poleg tega, da je vsaka kategorija v ločenem `<ul>`, vsaka podkategorija v ločenem ciklu `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/sl/cookbook/iteratewhile.texy b/latte/sl/cookbook/iteratewhile.texy
deleted file mode 100644
index 16f20568ff..0000000000
--- a/latte/sl/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Vse, kar ste vedno želeli vedeti o {iterateWhile}
-*************************************************
-
-.[perex]
-Oznaka `{iterateWhile}` je primerna za različne trike v ciklih foreach.
-
-Recimo, da imamo naslednjo tabelo podatkovne zbirke, v kateri so predmeti razdeljeni v kategorije:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Seveda je risanje elementov v zanki foreach kot seznam enostavno:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Kaj pa storiti, če želite vsako kategorijo prikazati na ločenem seznamu? Z drugimi besedami, kako rešiti nalogo združevanja elementov z linearnega seznama v ciklu foreach. Rezultat mora biti videti takole:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Pokazali vam bomo, kako enostavno in elegantno lahko to nalogo rešimo z iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Medtem ko `{foreach}` označuje zunanji del cikla, tj. izris seznamov za vsako kategorijo, oznake `{iterateWhile}` označujejo notranji del, tj. posamezne elemente.
-Pogoj v končni oznaki pove, da se bo ponavljanje nadaljevalo, dokler trenutni in naslednji element pripadata isti kategoriji (`$iterator->nextValue` je [naslednji element |/tags#$iterator]).
-
-Če je pogoj vedno izpolnjen, so v notranjem ciklu narisani vsi elementi:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Rezultat bo videti takole:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Kaj dobrega prinaša takšna uporaba iterateWhile? Kako se razlikuje od rešitve, ki smo jo prikazali na samem začetku tega učbenika? Razlika je v tem, da če je tabela prazna in ne vsebuje nobenih elementov, se ne bo prikazala prazna `<ul></ul>`.
-
-
-Rešitev brez spletne strani `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-----------------------------------------------------------------------------------
-
-Če bi isto nalogo reševali s povsem osnovnimi konstrukcijami sistemov predlog, na primer v Twigu, Bladeu ali čistem PHP, bi bila rešitev videti nekako takole:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* kategorija se je spremenila *}
-
-		{* zapremo prejšnji <ul>, če to ni prvi element *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* odpremo nov seznam *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* zapremo zadnji seznam *}
-	</ul>
-{/if}
-```
-
-Vendar je ta koda nerazumljiva in neintuitivna. Povezava med začetnimi in zaključnimi oznakami HTML sploh ni jasna. Na prvi pogled ni jasno, ali gre za napako. In zahteva pomožne spremenljivke, kot je `$prevCatId`.
-
-V nasprotju s tem je rešitev s `{iterateWhile}` čista, jasna, ne potrebuje pomožnih spremenljivk in je zanesljiva.
-
-
-Pogoj v zaključni oznaki .[#toc-condition-in-the-closing-tag]
--------------------------------------------------------------
-
-Če določimo pogoj v začetni oznaki `{iterateWhile}`, se obnašanje spremeni: pogoj (in prehod na naslednji element) se izvede na začetku notranjega cikla in ne na koncu.
-Tako se `{iterateWhile}` brez pogoja vedno vnese, `{iterateWhile $cond}` pa se vnese šele, ko je izpolnjen pogoj `$cond`. Hkrati se v `$item` zapiše naslednji element.
-
-To je uporabno na primer v primeru, ko želite prvi element v vsaki kategoriji prikazati na drugačen način, npr:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Spremenimo prvotno kodo, v notranji zanki izrišemo prvi element in nato dodatne elemente iz iste kategorije `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Vgnezdene zanke .[#toc-nested-loops]
-------------------------------------
-
-V enem ciklu lahko ustvarimo več notranjih zank in jih celo ugnezdimo. Na ta način lahko na primer združimo podkategorije.
-
-Recimo, da je v preglednici še en stolpec `subCatId` in poleg tega, da je vsaka kategorija v ločenem `<ul>`, bo vsaka podkategorija v ločenem `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtriranje `|batch` .[#toc-filter-batch]
------------------------------------------
-
-Združevanje linearnih elementov v skupine omogoča tudi filter `batch`, in sicer v serije s fiksnim številom elementov:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Zamenjamo ga lahko z iterateWhile, kot sledi:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/sl/cookbook/passing-variables.texy b/latte/sl/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..71d23f9759
--- /dev/null
+++ b/latte/sl/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Posredovanje spremenljivk med predlogami
+****************************************
+
+V tem priročniku je pojasnjeno, kako se spremenljivke posredujejo med predlogami v Latte z uporabo različnih oznak, kot so `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` in druge. Naučili se boste tudi, kako delati s spremenljivkami v oznakah `{block}` in `{define}` ter kakšen je namen oznake `{parameters}`.
+
+
+Vrste spremenljivk .[#toc-types-of-variables]
+---------------------------------------------
+Spremenljivke v Latte lahko razdelimo v tri kategorije glede na to, kako in kje so opredeljene:
+
+**Vhodne spremenljivke** so tiste, ki se v predlogo posredujejo od zunaj, na primer iz skripte PHP ali z uporabo oznake, kot je `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Okoliške spremenljivke** so spremenljivke, ki obstajajo na lokaciji določene oznake. Sem spadajo vse vhodne spremenljivke in druge spremenljivke, ustvarjene z uporabo oznak, kot so `{var}`, `{default}`, ali znotraj zanke `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Izrecne spremenljivke** so tiste, ki so neposredno določene v oznaki in poslane ciljni predlogi.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Oznaka `{block}` se uporablja za opredelitev blokov kode, ki jih je mogoče ponovno uporabiti in jih prilagoditi ali razširiti v podedovanih predlogah. Okoliške spremenljivke, opredeljene pred blokom, so na voljo znotraj bloka, vendar se vse spremembe spremenljivk odražajo le znotraj tega bloka.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Oznaka `{define}` se uporablja za ustvarjanje blokov, ki se prikažejo le, če jih pokličete z uporabo `{include}`. Spremenljivke, ki so na voljo znotraj teh blokov, so odvisne od tega, ali so v definiciji določeni parametri. Če so parametri navedeni, so dostopni samo ti parametri. Če ne, so dostopne vse vhodne spremenljivke predloge, v kateri so bloki definirani.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Oznaka `{parameters}` se uporablja za izrecno prijavo pričakovanih vhodnih spremenljivk na začetku predloge. Tako lahko enostavno dokumentirate pričakovane spremenljivke in njihove podatkovne tipe. Prav tako je mogoče opredeliti privzete vrednosti.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Oznaka `{include file}` se uporablja za vstavljanje celotne predloge. Tej predlogi se posredujejo tako vhodne spremenljivke predloge, v kateri se uporablja oznaka, kot tudi izrecno določene spremenljivke. Vendar lahko ciljna predloga omeji področje uporabe z uporabo `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Pri vstavljanju bloka, definiranega v isti predlogi, se mu posredujejo vse okoliške in izrecno definirane spremenljivke:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+V tem primeru se spremenljivki `$name` in `$age` posredujeta bloku `blockName`. Enako se obnaša tudi `{include parent}`.
+
+Pri vstavljanju bloka iz druge predloge se posredujejo samo vhodne spremenljivke in izrecno določene spremenljivke. Okoliške spremenljivke niso samodejno na voljo.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` ali `{extends}`
+--------------------------
+Te oznake določajo postavitev, v katero se prenesejo vhodne spremenljivke podrejene predloge in spremenljivke, ustvarjene v kodi pred bloki:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Predloga `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Oznaka `{embed}` je podobna oznaki `{include}`, vendar omogoča vstavljanje blokov v predlogo. Za razliko od `{include}` se posredujejo samo izrecno deklarirane spremenljivke:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+V tem primeru ima predloga `menu.latte` dostop samo do spremenljivke `$items`.
+
+Nasprotno pa imajo bloki znotraj `{embed}` dostop do vseh okoliških spremenljivk:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Oznaka `{import}` se uporablja za nalaganje blokov iz drugih predlog. Uvoženim blokom se posredujejo vhodne in izrecno deklarirane spremenljivke.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Oznaka `{sandbox}` izolira predlogo za varno obdelavo. Spremenljivke se posredujejo izključno izrecno.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/sl/creating-extension.texy b/latte/sl/creating-extension.texy
index dcf41f3758..cfa9fb6bf3 100644
--- a/latte/sl/creating-extension.texy
+++ b/latte/sl/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// funkcija razčlenjevanja, ki za zdaj samo ustvari vozlišče
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Če ustvarjate novo oznako za Latte, je zanjo priporočljivo ustvariti poseben razred vozlišča, ki jo bo predstavljal v drevesu AST (glej razred `ForeachNode` v zgornjem primeru). V nekaterih primerih se vam bo morda zdel uporaben trivialni pomožni razred vozlišč [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], ki vam omogoča, da kot parametre konstruktorja posredujete telo metode `print()` in seznam vozlišč, do katerih je dostopna metoda `getIterator()`:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Prevajalnik prenese .[#toc-compiler-passes]
 ===========================================
 
diff --git a/latte/sl/develop.texy b/latte/sl/develop.texy
index 3eee56c049..e4dd654ce2 100644
--- a/latte/sl/develop.texy
+++ b/latte/sl/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Lokacija .[#toc-locale]{data-version:3.0.18}
+============================================
+
+Latte omogoča nastavitev lokalnega okolja, ki vpliva na oblikovanje številk, datumov in razvrščanje. Nastavlja se z metodo `setLocale()`. Identifikator locale sledi standardu jezikovnih oznak IETF, ki uporablja razširitev PHP `intl`. Sestavljen je iz kode jezika in po možnosti kode države, na primer `en_US` za angleščino v ZDA, `de_DE` za nemščino v Nemčiji itd.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Nastavitev locale vpliva na filtre [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] in [bytes |filters#bytes].
+
+.[note]
+Zahteva razširitev PHP `intl`. Nastavitev v Latte ne vpliva na globalno nastavitev locale v PHP.
+
+
 Strogi način .[#toc-strict-mode]{data-version:3.0.8}
 ====================================================
 
@@ -274,16 +290,25 @@ S parametrom `--strict` lahko aktivirate [strogi način|#strict mode].
 // vnesite dejansko pot do datoteke autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// tukaj dodajte posamezne razširitve
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// tukaj dodajte svoje posamezne razširitve
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Druga možnost je, da programu Linter posredujete svoj predmet `Latte\Engine`:
+
+```php
+$latte = new Latte\Engine;
+// tukaj konfiguriramo predmet $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Nalaganje predlog iz niza .[#toc-loading-templates-from-a-string]
 =================================================================
diff --git a/latte/sl/extending-latte.texy b/latte/sl/extending-latte.texy
index 791fe3bcee..b9479b5c87 100644
--- a/latte/sl/extending-latte.texy
+++ b/latte/sl/extending-latte.texy
@@ -68,6 +68,16 @@ Kot lahko vidite, funkcija kot naslednje argumente prejme levo stran filtra pred
 
 Seveda lahko funkcija, ki predstavlja filter, sprejme poljubno število parametrov, podprti pa so tudi variabilni parametri.
 
+Če filter vrne niz HTML, ga lahko označite, da ga Latte ne bo samodejno (in zato dvojno) eskapiral. S tem se izognete potrebi, da bi v predlogi določili `|noescape`.
+Najlažji način je, da niz zapakirate v objekt `Latte\Runtime\Html`, drugi način pa so [kontekstualni filtri |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+V tem primeru mora filter zagotoviti pravilno izpisovanje podatkov.
+
 
 Filtri z uporabo razreda .[#toc-filters-using-the-class]
 --------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// spremenimo tip vsebine v HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/sl/filters.texy b/latte/sl/filters.texy
index f031d784fb..0c462647d1 100644
--- a/latte/sl/filters.texy
+++ b/latte/sl/filters.texy
@@ -11,14 +11,16 @@ Filtri so funkcije, ki spremenijo ali oblikujejo podatke v želeno obliko. To je
 | `bytes` | [oblikuje velikost v bajtih |#bytes]
 | `clamp` | [vpne vrednost v območje |#clamp]
 | `dataStream` | [Pretvorba protokola URI podatkov |#datastream]
-| `date` | [oblikuje datum |#date]
+| `date` | [oblikovanje datuma in časa |#date]
 | `explode` | [razdeli niz z danim ločilom |#explode]
 | `first` | [vrne prvi element polja ali znak niza |#first]
+| `group` | [združevanje podatkov po različnih merilih |#group]
 | `implode` | [združi polje z nizom |#implode]
 | `indent` | [besedilo z leve strani odriva s številom tabulatorjev |#indent]
 | `join` | [združi polje z nizom |#implode]
 | `last` | [vrne zadnji element polja ali znak niza |#last]
 | `length` | [vrne dolžino niza ali polja |#length]
+| `localDate` | [oblikovanje datuma in časa v skladu z lokalnim jezikom |#localDate]
 | `number` | [oblikovanje števila |#number]
 | `padLeft` | [dopolni niz do dane dolžine z leve |#padLeft]
 | `padRight` | [dopolni niz do dane dolžine od desne |#padRight]
@@ -118,8 +120,8 @@ Filtri .[#toc-filters]
 ======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Filter, ki poenostavi navajanje linearnih podatkov v obliki tabele. Vrne polje z danim številom elementov. Če navedete drugi parameter, se ta uporabi za dopolnitev manjkajočih elementov v zadnji vrstici.
 
 ```latte
@@ -152,6 +154,8 @@ Izpisuje:
 </table>
 ```
 
+Oglejte si tudi oznako [group |#group] in [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Pred vse nove vrstice vstavi prelome vrstic HTML.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Oblikuje velikost v bajtih v človeku berljivo obliko.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Oblikuje velikost v bajtih v človeku razumljivo obliko. Če je nastavljen [lokalni jezik, |develop#locale] se uporabijo ustrezna decimalna ločila in ločila v tisočih.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Oblikuje velikost v bajtih v človeku berljivo obliko.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Zaokroži število do določene natančnosti.
 
 ```latte
@@ -203,8 +207,8 @@ Uveljavlja čiščenje URL-jev. Preveri, ali spremenljivka vsebuje spletni naslo
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Izpisuje:
@@ -217,8 +221,8 @@ Izpisuje:
 Glej tudi [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Vrne vrednost, ki je omejena na vključujoče območje min in max.
 
 ```latte
@@ -228,14 +232,14 @@ Vrne vrednost, ki je omejena na vključujoče območje min in max.
 Obstaja tudi kot [funkcija |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Pretvori vsebino v podatkovno shemo URI. Uporablja se lahko za vstavljanje slik v HTML ali CSS, ne da bi bilo treba povezovati zunanje datoteke.
 
 Imejmo sliko v spremenljivki `$img = Image::fromFile('obrazek.gif')`, potem
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 natisne na primer:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Zahteva razširitev PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Vrne datum v danem formatu z uporabo možnosti funkcij PHP [php:strftime] ali [php:date]. Filter dobi datum kot časovni žig UNIX, niz ali objekt tipa `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Oblikuje datum in čas v skladu z masko, ki jo uporablja funkcija PHP [php:date]. Filter sprejme datum v obliki časovnega žiga UNIX, kot niz ali kot objekt `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Glej tudi [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ Izbriše spremenljivko, ki se uporabi kot parameter v naslovu URL.
 Glej tudi [poizvedbo |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Razdeli niz z danim ločilom in vrne polje nizov. Vzdevek za `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Vrne prvi element polja ali znak niza:
 Glej tudi [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Zaokroži število do določene natančnosti.
 
 ```latte
@@ -330,8 +335,27 @@ Prvo črko vrednosti pretvori v veliko črko. Zahteva razširitev PHP `mbstring`
 Oglejte si tudi [velika začetnica |#capitalize], [mala |#lower] [začetnica |#capitalize], [velika |#upper] začetnica.
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Filter razvrsti podatke v skupine glede na različna merila.
+
+V tem primeru so vrstice v tabeli razvrščene po stolpcu `categoryId`. Rezultat je polje polj, kjer je ključ vrednost v stolpcu `categoryId`. Preberite [podrobna navodila |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Oglejte si tudi [paket |#batch], funkcijo [group |functions#group] in oznako [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Vrne niz, ki je sestavljen iz nizov v polju. Vzdevek za `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Uporabite lahko tudi vzdevek `join`:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Odmakne besedilo od leve strani za določeno število tabulatorjev ali drugih znakov, ki jih določimo v drugem neobveznem argumentu. Prazne vrstice se ne odrivajo.
 
 ```latte
@@ -396,6 +420,68 @@ Vrne dolžino niza ali polja.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Oblikuje datum in čas glede na [lokalno okolje, |develop#locale] kar zagotavlja dosleden in lokaliziran prikaz časovnih podatkov v različnih jezikih in regijah. Filter sprejme datum kot časovni žig UNIX, niz ali objekt `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Če filter uporabite brez parametrov, bo izpisal datum v dolgem formatu, kot je pojasnjeno v nadaljevanju.
+
+**a) Uporaba oblike**
+
+Parameter `format` opisuje, katere časovne komponente je treba prikazati. Uporablja črkovne kode, pri čemer število ponovitev vpliva na širino izpisa:
+
+| Leto | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Mesec | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `avg.` / `avgust`
+| Dan | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `ned.` / `nedelja`
+| Ura | `j` / `H` / `h` | prednostno / 24-urno / 12-urno
+| Minuta | `m` / `mm` | `5` / `05` <small>(2 števki v kombinaciji s sekundami)</small>
+| Sekunda | `s` / `ss` | `8` / `08` <small>(2 števki v kombinaciji z minutami)</small>
+
+Vrstni red kod v formatu ni pomemben, saj bo vrstni red komponent prikazan v skladu s konvencijami lokalnega okolja. Zato je oblika neodvisna od krajevnega okolja. Na primer, format `yyyyMMMMd` v lokalnem okolju `en_US` prikaže `April 15, 2024`, medtem ko v lokalnem okolju `cs_CZ` prikaže `15. dubna 2024`:
+
+| locale:  | sl-SI | en_US
+|---
+| `format: 'dMy'` | 10. 8. 2024 | 8/10/2024
+| `format: 'yM'` | 8/2024 | 8/2024
+| `format: 'yyyyMMMM'` | avgust 2024 | August 2024
+| `format: 'MMMM'` | avgust | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 pop. | 5:54 PM
+
+
+**b) Uporaba prednastavljenih slogov**
+
+Parametra `date` in `time` določata stopnjo podrobnosti prikaza datuma in časa. Izbirate lahko med več ravnmi: `full`, `long`, `medium`, `short`. Prikažete lahko samo datum, samo čas ali oboje:
+
+| locale:  | sl-SI | en_US
+|---
+| `date: short` | 23. 01. 78 | 1/23/78
+| `date: medium` | 23. jan. 1978 | Jan 23, 1978
+| `date: long` | 23. januar 1978 | January 23, 1978
+| `date: full` | ponedeljek, 23. januar 1978 | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 GMT+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23. 01. 78, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23. jan. 1978, 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23. januar 1978 ob 08:30 | January 23, 1978 at 8:30 AM
+
+Za datum lahko uporabite tudi predpono `relative-` (npr. `relative-short`), ki za datume blizu sedanjosti prikaže `yesterday`, `today` ali `tomorrow`; sicer se prikaže na standardni način.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Glejte tudi [datum |#date].
+
+
 lower .[filter]
 ---------------
 Pretvori vrednost v male črke. Zahteva razširitev PHP `mbstring`.
@@ -416,8 +502,8 @@ Preprečuje samodejno prečiščevanje URL. Latte [samodejno preveri, |safety-fi
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Izpisi:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 Zloraba filtra `noescape` lahko privede do ranljivosti XSS! Nikoli ga ne uporabljajte, razen če ste **trdno prepričani**, kaj počnete in da niz, ki ga tiskate, prihaja iz zaupanja vrednega vira.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Oblikuje število na določeno število decimalnih mest. Določite lahko tudi znak za decimalno vejico in ločilo tisočic.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Oblikuje število na določeno število decimalnih mest. Če je nastavljen [lokalni jezik, |develop#locale] se uporabijo ustrezna ločila za decimalke in tisočinke.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Oblikuje število na določeno število decimalnih mest. Določite lahko tudi zn
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+S parametrom `format` lahko videz številk določite točno po svojih potrebah. Zahteva nastavljeno [lokalno okolje |develop#locale]. Oblika je sestavljena iz več posebnih znakov, katerih popoln opis je na voljo v dokumentaciji "DecimalFormat"::https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns
+
+- <c id=6/> obvezna številka, ki je vedno prikazana, tudi če je enaka nič
+- `#` neobvezna števka, prikazana samo, če ima število na tem mestu števko
+- `@` pomembna števka, pomaga prikazati število z določenim številom pomembnih števk
+- `.` označuje, kje mora biti decimalno ločilo (vejica ali pika, odvisno od lokalnega okolja)
+- `,` se uporablja za ločevanje skupin številk, običajno tisočic
+- `%` pomnoži število s 100 in doda znak odstotka
+
+Oglejmo si nekaj primerov. V prvem primeru sta dve decimalki obvezni, v drugem pa neobvezni. Tretji primer prikazuje polnilo z ničlami na obeh straneh, četrti pa prikazuje samo obstoječe števke:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Pomembne števke določajo, koliko števk, ne glede na decimalno vejico, naj se prikaže, pri čemer se število po potrebi zaokroži:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Enostaven način za prikaz števila v odstotkih. Število pomnožimo s 100 in dodamo znak `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Za pozitivna in negativna števila, ločena z znakom `;`, lahko določimo drugačno obliko. Tako lahko na primer pozitivna števila prikažemo z znakom `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Ne pozabite, da se dejanski videz številk lahko razlikuje glede na nastavitve lokalnega okolja. V nekaterih državah se na primer namesto pike kot decimalno ločilo uporablja vejica. Ta filter to samodejno upošteva, zato vam ni treba skrbeti za to.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Podaljša niz do določene dolžine z drugim nizom z leve.
 
@@ -472,7 +606,7 @@ Podaljša niz do določene dolžine z drugim nizom z leve.
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Podloži niz na določeno dolžino z drugim nizom z desne.
 
@@ -514,8 +648,8 @@ Vrne naključni element polja ali znak niza:
 Glej tudi [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Ponovi niz x-krat.
 
 ```latte
@@ -523,7 +657,7 @@ Ponovi niz x-krat.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Zamenja vse pojavitve iskanega niza z nadomestnim nizom.
 
@@ -538,7 +672,7 @@ Izvede se lahko več zamenjav naenkrat:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Zamenja vse pojavitve v skladu z regularnim izrazom.
 
@@ -559,8 +693,8 @@ Obrne dani niz ali polje.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Zaokroži število na določeno natančnost.
 
 ```latte
@@ -573,7 +707,7 @@ Zaokroži število na določeno natančnost.
 Glej tudi [strop |#ceil], [dno |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Izvleče rezino polja ali niza.
 
@@ -591,9 +725,9 @@ Filter rezine deluje kot funkcija PHP `array_slice` za polja in `mb_substr` za n
 Filter bo privzeto spremenil vrstni red in ponastavil ključe celoštevilskega polja. To obnašanje lahko spremenite z nastavitvijo vrednosti preserveKeys na true. Vrstični ključi se vedno ohranijo, ne glede na ta parameter.
 
 
-sort  .[filter]
----------------
-Filter, ki razvrsti polje in ohrani povezavo indeksov.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Filter razvrsti elemente polja ali iteratorja, pri čemer ohrani njihove asociativne ključe. Ko je nastavljen [lokalni jezik, |develop#locale] razvrščanje sledi njegovim pravilom, razen če je določena primerjalna funkcija po meri.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Polje je razvrščeno v obratnem vrstnem redu.
 {/foreach}
 ```
 
-Kot parameter lahko posredujete svojo primerjalno funkcijo:
+Za razvrščanje lahko določite primerjalno funkcijo po meri (primer prikazuje, kako obrniti razvrščanje od največjega do najmanjšega):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Filter `|sort` omogoča tudi razvrščanje elementov po ključu:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Če želite tabelo razvrstiti po določenem stolpcu, lahko uporabite parameter `by`. Vrednost `'name'` v primeru določa, da se razvrščanje opravi po `$row->name` ali `$row['name']`, odvisno od tega, ali je `$row` polje ali objekt:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Določite lahko tudi funkcijo povratnega klica, ki določi vrednost, po kateri se bo razvrščalo:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Na enak način lahko uporabite tudi parameter `byKey`.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ Pretvarja HTML v navadno besedilo. To pomeni, da odstrani oznake HTML in pretvor
 Dobljeno navadno besedilo lahko seveda vsebuje znake, ki predstavljajo oznake HTML, na primer `'&lt;p&gt;'|stripHtml` se pretvori v `<p>`. Dobljenega besedila nikoli ne izpišite s `|noescape`, saj to lahko povzroči varnostno ranljivost.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Izvleče rezino niza. Ta filter je bil nadomeščen s filtrom za [rezine |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ Izvleče rezino niza. Ta filter je bil nadomeščen s filtrom za [rezine |#slice
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Prevaja izraze v druge jezike. Če želite, da je filter na voljo, morate [nastaviti prevajalnik |develop#TranslatorExtension]. Za [prevajanje |tags#Translation] lahko uporabite tudi [oznake |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ Prevaja izraze v druge jezike. Če želite, da je filter na voljo, morate [nasta
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Odstrani vodilne in končne znake, privzeto beli prostor.
 
 ```latte
@@ -675,7 +835,7 @@ Odstrani vodilne in končne znake, privzeto beli prostor.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Skrajša niz na največjo dovoljeno dolžino, vendar poskuša ohraniti cele besede. Če je niz skrajšan, na koncu doda elipso (to lahko spremenite z drugim parametrom).
 
diff --git a/latte/sl/functions.texy b/latte/sl/functions.texy
index f37f7176f4..38a1b37a6e 100644
--- a/latte/sl/functions.texy
+++ b/latte/sl/functions.texy
@@ -9,6 +9,8 @@ Poleg običajnih funkcij PHP lahko v predlogah uporabljate tudi te.
 | `divisibleBy`| [preveri, ali je spremenljivka deljiva s številom |#divisibleBy]
 | `even` | [preveri, ali je dano število sodo |#even]
 | `first` | [vrne prvi element polja ali znak niza |#first]
+| `group` | [združevanje podatkov po različnih merilih |#group]
+| `hasBlock` | [zazna obstoj bloka |#hasBlock]
 | `last` | [vrne zadnji element polja ali znak niza |#last]
 | `odd` | [preveri, ali je podano število liho |#odd]
 | `slice` | [izvleče rezino polja ali niza |#slice]
@@ -73,8 +75,8 @@ Preveri, ali je podano število sodo.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Vrne prvi element polja ali znak niza:
 
 ```latte
@@ -85,6 +87,36 @@ Vrne prvi element polja ali znak niza:
 Glej tudi [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Ta funkcija razvršča podatke v skupine glede na različna merila.
+
+V tem primeru so vrstice v tabeli združene po stolpcu `categoryId`. Rezultat je polje polj, kjer je ključ vrednost v stolpcu `categoryId`. Preberite [podrobna navodila |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Oglejte si tudi [skupino |filters#group] filtrov.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Preveri, ali obstaja blok z navedenim imenom:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Glej tudi [preverjanje obstoja bloka |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Vrne zadnji element polja ali znak niza:
@@ -106,8 +138,8 @@ Preveri, ali je podano število liho.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Izvleče rezino polja ali niza.
 
 ```latte
diff --git a/latte/sl/recipes.texy b/latte/sl/recipes.texy
index f9b3d43c7d..94203c290d 100644
--- a/latte/sl/recipes.texy
+++ b/latte/sl/recipes.texy
@@ -9,7 +9,7 @@ Predloge pišite v urejevalniku ali IDE, ki podpira Latte. Bilo bo veliko bolj p
 
 - V okolju NetBeans IDE je vgrajena podpora
 - PhpStorm: namestite [vtičnik Latte |https://plugins.jetbrains.com/plugin/7457-latte] v `Settings > Plugins > Marketplace`
-- Koda VS: iskanje v markerplaceu za vtičnik "Nette Latte + Neon"
+- VS koda: iskanje markerplace za [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ali [Nette Latte predloge |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin
 - Sublime Text 3: v Upravljanju paketov poiščite in namestite paket `Nette` ter izberite Latte v `View > Syntax`
 - V starih urejevalnikih uporabite Smartyjevo označevanje za datoteke .latte
 
diff --git a/latte/sl/safety-first.texy b/latte/sl/safety-first.texy
index 47770a5dac..e6fd55b0db 100644
--- a/latte/sl/safety-first.texy
+++ b/latte/sl/safety-first.texy
@@ -351,7 +351,7 @@ Latte samodejno preveri, ali spremenljivka, uporabljena v atributih `src` ali `h
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Napiše:
diff --git a/latte/sl/syntax.texy b/latte/sl/syntax.texy
index 64b197c208..c53cb2e597 100644
--- a/latte/sl/syntax.texy
+++ b/latte/sl/syntax.texy
@@ -98,7 +98,7 @@ Izpisi:
 S predpono `tag-` se funkcionalnost uporablja samo za oznake HTML:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Glede na vrednost spremenljivke `$url` se izpiše:
@@ -155,6 +155,20 @@ Ali neposredno na vrednosti (v kombinaciji z [`{=expr}` | https://latte.nette.or
 ```
 
 
+Dinamične oznake HTML .[#toc-dynamic-html-tags]
+===============================================
+
+Latte podpira dinamične oznake HTML, ki so uporabne, kadar je potrebna prilagodljivost imen oznak:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Zgornja koda lahko na primer ustvari `<h1>Heading</h1>` ali `<h2>Heading</h2>` odvisno od vrednosti spremenljivke `$level`. Dinamične oznake HTML v Latte morajo biti vedno v paru. Njihova alternativa je [n:tag |tags#n:tag].
+
+Ker je Latte varen sistem za oblikovanje predlog, preveri, ali je dobljeno ime oznake veljavno in ne vsebuje neželenih ali zlonamernih vrednosti. Prav tako zagotavlja, da je končno ime oznake vedno enako začetnemu imenu oznake.
+
+
 Komentarji .[#toc-comments]
 ===========================
 
diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy
index c619c4a3ff..9030ab77a4 100644
--- a/latte/sl/tags.texy
+++ b/latte/sl/tags.texy
@@ -16,6 +16,7 @@ Povzetek in opis vseh vgrajenih oznak Latte.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [pogoj ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [testiranje, ali je prišlo do spremembe |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [pogoj switch |#switch-case-default]
+| `n:else` | [alternativna vsebina za pogoje |#n:else]
 
 .[table-latte-tags language-latte]
 |### zanke
@@ -97,8 +98,8 @@ Povzetek in opis vseh vgrajenih oznak Latte.
 | `{link}` | [izpiše povezavo |application:creating-links#In the Presenter Template]
 | `{plink}` | [natisne povezavo do predvajalnika |application:creating-links#In the Presenter Template]
 | `{control}` | [natisne komponento |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [odlomek predloge, ki se lahko pošlje z AJAXom |application:ajax#tag-snippet]
-| `{snippetArea}` | ovojnica snippets
+| `{snippet}`... `{/snippet}` | [odlomek predloge, ki se lahko pošlje z AJAXom |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [ovojnica snippets |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [predpomnilnik oddelka predloge |caching:en#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Povzetek in opis vseh vgrajenih oznak Latte.
 | `{input}` | [natisne vhodni element obrazca |forms:rendering#label-input]
 | `{inputError}` | [izpiše sporočilo o napaki za vhodni element obrazca |forms:rendering#inputError]
 | `n:name` | [aktivira vnosni element HTML |forms:rendering#n:name]
-| `{formPrint}` | [ustvari načrt obrazca Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [izpiše razred PHP za podatke obrazca |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [delni prikaz obrazca |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [upodabljanje vsebnika obrazca |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Ali veste, da lahko n:atributom dodate predpono `tag-`? Potem bo pogoj vplival s
 Lepo.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Če pogoj `{if} ... {/if}` zapišete v obliki [n:atributa |syntax#n:attributes], imate možnost določiti alternativno vejo z uporabo `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Atribut `n:else` lahko uporabite tudi v povezavi z [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], in [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Glej tudi [`{ifset block}` |template-inheritance#checking-block-existence]
 Pogoj `{ifset $var}` uporabite za ugotavljanje, ali spremenljivka (ali več spremenljivk) obstaja in ima vrednost, ki ni ničelna. To je pravzaprav enako kot `if (isset($var))` v PHP. Kot vsako parno oznako lahko tudi to zapišemo v obliki [n:atribut |syntax#n:attributes], zato jo prikažimo na primeru:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ To je precej praktično, kajne?
 `{iterateWhile}`
 ----------------
 
-Poenostavlja grupiranje linearnih podatkov med iteracijo v zanki foreach tako, da izvaja iteracijo v ugnezdeni zanki, dokler je pogoj izpolnjen. [Preberite navodila v kuharski knjigi |cookbook/iteratewhile].
+Poenostavi razvrščanje linearnih podatkov v skupine med iteracijo v zanki foreach z iteracijo v ugnezdeni zanki, dokler ni izpolnjen pogoj. [Preberite podrobna navodila |cookbook/grouping].
 
 Elegantno lahko nadomesti tudi `{first}` in `{last}` v zgornjem primeru:
 
@@ -489,6 +501,8 @@ Elegantno lahko nadomesti tudi `{first}` in `{last}` v zgornjem primeru:
 {/foreach}
 ```
 
+Oglejte si tudi [paketne |filters#batch] in [skupinske |filters#group] filtre.
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Atribut `n:tag` lahko dinamično spremeni ime elementa HTML.
 <h3 class="main">...</h3>
 ```
 
+Ker je Latte varen sistem za oblikovanje predlog, preveri, ali je ime nove oznake veljavno in ne vsebuje neželenih ali zlonamernih vrednosti.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/sl/template-inheritance.texy b/latte/sl/template-inheritance.texy
index 1962057513..dde9554882 100644
--- a/latte/sl/template-inheritance.texy
+++ b/latte/sl/template-inheritance.texy
@@ -132,7 +132,7 @@ Tukaj je nekaj nasvetov za delo z dedovanjem postavitve:
 
 - Če v predlogi uporabite `{layout}`, mora biti to prva oznaka v predlogi.
 
-- Postavitev lahko [iščete samodejno |develop#automatic-layout-lookup] (kot v [predstavitvah |application:templates#search-for-templates]). Če v tem primeru predloga ne sme imeti postavitve, se to označi z oznako `{layout none}`.
+- Postavitev lahko [iščete samodejno |develop#automatic-layout-lookup] (kot v [predstavitvah |application:templates#Template Lookup]). Če v tem primeru predloga ne sme imeti postavitve, se to označi z oznako `{layout none}`.
 
 - Oznaka `{layout}` ima vzdevek `{extends}`.
 
@@ -396,6 +396,14 @@ Kot ime bloka lahko uporabite spremenljivko ali kateri koli izraz v jeziku PHP.
 {/ifset}
 ```
 
+Obstoj blokov vrne tudi funkcija [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Nasveti .[#toc-tips]
 --------------------
@@ -415,7 +423,7 @@ Tukaj je nekaj nasvetov za delo z bloki:
 Vodoravna ponovna uporaba `{import}` .{toc: Horizontal Reuse}
 =============================================================
 
-Horizontalna ponovna uporaba je tretji mehanizem ponovne uporabe in dedovanja v Latte. Omogoča nalaganje blokov iz drugih predlog. To je podobno ustvarjanju datoteke PHP s pomožnimi funkcijami ali lastnostmi.
+Horizontalna ponovna uporaba je tretji mehanizem za ponovno uporabo in dedovanje v Latte. Omogoča nalaganje blokov iz drugih predlog. Podobno je, kot če bi v PHP ustvarili datoteko s pomožnimi funkcijami in jo nato naložili z uporabo spletne strani `require`.
 
 Čeprav je dedovanje postavitve predloge ena od najmočnejših funkcij sistema Latte, je omejeno na preprosto dedovanje - predloga lahko razširi le eno drugo predlogo. Horizontalna ponovna uporaba je način za doseganje večkratnega dedovanja.
 
@@ -447,7 +455,7 @@ Oznaka `{import}` mora biti prva oznaka predloge za `{layout}`. Ime predloge je
 
 V posamezni predlogi lahko uporabite poljubno število izrazov `{import}`. Če dve uvoženi predlogi definirata isti blok, zmaga prva. Vendar ima največjo prednost glavna predloga, ki lahko prepiše kateri koli uvoženi blok.
 
-Vse prepisane bloke lahko postopoma vključite tako, da jih vstavite kot [nadrejeni blok |#parent block]:
+Vsebino prepisanih blokov lahko ohranite tako, da blok vstavite na enak način kot [nadrejeni blok |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/tr/@left-menu.texy b/latte/tr/@left-menu.texy
index 297637d462..cae1d20ce9 100644
--- a/latte/tr/@left-menu.texy
+++ b/latte/tr/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Başlarken |Guide]
 - [Neden Şablon Kullanmalı? |why-use]
-- Kavramlar
+- Kavramlar ⚗️
 	- [Önce Güvenlik |Safety First]
 	- [Şablon Kalıtımı |Template Inheritance]
 	- [Tip Sistem |Type System]
 	- [Sandbox |Sandbox]
 
-- Tasarımcılar için
+- Tasarımcılar için 🎨
 	- [Sözdizimi |Syntax]
 	- [Etiketler |Tags]
 	- [Filtreler |Filters]
 	- [Fonksiyonlar |Functions]
 	- [İpuçları ve Püf Noktaları|recipes]
 
-- Geliştiriciler için
+- Geliştiriciler için 🧮
 	- [Geliştiriciler için Uygulamalar |develop]
 	- [Uzayan Latte |Extending Latte]
 	- [Uzantı Oluşturma |creating-extension]
 
-- [Yemek Kitabı |cookbook/@home]
+- [Yemek Kitabı 💡|cookbook/@home]
 	- [Twig'den geçiş |cookbook/migration-from-twig]
 	- [... daha fazla |cookbook/@home]
 
diff --git a/latte/tr/cookbook/@home.texy b/latte/tr/cookbook/@home.texy
index 8ffcd3e435..ee33707cb2 100644
--- a/latte/tr/cookbook/@home.texy
+++ b/latte/tr/cookbook/@home.texy
@@ -4,7 +4,9 @@ Yemek Kitabı
 .[perex]
 Latte ile ortak görevleri gerçekleştirmek için örnek kodlar ve tarifler.
 
-- [{iterateWhile} Hakkında Her Zaman Bilmek İstediğiniz Her Şey |iteratewhile]
+- [Geliştirici yönergeleri |/develop]
+- [Şablonlar arasında değişkenleri geçirme |passing-variables]
+- [Gruplama hakkında her zaman bilmek istediğiniz her şey |grouping]
 - [Latte'de SQL sorguları nasıl yazılır? |how-to-write-sql-queries-in-latte]
 - [PHP'den geçiş |migration-from-php]
 - [Twig'den geçiş |migration-from-twig]
diff --git a/latte/tr/cookbook/grouping.texy b/latte/tr/cookbook/grouping.texy
new file mode 100644
index 0000000000..6459cc559d
--- /dev/null
+++ b/latte/tr/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Gruplama Hakkında Her Zaman Bilmek İstediğiniz Her Şey
+******************************************************
+
+.[perex]
+Şablonlardaki verilerle çalışırken, bunları gruplama veya belirli kriterlere göre özel olarak görüntüleme ihtiyacıyla sık sık karşılaşırsınız. Bu amaçla, Latte birkaç güçlü araç sunar.
+
+Filtre ve fonksiyon `|group` belirli kriterlere göre etkin veri gruplandırması sağlarken, `|batch` filtresi verileri sabit gruplara ayırmayı kolaylaştırır ve `{iterateWhile}` etiketi koşullarla daha karmaşık döngü kontrolü imkanı sağlar.
+Bu etiketlerin her biri verilerle çalışmak için özel seçenekler sunarak Latte şablonlarında dinamik ve yapılandırılmış bilgi gösterimi için vazgeçilmez araçlar haline getirir.
+
+
+Filtre ve işlev `group` .[#toc-filter-and-function-group]
+=========================================================
+
+Kategorilere ayrılmış öğeler içeren bir veritabanı tablosu `items` hayal edin:
+
+| id | kategoriId | isim
+|------------------
+| 1 | 1 | Elma
+| 2 | 1 | Muz
+| 3 | 2 | PHP
+| 4 | 3 | Yeşil
+| 5 | 3 | Kırmızı
+| 6 | 3 | Mavi
+
+Latte şablonunu kullanan tüm öğelerin basit bir listesi şöyle görünecektir:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Ancak, öğelerin kategorilere göre gruplar halinde düzenlenmesini istiyorsak, bunları her kategorinin kendi listesi olacak şekilde bölmemiz gerekir. Bu durumda sonuç şöyle olacaktır:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Bu görev `|group` kullanılarak kolayca ve zarif bir şekilde çözülebilir. Parametre olarak `categoryId` belirtiyoruz, yani öğeler `$item->categoryId` değerine göre daha küçük dizilere bölünecek ( `$item` bir dizi olsaydı `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Filtre, Latte'de bir fonksiyon olarak da kullanılabilir ve bize alternatif bir sözdizimi sunar: `{foreach group($items, categoryId) ...}`.
+
+Öğeleri daha karmaşık ölçütlere göre gruplamak istiyorsanız filtre parametresinde bir işlev kullanabilirsiniz. Örneğin, öğeleri adlarının uzunluğuna göre gruplamak şu şekilde görünecektir:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+ `$categoryItems` adresinin normal bir dizi değil, yineleyici gibi davranan bir nesne olduğuna dikkat etmek önemlidir. Gruptaki ilk öğeye erişmek için [`first()` |latte:functions#first] fonksiyon.
+
+Veri gruplamadaki bu esneklik, `group` adresini Latte şablonlarında veri sunmak için son derece kullanışlı bir araç haline getirmektedir.
+
+
+İç İçe Döngüler .[#toc-nested-loops]
+------------------------------------
+
+Diyelim ki her bir öğe için alt kategorileri tanımlayan `subcategoryId` sütununa sahip bir veritabanı tablomuz var. Her ana kategoriyi ayrı bir tabloda görüntülemek istiyoruz. `<ul>` listesini ve her bir alt kategoriyi ayrı bir yuvalanmış `<ol>` Liste:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Nette Veritabanı ile Bağlantı .[#toc-connection-with-nette-database]
+--------------------------------------------------------------------
+
+Veri gruplandırmanın Nette Database ile birlikte nasıl etkin bir şekilde kullanılacağını gösterelim. İlk örnekteki `items` tablosuyla çalıştığımızı ve `categoryId` sütunu aracılığıyla bu `categories` tablosuna bağlandığımızı varsayalım:
+
+| kategoriId | isim |
+|------------|------------|
+| 1 | Meyveler |
+| 2 | Diller |
+| 3 | Renkler |
+
+Nette Database Explorer komutunu kullanarak `items` tablosundan veri yüklüyoruz `$items = $db->table('items')`. Bu veriler üzerinde yineleme yaparken, yalnızca `$item->name` ve `$item->categoryId` gibi özniteliklere değil, `categories` tablosuyla olan bağlantı sayesinde, `$item->category` aracılığıyla ilgili satıra da erişme fırsatına sahibiz. Bu bağlantı ilginç kullanımlar sergileyebilir:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Bu durumda, sadece `categoryId` sütununa göre değil, bağlı `$item->category` satırına göre gruplamak için `|group` filtresini kullanırız. Bu bize değişken anahtarında verilen kategorinin `ActiveRow` adresini verir ve `{$category->name}` adresini kullanarak doğrudan adını görüntülememize olanak tanır. Bu, gruplamanın şablonları nasıl basitleştirebileceğini ve veri işlemeyi nasıl kolaylaştırabileceğini gösteren pratik bir örnektir.
+
+
+Filtre `|batch` .[#toc-filter-batch]
+====================================
+
+Filtre, bir öğe listesini önceden belirlenmiş sayıda öğe içeren gruplara ayırmanıza olanak tanır. Bu filtre, örneğin sayfada daha iyi netlik veya görsel düzenleme için verileri birkaç küçük grup halinde sunmak istediğiniz durumlar için idealdir.
+
+Elimizde bir öğe listesi olduğunu ve bunları her biri en fazla üç öğe içeren listeler halinde görüntülemek istediğimizi düşünün. Böyle bir durumda `|batch` filtresini kullanmak çok pratiktir:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+Bu örnekte, `$items` listesi, her grup (`$batch`) en fazla üç öğe içerecek şekilde daha küçük gruplara bölünmüştür. Her grup daha sonra ayrı bir `<ul>` Liste.
+
+Son grup istenen sayıya ulaşmak için yeterli öğe içermiyorsa, filtrenin ikinci parametresi bu grubun ne ile tamamlanacağını tanımlamanıza olanak tanır. Bu, tamamlanmamış bir satırın düzensiz görünebileceği öğeleri estetik olarak hizalamak için idealdir.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Etiket `{iterateWhile}` .[#toc-tag-iteratewhile]
+================================================
+
+ `|group` filtresi ile ele aldığımız aynı görevleri `{iterateWhile}` etiketini kullanarak göstereceğiz. İki yaklaşım arasındaki temel fark, `group` ilk olarak tüm girdi verilerini işler ve gruplandırırken, `{iterateWhile}` döngülerin ilerlemesini koşullarla kontrol eder, böylece yineleme sırayla gerçekleşir.
+
+İlk olarak, iterateWhile kullanarak kategorileri içeren bir tablo çiziyoruz:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+ `{foreach}` etiketi döngünün dış kısmını, yani her bir kategori için çizim listelerini işaretlerken, `{iterateWhile}` etiketi iç kısmı, yani tek tek öğeleri işaretler.
+End etiketindeki koşul, mevcut ve sonraki öğe aynı kategoriye ait olduğu sürece tekrarlamanın devam edeceğini söyler (`$iterator->nextValue` [sonraki öğ |/tags#$iterator]edir).
+
+Koşul her zaman karşılanmış olsaydı, tüm öğeler iç döngüde çizilirdi:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Sonuç şu şekilde görünecektir:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+iterateWhile'ın bu şekilde kullanımı nedir? Tablo boş olduğunda ve hiçbir öğe içermediğinde, boş `<ul></ul>` basıldı.
+
+Eğer koşulu `{iterateWhile}` etiketinin açılışında belirtirsek, davranış değişir: koşul (ve bir sonraki öğeye geçiş) iç döngünün sonunda değil başında gerçekleştirilir.
+Böylece, `{iterateWhile}` adresine her zaman koşulsuz olarak girerken, `{iterateWhile $cond}` adresine yalnızca `$cond` koşulu karşılandığında girersiniz. Ve aynı zamanda, bir sonraki öğe `$item` adresine yazılır.
+
+Bu, örneğin, her kategorideki ilk öğeyi farklı şekilde oluşturmak istediğimiz bir durumda kullanışlıdır:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Orijinal kodu, önce ilk öğeyi oluşturacak ve ardından iç döngüde `{iterateWhile}` aynı kategorideki diğer öğeleri oluşturacak şekilde değiştiriyoruz:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+Bir döngü içinde birden fazla iç döngü oluşturabilir ve hatta bunları iç içe geçirebiliriz. Bu şekilde, örneğin alt kategoriler gruplandırılabilir.
+
+Tabloda başka bir sütun olduğunu varsayalım `subcategoryId` ve her kategorinin ayrı bir kategoride olmasının yanı sıra `<ul>`her bir alt kategori ayrı bir `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/tr/cookbook/iteratewhile.texy b/latte/tr/cookbook/iteratewhile.texy
deleted file mode 100644
index 97e04321c0..0000000000
--- a/latte/tr/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-iterateWhile} Hakkında Her Zaman Bilmek İstediğiniz Her Şey
-***********************************************************
-
-.[perex]
-`{iterateWhile}` etiketi foreach döngülerinde çeşitli hileler için uygundur.
-
-Öğelerin kategorilere ayrıldığı aşağıdaki veritabanı tablosuna sahip olduğumuzu varsayalım:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Elbette, bir foreach döngüsündeki öğeleri liste olarak çizmek kolaydır:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Ancak her kategoriyi ayrı bir listede işlemek istiyorsanız ne yapmalısınız? Başka bir deyişle, doğrusal bir listedeki öğeleri bir foreach döngüsü içinde gruplama görevi nasıl çözülür? Çıktı şöyle görünmelidir:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-iterateWhile ile bu görevin ne kadar kolay ve zarif bir şekilde çözülebileceğini göstereceğiz:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-`{foreach}` döngünün dış kısmını, yani her kategori için listelerin çizilmesini işaret ederken, `{iterateWhile}` etiketleri iç kısmı, yani tek tek öğeleri gösterir.
-Bitiş etiketindeki koşul, mevcut ve bir sonraki [öğe |/tags#$iterator] aynı kategoriye ait olduğu sürece tekrarın devam edeceğini söyler (`$iterator->nextValue` bir sonraki öğedir).
-
-Koşul her zaman karşılanırsa, tüm öğeler iç döngüde çizilir:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Sonuç şu şekilde görünecektir:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-iterateWhile'ın böyle bir kullanımı ne işe yarar? Bu eğitimin en başında gösterdiğimiz çözümden ne farkı var? Aradaki fark, tablo boşsa ve herhangi bir öğe içermiyorsa, boş olarak işlenmeyecektir `<ul></ul>`.
-
-
-`{iterateWhile}` Olmadan Çözüm .[#toc-solution-without-iteratewhile]
---------------------------------------------------------------------
-
-Aynı görevi şablon sistemlerinin tamamen temel yapılarıyla, örneğin Twig, Blade veya saf PHP ile çözmüş olsaydık, çözüm şuna benzer bir şey olurdu:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* kategori değişti *}
-
-		{* <ul> ilk öğe değilse</ul>bir öncekini kapatıyoruz <ul>*}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-Ancak, bu kod anlaşılmaz ve sezgisel değildir. Açılış ve kapanış HTML etiketleri arasındaki bağlantı hiç açık değildir. Bir hata olup olmadığı ilk bakışta anlaşılmıyor. Ve `$prevCatId` gibi yardımcı değişkenler gerektirir.
-
-Buna karşılık, `{iterateWhile}` ile çözüm temiz, net, yardımcı değişkenlere ihtiyaç duymaz ve hatasızdır.
-
-
-Kapanış Etiketindeki Koşul .[#toc-condition-in-the-closing-tag]
----------------------------------------------------------------
-
-Açılış etiketinde bir koşul belirtirsek `{iterateWhile}`, davranış değişir: koşul (ve bir sonraki öğeye ilerleme) iç döngünün sonunda değil başında yürütülür.
-Böylece, koşul olmadan `{iterateWhile}` her zaman girilirken, `{iterateWhile $cond}` yalnızca `$cond` koşulu karşılandığında girilir. Aynı zamanda, aşağıdaki eleman `$item` adresine yazılır.
-
-Bu, örneğin, her kategorideki ilk öğeyi farklı bir şekilde oluşturmak istediğiniz bir durumda kullanışlıdır:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Orijinal kodu değiştirelim, `{iterateWhile}` iç döngüsünde ilk öğeyi ve ardından aynı kategoriden ek öğeleri çizelim:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-İç İçe Döngüler .[#toc-nested-loops]
-------------------------------------
-
-Bir döngüde birden fazla iç döngü oluşturabilir ve hatta bunları iç içe yerleştirebiliriz. Bu şekilde, örneğin alt kategoriler gruplandırılabilir.
-
-Tabloda başka bir sütun olduğunu varsayalım `subCatId` ve her kategorinin ayrı bir kategoride olmasına ek olarak `<ul>`her bir alt kategori ayrı bir `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Filtre | yığın .[#toc-filter-batch]
------------------------------------
-
-Doğrusal öğelerin gruplandırılması da bir filtre tarafından sağlanır `batch`, sabit sayıda öğeye sahip gruplar halinde:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Aşağıdaki gibi iterateWhile ile değiştirilebilir:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/tr/cookbook/passing-variables.texy b/latte/tr/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..2cf84515a9
--- /dev/null
+++ b/latte/tr/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Değişkenleri Şablonlar Arasında Geçirme
+***************************************
+
+Bu kılavuzda, `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` ve diğerleri gibi çeşitli etiketler kullanılarak Latte'deki şablonlar arasında değişkenlerin nasıl aktarıldığı açıklanmaktadır. Ayrıca `{block}` ve `{define}` etiketlerindeki değişkenlerle nasıl çalışacağınızı ve `{parameters}` etiketinin amacını öğreneceksiniz.
+
+
+Değişken Türleri .[#toc-types-of-variables]
+-------------------------------------------
+Latte'deki değişkenler, nasıl ve nerede tanımlandıklarına bağlı olarak üç kategoriye ayrılabilir:
+
+**Giriş Değişkenleri** şablona dışarıdan, örneğin bir PHP betiğinden veya `{include}` gibi bir etiket kullanılarak aktarılan değişkenlerdir.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Çevreleyen Değişkenler** belirli bir etiketin bulunduğu yerde var olan değişkenlerdir. Bunlar, tüm girdi değişkenlerini ve `{var}`, `{default}` veya bir döngü içinde `{foreach}` gibi etiketler kullanılarak oluşturulan diğer değişkenleri içerir.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Açık Değişkenler** doğrudan bir etiket içinde belirtilen ve hedef şablona gönderilen değişkenlerdir.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+ `{block}` etiketi, devralınan şablonlarda özelleştirilebilen veya genişletilebilen yeniden kullanılabilir kod bloklarını tanımlamak için kullanılır. Bloktan önce tanımlanan çevreleyen değişkenler blok içinde kullanılabilir, ancak değişkenlerdeki herhangi bir değişiklik yalnızca bu blok içinde yansıtılır.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+ `{define}` etiketi, yalnızca `{include}` kullanılarak çağrıldığında işlenen bloklar oluşturmak için kullanılır. Bu blokların içinde bulunan değişkenler, tanımda parametrelerin belirtilip belirtilmediğine bağlıdır. Parametreler belirtilmişse, yalnızca bu parametrelere erişilebilir. Belirtilmemişse, blokların tanımlandığı şablonun tüm girdi değişkenlerine erişilebilir.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+ `{parameters}` etiketi, şablonun başında beklenen girdi değişkenlerini açıkça beyan etmek için kullanılır. Bu şekilde, beklenen değişkenleri ve veri türlerini kolayca belgeleyebilirsiniz. Varsayılan değerleri tanımlamak da mümkündür.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+ `{include file}` etiketi bir şablonun tamamını eklemek için kullanılır. Bu şablona hem etiketin kullanıldığı şablonun girdi değişkenleri hem de açıkça tanımlanmış değişkenler aktarılır. Ancak, hedef şablon `{parameters}` adresini kullanarak kapsamı sınırlayabilir.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+Aynı şablonda tanımlanmış bir blok eklenirken, tüm çevreleyen ve açıkça tanımlanmış değişkenler buna aktarılır:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+Bu örnekte, `$name` ve `$age` değişkenleri `blockName` bloğuna aktarılır. Aynı davranış `{include parent}` için de geçerlidir.
+
+Başka bir şablondan bir blok eklerken, yalnızca giriş değişkenleri ve açıkça tanımlanmış değişkenler aktarılır. Çevreleyen değişkenler otomatik olarak kullanılamaz.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` veya `{extends}`
+---------------------------
+Bu etiketler, alt şablonun girdi değişkenlerinin ve bloklardan önce kodda oluşturulan değişkenlerin geçirildiği bir düzen tanımlar:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Şablon `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+ `{embed}` etiketi `{include}` etiketine benzer ancak blokların şablona gömülmesine izin verir. `{include}` etiketinden farklı olarak, yalnızca açıkça bildirilen değişkenler aktarılır:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+Bu örnekte, `menu.latte` şablonunun yalnızca `$items` değişkenine erişimi vardır.
+
+Tersine, `{embed}` içindeki bloklar çevredeki tüm değişkenlere erişebilir:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+ `{import}` etiketi diğer şablonlardan blok yüklemek için kullanılır. Hem girdi hem de açıkça bildirilen değişkenler içe aktarılan bloklara aktarılır.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+ `{sandbox}` etiketi, şablonu güvenli işleme için izole eder. Değişkenler yalnızca açık olarak aktarılır.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/tr/creating-extension.texy b/latte/tr/creating-extension.texy
index db2b4410f8..72e4325109 100644
--- a/latte/tr/creating-extension.texy
+++ b/latte/tr/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// a parsing function that just creates a node for now
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Latte için yeni bir etiket oluşturuyorsanız, bunun için AST ağacında temsil edecek özel bir düğüm sınıfı oluşturmanız tavsiye edilir (yukarıdaki örnekte `ForeachNode` sınıfına bakın). Bazı durumlarda, `print()` yönteminin gövdesini ve `getIterator()` yöntemi tarafından erişilebilir kılınan düğümlerin listesini yapıcı parametreleri olarak geçirmenize olanak tanıyan önemsiz yardımcı düğüm sınıfı [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] 'u yararlı bulabilirsiniz:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Derleyici Geçişleri .[#toc-compiler-passes]
 ===========================================
 
diff --git a/latte/tr/develop.texy b/latte/tr/develop.texy
index d1c0485531..6def79178d 100644
--- a/latte/tr/develop.texy
+++ b/latte/tr/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Yerel .[#toc-locale]{data-version:3.0.18}
+=========================================
+
+Latte, sayıların, tarihlerin ve sıralamanın biçimlendirilmesini etkileyen yerel ayarı ayarlamanıza olanak tanır. `setLocale()` yöntemi kullanılarak ayarlanır. Yerel ayar tanımlayıcısı, PHP `intl` uzantısını kullanan IETF dil etiketi standardını izler. Bir dil kodu ve muhtemelen bir ülke kodundan oluşur, örneğin, ABD'deki İngilizce için `en_US`, Almanya'daki Almanca için `de_DE` vb.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+ [Yerel |filters#localDate] ayar, [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] ve [bytes |filters#bytes] filtrelerini etkiler.
+
+.[note]
+PHP `intl` eklentisini gerektirir. Latte'deki ayar PHP'deki global yerel ayarını etkilemez.
+
+
 Sıkı Mod .[#toc-strict-mode]{data-version:3.0.8}
 ================================================
 
@@ -274,16 +290,25 @@ vendor/bin/latte-lint <path>
 // autoload.php dosyasının gerçek yolunu girin
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// bireysel uzantıları buraya ekleyin
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// bireysel uzantılarınızı buraya ekleyin
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Alternatif olarak, kendi `Latte\Engine` nesnenizi Linter'a aktarabilirsiniz:
+
+```php
+$latte = new Latte\Engine;
+// burada $latte nesnesini yapılandırıyoruz
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Dizeden Şablon Yükleme .[#toc-loading-templates-from-a-string]
 ==============================================================
diff --git a/latte/tr/extending-latte.texy b/latte/tr/extending-latte.texy
index 51489c1c4a..cace18d2bb 100644
--- a/latte/tr/extending-latte.texy
+++ b/latte/tr/extending-latte.texy
@@ -68,6 +68,16 @@ Gördüğünüz gibi, fonksiyon `|` as the first argument and the arguments pass
 
 Elbette, filtreyi temsil eden fonksiyon herhangi bir sayıda parametre kabul edebilir ve değişken parametreler de desteklenir.
 
+Filtre HTML'de bir dize döndürürse, Latte'nin otomatik olarak (ve bu nedenle çift) kaçış yapmaması için işaretleyebilirsiniz. Bu, şablonda `|noescape` belirtme ihtiyacını ortadan kaldırır.
+En kolay yol dizeyi bir `Latte\Runtime\Html` nesnesine sarmaktır, diğer yol ise [Bağlamsal Filtrelerdir |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+Bu durumda, filtre verilerin doğru şekilde kaçmasını sağlamalıdır.
+
 
 Sınıfı Kullanan Filtreler .[#toc-filters-using-the-class]
 ---------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// içerik türünü HTML olarak değiştir
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/tr/filters.texy b/latte/tr/filters.texy
index c5715649be..4047c73ce4 100644
--- a/latte/tr/filters.texy
+++ b/latte/tr/filters.texy
@@ -11,14 +11,16 @@ Filtreler, verileri istediğimiz biçimde değiştiren veya biçimlendiren işle
 | `bytes` | [bayt cinsinden biçim boyutu |#bytes]
 | `clamp` | [değeri aralığa sıkıştırır |#clamp]
 | `dataStream` | [Veri URI protokol dönüşümü |#datastream]
-| `date` | [tarihi biçimlendirir |#date]
+| `date` | [tarih ve saati biçimlendirir |#date]
 | `explode` | [bir dizeyi verilen sınırlayıcıya göre böler |#explode]
 | `first` | [dizinin ilk elemanını veya karakter dizisini döndürür |#first]
+| `group` | [verileri çeşitli kriterlere göre gruplar |#group]
 | `implode` | [bir diziyi bir dizeye birleştirir|#implode]
 | `indent` | [metni soldan sekme sayısı kadar girintiler |#indent]
 | `join` | [bir diziyi bir dizeye birleştirir|#implode]
 | `last` | [dizinin son elemanını veya karakter dizisini döndürür |#last]
 | `length` | [bir dize veya dizinin uzunluğunu döndürür |#length]
+| `localDate` | [tarih ve saati yerel ayara göre biçimlendirir |#localDate]
 | `number` | [format numarası |#number]
 | `padLeft` | [dizeyi soldan verilen uzunluğa tamamlar |#padLeft]
 | `padRight` | [dizeyi sağdan verilen uzunluğa tamamlar |#padRight]
@@ -118,8 +120,8 @@ Filtreler .[#toc-filters]
 =========================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Doğrusal verilerin bir tablo biçiminde listelenmesini basitleştiren filtre. Verilen sayıda öğe içeren bir dizi döndürür. İkinci bir parametre sağlarsanız, bu son satırdaki eksik öğeleri doldurmak için kullanılır.
 
 ```latte
@@ -152,6 +154,8 @@ Baskılar:
 </table>
 ```
 
+Ayrıca bkz. [group |#group] ve [iterateWhile |tags#iterateWhile] etiketi.
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ Tüm yeni satırlardan önce HTML satır sonlarını ekler.
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Bayt cinsinden bir boyutu insan tarafından okunabilir biçimde biçimlendirir.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Bayt cinsinden boyutu insan tarafından okunabilir bir biçimde biçimlendirir. [Yerel |develop#locale] ayar belirlenmişse, ilgili ondalık ve binlik ayırıcılar kullanılır.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ Bayt cinsinden bir boyutu insan tarafından okunabilir biçimde biçimlendirir.
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Bir sayıyı belirli bir hassasiyete kadar yuvarlar.
 
 ```latte
@@ -203,8 +207,8 @@ URL sanitizasyonunu zorlar. Değişkenin bir web URL'si (yani HTTP/HTTPS protoko
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Baskılar:
@@ -217,8 +221,8 @@ Baskılar:
 Ayrıca bkz. [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Min ve maks. dahil aralığına sıkıştırılmış değeri döndürür.
 
 ```latte
@@ -228,14 +232,14 @@ Min ve maks. dahil aralığına sıkıştırılmış değeri döndürür.
 [Fonksiyon |functions#clamp] olarak da mevcuttur.
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 İçeriği veri URI şemasına dönüştürür. Harici dosyalara bağlantı vermeye gerek kalmadan HTML veya CSS'ye görüntü eklemek için kullanılabilir.
 
 `$img = Image::fromFile('obrazek.gif')` değişkeninde bir görüntüye sahip olalım, sonra
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Örneğin baskılar:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 PHP uzantısı gerektirir `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-[php:strftime] veya [php:date] PHP işlevlerinin seçeneklerini kullanarak verilen biçimde bir tarih döndürür. Süzgeç bir tarihi UNIX zaman damgası, bir dizge veya `DateTime` türünde bir nesne olarak alır.
+date(string $format) .[filter]
+------------------------------
+Tarih ve saati [php:date] PHP işlevi tarafından kullanılan maskeye göre biçimlendirir. Süzgeç, tarihi UNIX zaman damgası biçiminde, dize olarak veya `DateTimeInterface` nesnesi olarak kabul eder.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Ayrıca bkz. [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ URL'de parametre olarak kullanılacak bir değişkeni atar.
 Ayrıca [sorguya |#query] bakın.
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Bir dizeyi verilen sınırlayıcıya göre böler ve bir dizeler dizisi döndürür. İçin takma ad `split`.
 
 ```latte
@@ -306,8 +311,8 @@ Dizinin ilk elemanını veya karakter dizisini döndürür:
 Ayrıca bkz. [son |#last], [rastgele |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Bir sayıyı belirli bir hassasiyete yuvarlar.
 
 ```latte
@@ -330,8 +335,27 @@ Değerin ilk harfini büyük harfe dönüştürür. PHP eklentisi gerektirir `mb
 Ayrıca bkz. [büyük harf |#capitalize], [alt |#lower], [üst |#upper].
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Filtre, verileri farklı kriterlere göre gruplandırır.
+
+Bu örnekte, tablodaki satırlar `categoryId` sütununa göre gruplandırılmıştır. Çıktı, anahtarın `categoryId` sütunundaki değer olduğu bir dizi dizisidir. [Ayrıntılı talimatları |cookbook/grouping] okuyun.
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Ayrıca bkz. [batch |#batch], [group |functions#group] fonksiyonu ve [iterateWhile |tags#iterateWhile] etiketi.
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Dizideki dizelerin birleştirilmesinden oluşan bir dizge döndürür. İçin takma ad `join`.
 
 ```latte
@@ -346,8 +370,8 @@ Ayrıca `join` takma adını da kullanabilirsiniz:
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Bir metni soldan belirli sayıda sekme veya ikinci isteğe bağlı bağımsız değişkende belirttiğimiz diğer karakterler kadar girintiler. Boş satırlar girintilenmez.
 
 ```latte
@@ -396,6 +420,68 @@ Bir dize veya dizinin uzunluğunu döndürür.
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Tarih ve saati yerel [ayara |develop#locale] göre biçimlendirerek, zaman verilerinin farklı diller ve bölgeler arasında tutarlı ve yerelleştirilmiş bir şekilde görüntülenmesini sağlar. Filtre, tarihi UNIX zaman damgası, dize veya `DateTimeInterface` nesnesi olarak kabul eder.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Filtreyi herhangi bir parametre olmadan kullanırsanız, daha sonra açıklanacağı gibi tarihi uzun biçim düzeyinde verir.
+
+**a) Formatı kullanma**
+
+ `format` parametresi hangi zaman bileşenlerinin görüntülenmesi gerektiğini açıklar. Tekrar sayısının çıktının genişliğini etkilediği harf kodlarını kullanır:
+
+| Yıl | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Ay | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `Ağu` / `Ağustos`
+| Gün | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `Paz` / `Pazar`
+| Saat | `j` / `H` / `h` | tercih edilen / 24 saat / 12 saat
+| Dakika | `m` / `mm` | `5` / `05` <small>(saniye ile birleştirildiğinde 2 hane)</small>
+| Saniye | `s` / `ss` | `8` / `08` <small>(dakika ile birleştirildiğinde 2 hane)</small>
+
+Biçimdeki kodların sırası önemli değildir, çünkü bileşenlerin sırası yerel ayarların kurallarına göre görüntülenecektir. Bu nedenle, biçim yerelden bağımsızdır. Örneğin, `en_US` yerel ayarında `yyyyMMMMd` biçimi `April 15, 2024` çıktısını verirken, `cs_CZ` yerel ayarında `15. dubna 2024` çıktısını verir:
+
+| locale:  | tr-TR | en_US
+|---
+| `format: 'dMy'` | 10.08.2024 | 8/10/2024
+| `format: 'yM'` | 08/2024 | 8/2024
+| `format: 'yyyyMMMM'` | Ağustos 2024 | August 2024
+| `format: 'MMMM'` | Ağustos | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | ÖS 5:54 | 5:54 PM
+
+
+**b) Önceden ayarlanmış stilleri kullanma**
+
+ `date` ve `time` parametreleri tarih ve saat gösterimi için ayrıntı düzeyini belirler. Birkaç seviye arasından seçim yapabilirsiniz: `full`, `long`, `medium`, `short`. Sadece tarihi, sadece saati ya da her ikisini birden görüntüleyebilirsiniz:
+
+| locale:  | tr-TR | en_US
+|---
+| `date: short` | 23.01.1978 | 1/23/78
+| `date: medium` | 23 Oca 1978 | Jan 23, 1978
+| `date: long` | 23 Ocak 1978 | January 23, 1978
+| `date: full` | 23 Ocak 1978 Pazartesi | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 GMT+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.1978 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 Oca 1978 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 Ocak 1978 08:30 | January 23, 1978 at 8:30 AM
+
+Tarih için `relative-` önekini de kullanabilirsiniz (örneğin, `relative-short`), bu da günümüze yakın tarihler için `yesterday`, `today` veya `tomorrow` olarak görüntülenir; aksi takdirde standart şekilde görüntülenir.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Ayrıca bkz. [tarih |#date].
+
+
 lower .[filter]
 ---------------
 Bir değeri küçük harfe dönüştürür. PHP eklentisi gerektirir `mbstring`.
@@ -416,8 +502,8 @@ Bağlantı `javascript:` veya `data:` gibi farklı bir şema kullanıyorsa ve i
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Baskılar:
@@ -451,9 +537,9 @@ Unescaped: <b>hello</b>
 `noescape` filtresinin yanlış kullanımı bir XSS güvenlik açığına yol açabilir! Ne yaptığınızdan ve yazdırdığınız dizenin güvenilir bir kaynaktan geldiğinden **kesinlikle emin** değilseniz asla kullanmayın.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Bir sayıyı verilen ondalık basamak sayısına göre biçimlendirir. Ayrıca ondalık nokta ve binlik ayırıcının bir karakterini de belirtebilirsiniz.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Bir sayıyı belirtilen sayıda ondalık basamağa göre biçimlendirir. [Yerel |develop#locale] ayar belirlenmişse, ilgili ondalık ve binlik ayırıcılar kullanılır.
 
 ```latte
 {1234.20 |number}              1,234
@@ -463,7 +549,55 @@ Bir sayıyı verilen ondalık basamak sayısına göre biçimlendirir. Ayrıca o
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+ `format` parametresi, sayıların görünümünü tam olarak ihtiyaçlarınıza göre tanımlamanıza olanak tanır. Ayarlanmış bir [yerel |develop#locale] ayar gerektirir. Biçim, tam açıklamasını "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns belgesinde bulabileceğiniz birkaç özel karakterden oluşur:
+
+- <c id=6/> zorunlu rakam, sıfır olsa bile her zaman görüntülenir
+- `#` isteğe bağlı rakam, yalnızca sayının o yerde bir rakamı varsa görüntülenir
+- `@` anlamlı hane, sayının belirli sayıda anlamlı hane ile görüntülenmesine yardımcı olur
+- `.` ondalık ayırıcının olması gereken yeri işaretler (yerel ayara bağlı olarak virgül veya nokta)
+- `,` genellikle binlik rakam gruplarını ayırmak için kullanılır
+- `%` sayıyı 100 ile çarpar ve yüzde işaretini ekler
+
+Şimdi bazı örneklere bakalım. İlk örnekte, iki ondalık basamak zorunludur; ikincisinde ise isteğe bağlıdır. Üçüncü örnekte her iki tarafta da sıfırlarla doldurma gösterilirken, dördüncü örnekte yalnızca mevcut rakamlar görüntülenir:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Önemli basamaklar, ondalık noktadan bağımsız olarak kaç basamağın görüntülenmesi gerektiğini belirler ve gerekirse sayıyı yuvarlar:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Bir sayıyı yüzde olarak görüntülemenin kolay bir yolu. Sayı 100 ile çarpılır ve `%` işareti eklenir:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Pozitif ve negatif sayılar için `;` karakteriyle ayrılmış farklı bir format tanımlayabiliriz. Bu şekilde, örneğin pozitif sayılar bir `+` işaretiyle gösterilebilir:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Sayıların gerçek görünümünün yerel ayarlara bağlı olarak değişebileceğini unutmayın. Örneğin, bazı ülkelerde ondalık ayırıcı olarak nokta yerine virgül kullanılır. Bu filtre bunu otomatik olarak hesaba katar, bu nedenle endişelenmenize gerek yoktur.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Bir dizeyi soldan başka bir dizeyle belirli bir uzunluğa kadar doldurur.
 
@@ -472,7 +606,7 @@ Bir dizeyi soldan başka bir dizeyle belirli bir uzunluğa kadar doldurur.
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Bir dizeyi sağdan başka bir dizeyle belirli bir uzunlukta doldurur.
 
@@ -514,8 +648,8 @@ Dizinin rastgele elemanını veya karakter dizisini döndürür:
 Ayrıca bkz. [ilk |#first], [son |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Dizeyi x kez tekrarlar.
 
 ```latte
@@ -523,7 +657,7 @@ Dizeyi x kez tekrarlar.
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Arama dizesinin tüm geçtiği yerleri değiştirme dizesiyle değiştirir.
 
@@ -538,7 +672,7 @@ Aynı anda birden fazla değiştirme yapılabilir:
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Tüm oluşumları düzenli ifadeye göre değiştirir.
 
@@ -559,8 +693,8 @@ Verilen dizeyi veya diziyi tersine çevirir.
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Bir sayıyı belirli bir hassasiyete yuvarlar.
 
 ```latte
@@ -573,7 +707,7 @@ Bir sayıyı belirli bir hassasiyete yuvarlar.
 Ayrıca bkz. [tavan |#ceil], [zemin |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Bir dizinin veya dizginin bir dilimini çıkarır.
 
@@ -591,9 +725,9 @@ Uzunluk verilmişse ve pozitifse, dizinin içinde o kadar eleman olacaktır. De
 Filtre, varsayılan olarak tamsayı dizi anahtarlarını yeniden sıralar ve sıfırlar. Bu davranış preserveKeys öğesi true olarak ayarlanarak değiştirilebilir. Dize anahtarları bu parametreden bağımsız olarak her zaman korunur.
 
 
-sort  .[filter]
----------------
-Bir diziyi sıralayan ve dizin ilişkisini koruyan süzgeç.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Filtre, bir dizinin veya yineleyicinin öğelerini, ilişkisel anahtarlarını koruyarak sıralar. Bir [yerel |develop#locale] ayarlandığında, özel bir karşılaştırma işlevi belirtilmediği sürece sıralama [yerel |develop#locale] ayarın kurallarını izler.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ Dizi ters sırada sıralanır.
 {/foreach}
 ```
 
-Kendi karşılaştırma fonksiyonunuzu parametre olarak aktarabilirsiniz:
+Sıralama için özel bir karşılaştırma işlevi belirtebilirsiniz (örnekte sıralamanın en büyükten en küçüğe doğru nasıl tersine çevrileceği gösterilmektedir):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+ `|sort` filtresi ayrıca öğeleri anahtara göre sıralamanıza da olanak tanır:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Bir tabloyu belirli bir sütuna göre sıralamanız gerekiyorsa, `by` parametresini kullanabilirsiniz. Örnekteki `'name'` değeri, sıralamanın `$row->name` veya `$row['name']`, `$row` adresinin bir dizi veya nesne olmasına bağlı olarak değişir:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Ayrıca, sıralanacak değeri belirleyen bir geri arama işlevi de tanımlayabilirsiniz:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+ `byKey` parametresi de aynı şekilde kullanılabilir.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ HTML'yi düz metne dönüştürür. Yani, HTML etiketlerini kaldırır ve HTML v
 Ortaya çıkan düz metin doğal olarak HTML etiketlerini temsil eden karakterler içerebilir, örneğin `'&lt;p&gt;'|stripHtml` şu şekilde dönüştürülür `<p>`. Bir güvenlik açığına yol açabileceğinden, ortaya çıkan metni asla `|noescape` ile çıktı olarak vermeyin.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Bir dizenin bir dilimini çıkarır. Bu filtre bir [dilim |#slice] filtresi ile değiştirilmiştir.
 
 ```latte
@@ -655,8 +815,8 @@ Bir dizenin bir dilimini çıkarır. Bu filtre bir [dilim |#slice] filtresi ile
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 İfadeleri diğer dillere çevirir. Filtreyi kullanılabilir hale getirmek için [çevirmen kur |develop#TranslatorExtension]manız gerekir. [Çeviri için etiketleri |tags#Translation] de kullanabilirsiniz.
 
 ```latte
@@ -665,8 +825,8 @@ translate(string message, ...args) .[filter]
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Baştaki ve sondaki karakterleri, varsayılan olarak boşlukları soyun.
 
 ```latte
@@ -675,7 +835,7 @@ Baştaki ve sondaki karakterleri, varsayılan olarak boşlukları soyun.
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Bir dizeyi verilen maksimum uzunluğa kısaltır, ancak tüm kelimeleri korumaya çalışır. Dize kesilmişse sonuna üç nokta ekler (bu ikinci parametre ile değiştirilebilir).
 
diff --git a/latte/tr/functions.texy b/latte/tr/functions.texy
index 5cef94e584..ba9f7ef58e 100644
--- a/latte/tr/functions.texy
+++ b/latte/tr/functions.texy
@@ -9,6 +9,8 @@ Yaygın PHP işlevlerine ek olarak, bunları şablonlarda da kullanabilirsiniz.
 | `divisibleBy`| [bir değişkenin bir sayıya bölünebilir olup olmadığını kontroleder|#divisibleBy]
 | `even` | [verilen sayının çift olup olmadığını kontroleder |#even]
 | `first` | [dizinin ilk elemanını veya karakter dizisini döndürür |#first]
+| `group` | [verileri çeşitli kriterlere göre gruplar |#group]
+| `hasBlock` | [bir bloğun varlığını tespit |#hasBlock] eder
 | `last` | [dizinin son elemanını veya karakter dizisini döndürür |#last]
 | `odd` | [verilen sayının tek olup olmadığını kontroleder |#odd]
 | `slice` | [bir dizi veya dizenin bir dilimini çıkarır |#slice]
@@ -73,8 +75,8 @@ Verilen sayının çift olup olmadığını kontrol eder.
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Dizinin ilk elemanını veya karakter dizisini döndürür:
 
 ```latte
@@ -85,6 +87,36 @@ Dizinin ilk elemanını veya karakter dizisini döndürür:
 Ayrıca bkz. [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Bu fonksiyon verileri farklı kriterlere göre gruplandırır.
+
+Bu örnekte, tablodaki satırlar `categoryId` sütununa göre gruplandırılmıştır. Çıktı, anahtarın `categoryId` sütunundaki değer olduğu bir alan dizisidir. [Ayrıntılı talimatları |cookbook/grouping] okuyun.
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Ayrıca bkz. filtre [grubu |filters#group].
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Belirtilen addaki bloğun var olup olmadığını kontrol eder:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Ayrıca bkz. [blok varlık kontrolü |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Dizinin son elemanını veya karakter dizisini döndürür:
@@ -106,8 +138,8 @@ Verilen sayının tek olup olmadığını kontrol eder.
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Bir dizinin veya dizginin bir dilimini çıkarır.
 
 ```latte
diff --git a/latte/tr/recipes.texy b/latte/tr/recipes.texy
index 45c99eaa74..964b762217 100644
--- a/latte/tr/recipes.texy
+++ b/latte/tr/recipes.texy
@@ -9,7 +9,7 @@ Editörler ve IDE .[#toc-editors-and-ide]
 
 - NetBeans IDE yerleşik desteğe sahiptir
 - PhpStorm: [Latte eklentisini |https://plugins.jetbrains.com/plugin/7457-latte] şuraya yükleyin `Settings > Plugins > Marketplace`
-- VS Code: "Nette Latte + Neon" eklentisi için markerplace'te arama yapın
+- VS Code: [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] veya [Nette Latte şablonları |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] eklentisi için markerplace'te arama yapın
 - Sublime Text 3: Paket Kontrolünde `Nette` paketini bulun ve yükleyin ve Latte'yi seçin `View > Syntax`
 - eski düzenleyicilerde .latte dosyaları için Smarty vurgulamasını kullanın
 
diff --git a/latte/tr/safety-first.texy b/latte/tr/safety-first.texy
index bc798290c4..767b38c305 100644
--- a/latte/tr/safety-first.texy
+++ b/latte/tr/safety-first.texy
@@ -351,7 +351,7 @@ Latte, `src` veya `href` niteliklerinde kullanılan değişkenin bir web URL'si
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Yazıyor:
diff --git a/latte/tr/syntax.texy b/latte/tr/syntax.texy
index 7877c39232..805f3bc168 100644
--- a/latte/tr/syntax.texy
+++ b/latte/tr/syntax.texy
@@ -98,7 +98,7 @@ Baskılar:
 Veya `tag-` önekini kullanarak işlevsellik yalnızca HTML etiketlerine uygulanır:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 `$url` değişkeninin değerine bağlı olarak bu yazdırılacaktır:
@@ -155,6 +155,20 @@ Veya doğrudan değer üzerinde (ile birlikte [`{=expr}` | https://latte.nette.o
 ```
 
 
+Dinamik HTML Etiketleri .[#toc-dynamic-html-tags]
+=================================================
+
+Latte, etiket adlarında esnekliğe ihtiyaç duyduğunuzda yararlı olan dinamik HTML etiketlerini destekler:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Örneğin, yukarıdaki kod şunları üretebilir `<h1>Heading</h1>` veya `<h2>Heading</h2>` değişkeninin değerine bağlı olarak `$level`. Latte'deki dinamik HTML etiketleri her zaman eşleştirilmelidir. Alternatifleri [n:tag |tags#n:tag].
+
+Latte güvenli bir şablonlama sistemi olduğundan, ortaya çıkan etiket adının geçerli olup olmadığını ve istenmeyen veya kötü amaçlı değerler içermediğini kontrol eder. Ayrıca, son etiket adının her zaman açılış etiketi adıyla aynı olmasını sağlar.
+
+
 Yorumlar .[#toc-comments]
 =========================
 
diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy
index d724a901db..ec01a336da 100644
--- a/latte/tr/tags.texy
+++ b/latte/tr/tags.texy
@@ -16,6 +16,7 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması.
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [koşul ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [bir değişiklik olup olmadığını test edin|#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [koşul anahtarı |#switch-case-default]
+| `n:else` | [koşullar için alternatif içerik |#n:else]
 
 .[table-latte-tags language-latte]
 |## Döngüler
@@ -97,8 +98,8 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması.
 | `{link}` | [bir bağlantı yazdırır |application:creating-links#In the Presenter Template]
 | `{plink}` | [sunum yapan kişiye bir bağlantı yazdırır |application:creating-links#In the Presenter Template]
 | `{control}` | [bir bileşen yazdırır |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [AJAX ile gönderilebilecek bir şablon parçacığı |application:ajax#tag-snippet]
-| `{snippetArea}` | snippets zarfı
+| `{snippet}`... `{/snippet}` | [AJAX ile gönderilebilecek bir şablon parçacığı |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [snippets zarfı |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [bir şablon bölümünü önbelleğe alır|caching:#caching-in-latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması.
 | `{input}` | [bir form giriş öğesi yazdırır |forms:rendering#label-input]
 | `{inputError}` | [form giriş öğesi için hata mesajı yazdırır |forms:rendering#inputError]
 | `n:name` | [bir HTML giriş öğesini etkinleştirir |forms:rendering#n:name]
-| `{formPrint}` | [Latte form planını oluşturur |forms:rendering#formPrint]
-| `{formPrintClass}` | [form verileri için PHP sınıfını yazdırır |forms:in-presenter#mapping-to-classes]
-| `{formContext}`... `{/formContext}` | [kısmi form oluşturma |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [form kapsayıcısını oluşturma |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ n:attributes öğesine `tag-` önekini ekleyebileceğinizi biliyor musunuz? Bu d
 Güzel.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+ `{if} ... {/if}` koşulunu bir [n:niteliği |syntax#n:attributes] biçiminde yazarsanız, `n:else` adresini kullanarak alternatif bir dal belirtme seçeneğiniz vardır:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+ `n:else` özniteliği aşağıdakilerle birlikte de kullanılabilir [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]ve [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Ayrıca bakınız [`{ifset block}` |template-inheritance#checking-block-existenc
 Bir değişkenin (veya birden fazla değişkenin) var olup olmadığını ve boş olmayan bir değere sahip olup olmadığını belirlemek için `{ifset $var}` koşulunu kullanın. Aslında PHP'deki `if (isset($var))` ile aynıdır. Herhangi bir çift etiketi gibi, bu da [n:attribute |syntax#n:attributes] şeklinde yazılabilir, bu yüzden örnek olarak gösterelim:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Bu oldukça pratik, değil mi?
 `{iterateWhile}`
 ----------------
 
-Koşul karşılandığı sürece yinelemeyi iç içe bir döngüde gerçekleştirerek foreach döngüsünde yineleme sırasında doğrusal verilerin gruplanmasını basitleştirir. [Yemek kitabındaki talimatları okuyun |cookbook/iteratewhile].
+Bir koşul sağlanana kadar iç içe bir döngüde yineleme yaparak foreach döngüsünde yineleme sırasında doğrusal verilerin gruplanmasını basitleştirir. [Ayrıntılı talimatları okuyun |cookbook/grouping].
 
 Ayrıca yukarıdaki örnekte `{first}` ve `{last}` adreslerini zarif bir şekilde değiştirebilir:
 
@@ -489,6 +501,8 @@ Ayrıca yukarıdaki örnekte `{first}` ve `{last}` adreslerini zarif bir şekild
 {/foreach}
 ```
 
+Ayrıca bkz. [toplu |filters#batch] iş ve [grup |filters#group] filtreleri.
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ Eğer `$heading === null`, ise `<h1>` etiketi değiştirilmeden yazdırılır. A
 <h3 class="main">...</h3>
 ```
 
+Latte güvenli bir şablonlama sistemi olduğundan, yeni etiket adının geçerli olup olmadığını ve istenmeyen veya kötü amaçlı değerler içermediğini kontrol eder.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/tr/template-inheritance.texy b/latte/tr/template-inheritance.texy
index 8356a88f6f..216ec73eb3 100644
--- a/latte/tr/template-inheritance.texy
+++ b/latte/tr/template-inheritance.texy
@@ -132,7 +132,7 @@ Düzen kalıtımı ile çalışmak için bazı ipuçları:
 
 - Bir şablonda `{layout}` kullanıyorsanız, bu şablondaki ilk şablon etiketi olmalıdır.
 
-- Düzen [otomatik olarak aranabilir |develop#automatic-layout-lookup] ( [sunumlarda |application:templates#search-for-templates] olduğu gibi). Bu durumda, şablonun bir düzene sahip olmaması gerekiyorsa, bunu `{layout none}` etiketi ile belirtecektir.
+- Düzen [otomatik olarak aranabilir |develop#automatic-layout-lookup] ( [sunumlarda |application:templates#Template Lookup] olduğu gibi). Bu durumda, şablonun bir düzene sahip olmaması gerekiyorsa, bunu `{layout none}` etiketi ile belirtecektir.
 
 - `{layout}` etiketinin `{extends}` takma adı vardır.
 
@@ -396,6 +396,14 @@ PHP'de blok adı olarak bir değişken veya herhangi bir ifade kullanabilirsiniz
 {/ifset}
 ```
 
+Blokların varlığı da fonksiyon tarafından döndürülür [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 İpuçları .[#toc-tips]
 ---------------------
@@ -415,7 +423,7 @@ PHP'de blok adı olarak bir değişken veya herhangi bir ifade kullanabilirsiniz
 Yatay Yeniden Kullanım `{import}` .{toc: Horizontal Reuse}
 ==========================================================
 
-Yatay yeniden kullanım, Latte'deki üçüncü bir yeniden kullanılabilirlik ve kalıtım mekanizmasıdır. Diğer şablonlardan bloklar yüklemenizi sağlar. Yardımcı fonksiyonlar veya bir özellik içeren bir PHP dosyası oluşturmaya benzer.
+Yatay yeniden kullanım, Latte'de yeniden kullanım ve kalıtım için üçüncü mekanizmadır. Diğer şablonlardan blokların yüklenmesine izin verir. PHP'de yardımcı işlevlerle bir dosya oluşturmaya ve ardından `require` kullanarak yüklemeye benzer.
 
 Şablon düzeni kalıtımı Latte'nin en güçlü özelliklerinden biri olsa da, basit kalıtımla sınırlıdır - bir şablon yalnızca bir başka şablonu genişletebilir. Yatay yeniden kullanım, çoklu kalıtım elde etmenin bir yoludur.
 
@@ -447,7 +455,7 @@ Ana şablondaki blokları içe aktarırsanız (yani `{import}` adresini `layout.
 
 Herhangi bir şablonda istediğiniz kadar `{import}` ifadesi kullanabilirsiniz. İki içe aktarılan şablon aynı bloğu tanımlarsa, ilki kazanır. Ancak, en yüksek öncelik, içe aktarılan herhangi bir bloğun üzerine yazabilen ana şablona verilir.
 
-Geçersiz kılınan tüm bloklar, [üst |#parent block] blok olarak eklenerek kademeli olarak dahil edilebilir:
+Üzerine yazılan blokların içeriği, blok bir [üst blokla |#parent block] aynı şekilde eklenerek korunabilir:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/latte/uk/@left-menu.texy b/latte/uk/@left-menu.texy
index b1aa36563b..719b7faca0 100644
--- a/latte/uk/@left-menu.texy
+++ b/latte/uk/@left-menu.texy
@@ -1,24 +1,24 @@
 - [Початок роботи |Guide]
 - [Навіщо використовувати шаблони? |why-use]
-- Концепції
+- Концепції ⚗️
 	- [Безпека понад усе |Safety First]
 	- Успадкування [шаблонів |Template Inheritance]
 	- [Система типів |Type System]
 	- [Пісочниця |Sandbox]
 
-- Для дизайнерів
+- Для дизайнерів 🎨
 	- [Синтаксис |Syntax]
 	- [Теги |Tags]
 	- [Фільтри |Filters]
 	- [Функції |Functions]
 	- [Поради та хитрощі |recipes]
 
-- Для розробників
+- Для розробників 🧮
 	- [Практика для розробників |develop]
 	- [Розширення Latte |Extending Latte]
 	- [Створення розширення |creating-extension]
 
-- [Куховарська книга |cookbook/@home]
+- [Куховарська книга 💡|cookbook/@home]
 	- [Міграція з Twig |cookbook/migration-from-twig]
 	- [... докладніше |cookbook/@home]
 
diff --git a/latte/uk/cookbook/@home.texy b/latte/uk/cookbook/@home.texy
index 5d60e3b64a..dd306aa04f 100644
--- a/latte/uk/cookbook/@home.texy
+++ b/latte/uk/cookbook/@home.texy
@@ -4,7 +4,9 @@
 .[perex]
 Приклади кодів і рецептів для виконання типових завдань за допомогою Latte.
 
-- [Все, що ви завжди хотіли знати про {iterateWhile} |iteratewhile]
+- [Посібник для розробників |/develop]
+- [Передача змінних між шаблонами |passing-variables]
+- [Все, що ви завжди хотіли знати про групування |grouping]
 - [Як писати SQL-запити в Latte? |how-to-write-sql-queries-in-latte]
 - [Міграція з PHP |migration-from-php]
 - [Міграція з Twig |migration-from-twig]
diff --git a/latte/uk/cookbook/grouping.texy b/latte/uk/cookbook/grouping.texy
new file mode 100644
index 0000000000..b260612b1a
--- /dev/null
+++ b/latte/uk/cookbook/grouping.texy
@@ -0,0 +1,257 @@
+Все, що ви завжди хотіли знати про групування
+*********************************************
+
+.[perex]
+Працюючи з даними в шаблонах, ви часто стикаєтеся з необхідністю групувати їх або відображати за певними критеріями. Для цього Latte пропонує кілька потужних інструментів.
+
+Фільтр і функція `|group` дозволяють ефективно групувати дані на основі заданих критеріїв, тоді як фільтр `|batch` полегшує розбиття даних на фіксовані партії, а тег `{iterateWhile}` надає можливість більш складного управління циклами з умовами.
+Кожен з цих тегів пропонує специфічні можливості для роботи з даними, що робить їх незамінними інструментами для динамічного і структурованого відображення інформації в шаблонах Latte.
+
+
+Фільтр і функція `group` .[#toc-filter-and-function-group]
+==========================================================
+
+Уявіть собі таблицю бази даних `items` з елементами, розділеними на категорії:
+
+| id | categoryId | name
+|------------------
+| 1 1 1 Яблуко
+| 2 | 1 | Банан
+| 3 | 2 | PHP
+| 4 | 3 | Зелений
+| 5 3 Червоний
+| 6 3 Синій
+
+Простий список всіх елементів з використанням шаблону Latte виглядатиме так:
+
+```latte
+<ul>
+{foreach $items as $item}
+	<li>{$item->name}</li>
+{/foreach}
+</ul>
+```
+
+Однак, якщо ми хочемо, щоб елементи були організовані в групи за категоріями, нам потрібно розділити їх так, щоб кожна категорія мала свій власний список. Результат матиме такий вигляд:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+</ul>
+
+<ul>
+	<li>PHP</li>
+</ul>
+
+<ul>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Це завдання можна легко і елегантно вирішити за допомогою `|group`. Ми вказуємо `categoryId` в якості параметра, що означає, що елементи будуть розбиті на менші масиви на основі значення `$item->categoryId` (якби `$item` було масивом, ми б використовували `$item['categoryId']`):
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+Фільтр також можна використовувати як функцію в Latte, що дає нам альтернативний синтаксис: `{foreach group($items, categoryId) ...}`.
+
+Якщо ви хочете згрупувати елементи за більш складними критеріями, ви можете використовувати функцію в параметрі фільтра. Наприклад, групування елементів за довжиною їхніх назв виглядатиме так:
+
+```latte
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+	...
+{/foreach}
+```
+
+Важливо зазначити, що `$categoryItems` - це не звичайний масив, а об'єкт, який поводиться як ітератор. Щоб отримати доступ до першого елемента в групі, ви можете скористатися функцією [`first()` |latte:functions#first] функцію
+
+Така гнучкість у групуванні даних робить `group` надзвичайно корисним інструментом для представлення даних у шаблонах Latte.
+
+
+Вкладені цикли .[#toc-nested-loops]
+-----------------------------------
+
+Припустимо, у нас є таблиця бази даних з ще одним стовпчиком `subcategoryId`, який визначає підкатегорії для кожного елемента. Ми хочемо відобразити кожну основну категорію в окремому `<ul>` а кожну підкатегорію в окремому вкладеному `<ol>` списку:
+
+```latte
+{foreach ($items|group: categoryId) as $categoryItems}
+	<ul>
+		{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+			<ol>
+				{foreach $subcategoryItems as $item}
+					<li>{$item->name}
+				{/foreach}
+			</ol>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+
+Підключення до бази даних Nette .[#toc-connection-with-nette-database]
+----------------------------------------------------------------------
+
+Покажемо, як ефективно використовувати групування даних у поєднанні з базою даних Nette. Припустимо, що ми працюємо з таблицею `items` з початкового прикладу, яка підключена через стовпець `categoryId` до цієї таблиці `categories`:
+
+| categoryId | name
+|------------|------------|
+| 1 | Фрукти
+| 2 | Мови
+| 3 кольори
+
+Завантажуємо дані з таблиці `items` за допомогою команди Nette Database Explorer `$items = $db->table('items')`. Під час ітерації над цими даними ми маємо можливість не тільки отримати доступ до таких атрибутів, як `$item->name` і `$item->categoryId`, але завдяки зв'язку з таблицею `categories`, також до відповідного рядка в ній через `$item->category`. Цей зв'язок може продемонструвати цікаве використання:
+
+```latte
+{foreach ($items|group: category) as $category => $categoryItems}
+	<h1>{$category->name}</h1>
+	<ul>
+		{foreach $categoryItems as $item}
+			<li>{$item->name}</li>
+		{/foreach}
+	</ul>
+{/foreach}
+```
+
+У цьому випадку ми використовуємо фільтр `|group` для групування за пов'язаним рядком `$item->category`, а не лише за стовпчиком `categoryId`. Це дає нам `ActiveRow` даної категорії в ключі-змінній, що дозволяє нам безпосередньо відображати її назву за допомогою `{$category->name}`. Це практичний приклад того, як групування може спростити шаблони і полегшити обробку даних.
+
+
+Фільтр `|batch` .[#toc-filter-batch]
+====================================
+
+Фільтр дозволяє розбити список елементів на групи із заздалегідь визначеною кількістю елементів. Цей фільтр ідеально підходить для ситуацій, коли ви хочете представити дані в декількох менших групах, наприклад, для кращої наочності або візуальної організації на сторінці.
+
+Уявіть, що у нас є список елементів і ми хочемо відобразити їх у вигляді списків, кожен з яких містить максимум три елементи. Використання фільтра `|batch` є дуже практичним у такому випадку:
+
+```latte
+<ul>
+{foreach ($items|batch: 3) as $batch}
+	{foreach $batch as $item}
+		<li>{$item->name}</li>
+	{/foreach}
+{/foreach}
+</ul>
+```
+
+У цьому прикладі список `$items` розбивається на менші групи, кожна з яких (`$batch`) містить до трьох елементів. Потім кожна група відображається в окремому `<ul>` списку.
+
+Якщо остання група не містить достатньо елементів, щоб досягти потрібної кількості, другий параметр фільтра дозволяє визначити, чим ця група буде доповнена. Це ідеально підходить для естетичного вирівнювання елементів, де неповний ряд може виглядати невпорядковано.
+
+```latte
+{foreach ($items|batch: 3, '—') as $batch}
+	...
+{/foreach}
+```
+
+
+Тег `{iterateWhile}` .[#toc-tag-iteratewhile]
+=============================================
+
+Ми продемонструємо ті ж самі завдання, що і з фільтром `|group`, використовуючи тег `{iterateWhile}`. Основна відмінність між двома підходами полягає в тому, що `group` спочатку обробляє і групує всі вхідні дані, тоді як `{iterateWhile}` контролює хід виконання циклів з умовами, тому ітерації відбуваються послідовно.
+
+Спочатку ми малюємо таблицю з категоріями за допомогою iterateWhile:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}</li>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+У той час як `{foreach}` позначає зовнішню частину циклу, тобто малювання списків для кожної категорії, тег `{iterateWhile}` позначає внутрішню частину, тобто окремі елементи.
+Умова в кінцевому тезі говорить, що повторення триватиме доти, доки поточний і наступний елементи належать до тієї ж категорії (`$iterator->nextValue` - [наступний елемент |/tags#$iterator]).
+
+Якби ця умова виконувалася завжди, всі елементи були б намальовані у внутрішньому циклі:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<li>{$item->name}
+		{/iterateWhile true}
+	</ul>
+{/foreach}
+```
+
+Результат буде виглядати так:
+
+```latte
+<ul>
+	<li>Apple</li>
+	<li>Banana</li>
+	<li>PHP</li>
+	<li>Green</li>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Яке використання iterateWhile у цьому випадку? Коли таблиця порожня і не містить жодного елемента, не виводиться пустий `<ul></ul>` не виводиться.
+
+Якщо ми вказуємо умову у відкриваючому тезі `{iterateWhile}`, поведінка змінюється: умова (і перехід до наступного елементу) виконується на початку внутрішнього циклу, а не в кінці.
+Таким чином, хоча ви завжди переходите на `{iterateWhile}` без умови, ви переходите на `{iterateWhile $cond}` тільки тоді, коли виконується умова `$cond`. І в той же час наступний елемент записується в `$item`.
+
+Це корисно, наприклад, в ситуації, коли ми хочемо відобразити перший елемент в кожній категорії по-різному, ось так:
+
+```latte
+<h1>Apple</h1>
+<ul>
+	<li>Banana</li>
+</ul>
+
+<h1>PHP</h1>
+<ul>
+</ul>
+
+<h1>Green</h1>
+<ul>
+	<li>Red</li>
+	<li>Blue</li>
+</ul>
+```
+
+Ми модифікуємо початковий код так, щоб спочатку відрендерити перший елемент, а потім у внутрішньому циклі `{iterateWhile}` відрендерити інші елементи з тієї ж категорії:
+
+```latte
+{foreach $items as $item}
+	<h1>{$item->name}</h1>
+	<ul>
+		{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+			<li>{$item->name}</li>
+		{/iterateWhile}
+	</ul>
+{/foreach}
+```
+
+У межах одного циклу ми можемо створювати кілька внутрішніх циклів і навіть вкладати їх один в одного. Таким чином, наприклад, можна згрупувати підкатегорії.
+
+Припустимо, що в таблиці є ще один стовпець `subcategoryId`, і крім того, що кожна категорія знаходиться в окремому стовпчику `<ul>`кожна підкатегорія знаходиться в окремому `<ol>`:
+
+```latte
+{foreach $items as $item}
+	<ul>
+		{iterateWhile}
+			<ol>
+				{iterateWhile}
+					<li>{$item->name}
+				{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
+			</ol>
+		{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
+	</ul>
+{/foreach}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/uk/cookbook/iteratewhile.texy b/latte/uk/cookbook/iteratewhile.texy
deleted file mode 100644
index 79a6d83f6e..0000000000
--- a/latte/uk/cookbook/iteratewhile.texy
+++ /dev/null
@@ -1,214 +0,0 @@
-Все, що ви завжди хотіли знати про {iterateWhile}
-*************************************************
-
-.[perex]
-Тег `{iterateWhile}` підходить для різних трюків у циклах foreach.
-
-Припустимо, у нас є така таблиця бази даних, у якій елементи розділені на категорії:
-
-| id  |  catId  |  name
-|------------------
-| 1   |      1  | Apple
-| 2   |      1  | Banana
-| 3   |      2  | PHP
-| 4   |      3  | Green
-| 5   |      3  | Red
-| 6   |      3  | Blue
-
-Звичайно, вивести елементи в циклі foreach у вигляді списку дуже просто:
-
-```latte
-<ul>
-{foreach $items as $item}
-	<li>{$item->name}</li>
-{/foreach}
-</ul>
-```
-
-Але що робити, якщо ви хочете вивести кожну категорію в окремий список? Інакше кажучи, як розв'язати задачу групування елементів із лінійного списку в циклі foreach. Виведення має мати такий вигляд:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-</ul>
-
-<ul>
-	<li>PHP</li>
-</ul>
-
-<ul>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Ми покажемо вам, як легко й елегантно можна вирішити це завдання за допомогою iterateWhile:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}</li>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-Якщо `{foreach}` позначає зовнішню частину циклу, тобто складання списків для кожної категорії, то теги `{iterateWhile}` вказують на внутрішню частину, тобто на окремі елементи.
-Умова в тезі end говорить, що повторення триватиме доти, доки поточний і наступний елемент належать до однієї категорії (`$iterator->nextValue` - [наступний елемент |/tags#iterator]).
-
-Якщо умова завжди виконується, то у внутрішньому циклі малюються всі елементи:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<li>{$item->name}
-		{/iterateWhile true}
-	</ul>
-{/foreach}
-```
-
-Результат матиме такий вигляд:
-
-```latte
-<ul>
-	<li>Apple</li>
-	<li>Banana</li>
-	<li>PHP</li>
-	<li>Green</li>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Чим корисне таке використання iterateWhile? Чим воно відрізняється від рішення, яке ми показали на самому початку цього посібника? Різниця в тому, що якщо таблиця порожня і не містить елементів, то вона не буде виводитися порожньою `<ul></ul>`.
-
-
-Рішення без `{iterateWhile}` .[#toc-solution-without-iteratewhile]
-------------------------------------------------------------------
-
-Якби ми вирішували ту саму задачу за допомогою абсолютно базових конструкцій систем шаблонів, наприклад, у Twig, Blade або чистому PHP, то рішення виглядало б приблизно так:
-
-```latte
-{var $prevCatId = null}
-{foreach $items as $item}
-	{if $item->catId !== $prevCatId}
-		{* the category has changed *}
-
-		{* we close the previous <ul>, if it is not the first item *}
-		{if $prevCatId !== null}
-			</ul>
-		{/if}
-
-		{* we will open a new list *}
-		<ul>
-
-		{do $prevCatId = $item->catId}
-	{/if}
-
-	<li>{$item->name}</li>
-{/foreach}
-
-{if $prevCatId !== null}
-	{* we close the last list *}
-	</ul>
-{/if}
-```
-
-Однак цей код незрозумілий і неінтуїтивний. Зв'язок між HTML-тегами, що відкривають і закривають, абсолютно не зрозумілий. З першого погляду не зрозуміло, чи є помилка. І для цього потрібні допоміжні змінні, такі як `$prevCatId`.
-
-На відміну від цього, рішення з `{iterateWhile}` чисте, зрозуміле, не потребує допоміжних змінних і є надійним.
-
-
-Умова в закриваючому тезі .[#toc-condition-in-the-closing-tag]
---------------------------------------------------------------
-
-Якщо вказати умову у відкриваючому тезі `{iterateWhile}`, то поведінка змінюється: умова (і перехід до наступного елемента) виконується на початку внутрішнього циклу, а не в кінці.
-Таким чином, якщо `{iterateWhile}` без умови вводиться завжди, то `{iterateWhile $cond}` вводиться тільки при виконанні умови `$cond`. Водночас, наступний елемент записується в `$item`.
-
-Це корисно, наприклад, у ситуації, коли потрібно по-різному відобразити перший елемент у кожній категорії, наприклад:
-
-```latte
-<h1>Apple</h1>
-<ul>
-	<li>Banana</li>
-</ul>
-
-<h1>PHP</h1>
-<ul>
-</ul>
-
-<h1>Green</h1>
-<ul>
-	<li>Red</li>
-	<li>Blue</li>
-</ul>
-```
-
-Змінимо вихідний код, ми відтворюємо перший елемент, а потім додаткові елементи з тієї ж категорії у внутрішньому циклі `{iterateWhile}`:
-
-```latte
-{foreach $items as $item}
-	<h1>{$item->name}</h1>
-	<ul>
-		{iterateWhile $item->catId === $iterator->nextValue->catId}
-			<li>{$item->name}</li>
-		{/iterateWhile}
-	</ul>
-{/foreach}
-```
-
-
-Вкладені цикли .[#toc-nested-loops]
------------------------------------
-
-Ми можемо створити кілька внутрішніх циклів в одному циклі і навіть вкласти їх один в одного. Таким чином, наприклад, можна згрупувати підкатегорії.
-
-Припустімо, що в таблиці `subCatId` є ще один стовпчик, і на додаток до того, що кожна категорія перебуватиме в окремому стовпчику, кожна підкатегорія перебуватиме в окремому стовпчику. `<ul>`, кожна підкатегорія буде знаходитися в окремій колонці `<ol>`:
-
-```latte
-{foreach $items as $item}
-	<ul>
-		{iterateWhile}
-			<ol>
-				{iterateWhile}
-					<li>{$item->name}
-				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
-			</ol>
-		{/iterateWhile $item->catId === $iterator->nextValue->catId}
-	</ul>
-{/foreach}
-```
-
-
-Фільтр | пакетний .[#toc-filter-batch]
---------------------------------------
-
-Групування лінійних елементів також забезпечується фільтром `batch`, у партії з фіксованою кількістю елементів:
-
-```latte
-<ul>
-{foreach ($items|batch:3) as $batch}
-	{foreach $batch as $item}
-		<li>{$item->name}</li>
-	{/foreach}
-{/foreach}
-</ul>
-```
-
-Його можна замінити на iterateWhile таким чином:
-
-```latte
-<ul>
-{foreach $items as $item}
-	{iterateWhile}
-		<li>{$item->name}</li>
-	{/iterateWhile $iterator->counter0 % 3}
-{/foreach}
-</ul>
-```
-
-{{leftbar: /@left-menu}}
diff --git a/latte/uk/cookbook/passing-variables.texy b/latte/uk/cookbook/passing-variables.texy
new file mode 100644
index 0000000000..efbb82f07e
--- /dev/null
+++ b/latte/uk/cookbook/passing-variables.texy
@@ -0,0 +1,161 @@
+Передача змінних між шаблонами
+******************************
+
+Цей посібник пояснює, як передавати змінні між шаблонами в Latte за допомогою різних тегів, таких як `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` та інших. Ви також дізнаєтеся, як працювати зі змінними в тегах `{block}` і `{define}`, а також про призначення тегу `{parameters}`.
+
+
+Типи змінних .[#toc-types-of-variables]
+---------------------------------------
+Змінні в Latte можна розділити на три категорії залежно від того, як і де вони визначаються:
+
+**Вхідні змінні** - це ті, які передаються в шаблон ззовні, наприклад, з PHP-скрипту або за допомогою тегу типу `{include}`.
+
+```php
+$latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]);
+```
+
+**Змінні оточення** - це змінні, що існують у місці розташування певного тегу. До них відносяться всі вхідні змінні та інші змінні, створені за допомогою тегів `{var}`, `{default}` або всередині циклу `{foreach}`.
+
+```latte
+{foreach $users as $user}
+	{include 'userBox.latte', user: $user}
+{/foreach}
+```
+
+**Явні змінні** - це змінні, які безпосередньо вказані в тегу і передаються до цільового шаблону.
+
+```latte
+{include 'userBox.latte', name: $user->name, age: $user->age}
+```
+
+
+`{block}`
+---------
+Тег `{block}` використовується для визначення блоків коду багаторазового використання, які можуть бути змінені або розширені в успадкованих шаблонах. Оточуючі змінні, визначені перед блоком, доступні всередині блоку, але будь-які зміни змінних відображаються тільки в межах цього блоку.
+
+```latte
+{var $foo = 'original'}
+{block example}
+	{var $foo = 'modified'}
+{/block}
+
+{$foo}    // outputs: original
+```
+
+
+`{define}`
+----------
+Тег `{define}` використовується для створення блоків, які відображаються тільки при виклику за допомогою `{include}`. Змінні, доступні всередині цих блоків, залежать від того, чи вказані параметри у визначенні. Якщо параметри вказані, то доступні тільки ці параметри. Якщо ні, то доступні всі вхідні змінні шаблону, в якому визначені блоки.
+
+```latte
+{define hello}
+	{* has access to all input variables of the template *}
+{/define}
+
+{define hello $name}
+	{* has access only to the $name parameter *}
+{/define}
+```
+
+
+`{parameters}`
+--------------
+Тег `{parameters}` використовується для явного оголошення очікуваних вхідних змінних на початку шаблону. Таким чином, ви можете легко задокументувати очікувані змінні та їхні типи даних. Також можна визначити значення за замовчуванням.
+
+```latte
+{parameters int $age, string $name = 'unknown'}
+<p>Age: {$age}, Name: {$name}</p>
+```
+
+
+`{include file}`
+----------------
+Тег `{include file}` використовується для вставки цілого шаблону. Цьому шаблону передаються як вхідні змінні шаблону, де використовується тег, так і явно визначені змінні. Однак цільовий шаблон може обмежити область застосування за допомогою `{parameters}`.
+
+```latte
+{include 'profile.latte', userId: $user->id}
+```
+
+
+`{include block}`
+-----------------
+При вставці блоку, визначеного в тому ж шаблоні, йому передаються всі навколишні та явно визначені змінні:
+
+```latte
+{define blockName}
+	<p>Name: {$name}, Age: {$age}</p>
+{/define}
+
+{var $name = 'Jan', $age = 30}
+{include blockName}
+```
+
+У цьому прикладі змінні `$name` і `$age` передаються до блоку `blockName`. Така ж поведінка застосовується і до `{include parent}`.
+
+При вставці блоку з іншого шаблону передаються тільки вхідні змінні і явно визначені змінні. Оточуючі змінні автоматично не стають доступними.
+
+```latte
+{include blockInOtherTemplate, name: $name, age: $age}
+```
+
+
+`{layout}` або `{extends}`
+--------------------------
+Ці теги визначають макет, до якого передаються вхідні змінні дочірнього шаблону та змінні, створені в коді перед блоками:
+
+```latte
+{layout 'layout.latte'}
+{var $seo = 'index, follow'}
+```
+
+Шаблон `layout.latte`:
+
+```latte
+<head>
+	<meta name="robots" content="{$seo}">
+</head>
+```
+
+
+`{embed}`
+---------
+Тег `{embed}` схожий на тег `{include}`, але дозволяє вбудовувати блоки в шаблон. На відміну від `{include}`, передаються лише явно оголошені змінні:
+
+```latte
+{embed 'menu.latte', items: $menuItems}
+{/embed}
+```
+
+У цьому прикладі шаблон `menu.latte` має доступ лише до змінної `$items`.
+
+І навпаки, блоки всередині `{embed}` мають доступ до всіх оточуючих змінних:
+
+```latte
+{var $name = 'Jan'}
+{embed 'menu.latte', items: $menuItems}
+	{block foo}
+		{$name}
+	{/block}
+{/embed}
+```
+
+
+`{import}`
+----------
+Тег `{import}` використовується для завантаження блоків з інших шаблонів. Імпортованим блокам передаються як вхідні, так і явно оголошені змінні.
+
+```latte
+{import 'buttons.latte'}
+```
+
+
+`{sandbox}`
+-----------
+Тег `{sandbox}` ізолює шаблон для безпечної обробки. Змінні передаються виключно явно.
+
+```latte
+{sandbox 'secure.latte', data: $secureData}
+```
+
+
+{{leftbar: /@left-menu}}
diff --git a/latte/uk/creating-extension.texy b/latte/uk/creating-extension.texy
index 8ddb1f21d1..9a75553be9 100644
--- a/latte/uk/creating-extension.texy
+++ b/latte/uk/creating-extension.texy
@@ -307,7 +307,7 @@ class ForeachNode extends StatementNode
 	// функція розбору, яка поки що просто створює вузол
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
-		$node = new self;
+		$node = $tag->node = new self;
 		return $node;
 	}
 
@@ -359,7 +359,7 @@ class ForeachNode extends StatementNode
 	public static function create(Latte\Compiler\Tag $tag): self
 	{
 		$tag->expectArguments();
-		$node = new self;
+		$node = $tag->node = new self;
 		$node->expression = $tag->parser->parseExpression();
 		$tag->parser->stream->consume('as');
 		$node->value = $parser->parseExpression();
@@ -486,6 +486,24 @@ public function &getIterator(): \Generator
 ```
 
 
+AuxiliaryNode
+-------------
+
+Якщо ви створюєте новий тег для Latte, бажано створити для нього спеціальний клас вузла, який буде представляти його в дереві AST (див. клас `ForeachNode` у прикладі вище). У деяких випадках вам може стати в нагоді тривіальний допоміжний клас вузлів [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], який дозволяє передавати тіло методу `print()` і список вузлів, доступних за допомогою методу `getIterator()`, як параметри конструктора:
+
+```php
+// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode
+// or Latte\Compiler\Nodes\AuxiliaryNode
+
+$node = new AuxiliaryNode(
+	// body of the print() method:
+	fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode),
+	// nodes accessed via getIterator() and also passed into the print() method:
+	[$argNode],
+);
+```
+
+
 Компілятор передає .[#toc-compiler-passes]
 ==========================================
 
diff --git a/latte/uk/develop.texy b/latte/uk/develop.texy
index bf30c26614..a539136910 100644
--- a/latte/uk/develop.texy
+++ b/latte/uk/develop.texy
@@ -166,6 +166,22 @@ try {
 ```
 
 
+Локація .[#toc-locale]{data-version:3.0.18}
+===========================================
+
+Latte дозволяє встановити локаль, яка впливає на форматування чисел, дат і сортування. Вона встановлюється за допомогою методу `setLocale()`. Ідентифікатор локалі відповідає стандарту мовних тегів IETF, який використовує розширення PHP `intl`. Він складається з коду мови і, можливо, коду країни, наприклад, `en_US` для англійської мови в США, `de_DE` для німецької мови в Німеччині тощо.
+
+```php
+$latte = new Latte\Engine;
+$latte->setLocale('cs');
+```
+
+Параметр локалі впливає на фільтри [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] і [bytes |filters#bytes].
+
+.[note]
+Потрібне розширення PHP `intl`. Налаштування у Latte не впливає на глобальне налаштування локалі у PHP.
+
+
 Суворий режим .[#toc-strict-mode]{data-version:3.0.8}
 =====================================================
 
@@ -271,19 +287,28 @@ vendor/bin/latte-lint <path>
 #!/usr/bin/env php
 <?php
 
-// вкажіть фактичний шлях до файлу autoload.php
+// введіть фактичний шлях до файлу autoload.php
 require __DIR__ . '/vendor/autoload.php';
 
-$engine = new Latte\Engine;
-// додайте тут індивідуальні розширення
-$engine->addExtension(/* ... */);
+$path = $argv[1] ?? '.';
+
+$linter = new Latte\Tools\Linter;
+$latte = $linter->getEngine();
+// додайте тут свої індивідуальні розширення
+$latte->addExtension(/* ... */);
 
-$path = $argv[1];
-$linter = new Latte\Tools\Linter(engine: $engine);
 $ok = $linter->scanDirectory($path);
 exit($ok ? 0 : 1);
 ```
 
+Крім того, ви можете передати лінтеру власний об'єкт `Latte\Engine`:
+
+```php
+$latte = new Latte\Engine;
+// тут ми налаштовуємо об'єкт $latte
+$linter = new Latte\Tools\Linter(engine: $latte);
+```
+
 
 Завантаження шаблонів з рядка .[#toc-loading-templates-from-a-string]
 =====================================================================
diff --git a/latte/uk/extending-latte.texy b/latte/uk/extending-latte.texy
index 0a2a8b29c3..531dd46cdb 100644
--- a/latte/uk/extending-latte.texy
+++ b/latte/uk/extending-latte.texy
@@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 
 Звичайно, функція, що представляє фільтр, може приймати будь-яку кількість параметрів, також підтримуються змінні параметри.
 
+Якщо фільтр повертає рядок у форматі HTML, ви можете позначити його, щоб Latte не використовував автоматичне (і, відповідно, подвійне) екранування. Це дозволяє уникнути необхідності вказувати `|noescape` у шаблоні.
+Найпростіший спосіб - обернути рядок в об'єкт `Latte\Runtime\Html`, інший спосіб - [контекстні фільтри |#Contextual Filters].
+
+```php
+$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
+```
+
+.[note]
+У цьому випадку фільтр повинен забезпечити коректне екранування даних.
+
 
 Фільтри, що використовують клас .[#toc-filters-using-the-class]
 ---------------------------------------------------------------
@@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string {
 
 	// змінюємо тип контенту на HTML
 	$info->contentType = ContentType::Html;
-	return "<i>$num Kč</i>";
+	return "<i>$amount EUR</i>";
 });
 ```
 
diff --git a/latte/uk/filters.texy b/latte/uk/filters.texy
index b3fe48bcc2..e6b7186e5e 100644
--- a/latte/uk/filters.texy
+++ b/latte/uk/filters.texy
@@ -11,14 +11,16 @@
 | `bytes` | [форматує розмір у байтах |#bytes]
 | `clamp` | [обмежує значення діапазоном |#clamp]
 | `dataStream` | [перетворення протоколу URI даних |#dataStream]
-| `date` | [форматує дату |#date]
+| `date` | [форматує дату та час |#date]
 | `explode` | [розділяє рядок за заданим роздільником |#explode]
 | `first` | [повертає перший елемент масиву або символ рядка |#first]
+| `group` | [групує дані за різними критеріями |#group]
 | `implode` | [з'єднує масив із ряд ком|#implode]
 | `indent` | [відступи тексту зліва з кількістю табуляцій |#indent]
 | `join` | [приєднує масив до ряд ка|#implode]
 | `last` | [повертає останній елемент масиву або символ рядка|#last]
 | `length` | [повертає довжину рядка або масиву |#length]
+| `localDate` | [форматує дату і час відповідно до місцевості |#localDate]
 | `number` | [форматує число |#number]
 | `padLeft` | [завершує рядок до заданої довжини зліва |#padLeft]
 | `padRight` | [завершує рядок до заданої довжини справа |#padRight]
@@ -118,8 +120,8 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $
 =======================
 
 
-batch(int length, mixed item): array .[filter]
-----------------------------------------------
+batch(int $length, mixed $item): array .[filter]
+------------------------------------------------
 Фільтр, який спрощує виведення лінійних даних у вигляді таблиці. Повертає масив із заданою кількістю елементів. Якщо ви вкажете другий параметр, він буде використаний для заповнення пропущених елементів в останньому рядку.
 
 ```latte
@@ -152,6 +154,8 @@ batch(int length, mixed item): array .[filter]
 </table>
 ```
 
+Дивіться також тег [group |#group] та [iterateWhile |tags#iterateWhile].
+
 
 breakLines .[filter]
 --------------------
@@ -163,9 +167,9 @@ breakLines .[filter]
 ```
 
 
-bytes(int precision = 2) .[filter]
-----------------------------------
-Форматує розмір у байтах у зручну для читання форму.
+bytes(int $precision=2) .[filter]
+---------------------------------
+Форматує розмір у байтах у зручну для читання форму. Якщо задано [локаль |develop#locale], використовуються відповідні десяткові та тисячні роздільники.
 
 ```latte
 {$size|bytes}     0 B, 1.25 GB, …
@@ -173,8 +177,8 @@ bytes(int precision = 2) .[filter]
 ```
 
 
-ceil(int precision = 0) .[filter]
----------------------------------
+ceil(int $precision=0) .[filter]
+--------------------------------
 Округлює число до заданої точності.
 
 ```latte
@@ -203,8 +207,8 @@ checkUrl .[filter]
 
 ```latte
 {var $link = 'javascript:window.close()'}
-<a data-href="{$link|checkUrl}">checked</a>
-<a data-href="{$link}">unchecked</a>
+<a data-href={$link|checkUrl}>checked</a>
+<a data-href={$link}>unchecked</a>
 ```
 
 Виводить на друк:
@@ -217,8 +221,8 @@ checkUrl .[filter]
 Див. також [nocheck |#nocheck].
 
 
-clamp(int|float min, int|float max) .[filter]
----------------------------------------------
+clamp(int|float $min, int|float $max) .[filter]
+-----------------------------------------------
 Повертає значення, обмежене діапазоном min та max.
 
 ```latte
@@ -228,14 +232,14 @@ clamp(int|float min, int|float max) .[filter]
 Існує також у вигляді [функції |functions#clamp].
 
 
-dataStream(string mimetype = detect) .[filter]
-----------------------------------------------
+dataStream(string $mimetype=detect) .[filter]
+---------------------------------------------
 Перетворює вміст на схему URI даних. Його можна використовувати для вставки зображень в HTML або CSS без необхідності посилання на зовнішні файли.
 
 Нехай у змінній є зображення `$img = Image::fromFile('obrazek.gif')`, тоді
 
 ```latte
-<img src="{$img|dataStream}">
+<img src={$img|dataStream}>
 ```
 
 Виводить, наприклад:
@@ -250,15 +254,16 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
 Потрібне розширення PHP `fileinfo`.
 
 
-date(string format) .[filter]
------------------------------
-Повертає дату в заданому форматі, використовуючи опції функцій PHP [php:strftime] або [php:date]. Фільтр отримує дату у вигляді мітки часу UNIX, рядка або об'єкта типу `DateTime`.
+date(string $format) .[filter]
+------------------------------
+Форматує дату і час відповідно до маски, що використовується функцією PHP [php:date]. Фільтр приймає дату у форматі мітки часу UNIX, як рядок або як об'єкт `DateTimeInterface`.
 
 ```latte
-{$today|date:'%d.%m.%Y'}
 {$today|date:'j. n. Y'}
 ```
 
+Дивіться також [localDate |#localDate].
+
 
 escapeUrl .[filter]
 -------------------
@@ -271,8 +276,8 @@ escapeUrl .[filter]
 Див. також [query |#query].
 
 
-explode(string separator = '') .[filter]
-----------------------------------------
+explode(string $separator='') .[filter]
+---------------------------------------
 Розділяє рядок за заданим роздільником і повертає масив рядків. Псевдонім для `split`.
 
 ```latte
@@ -306,8 +311,8 @@ first .[filter]
 Див. також [last |#last], [random |#random].
 
 
-floor(int precision = 0) .[filter]
-----------------------------------
+floor(int $precision=0) .[filter]
+---------------------------------
 Округлює число до заданої точності.
 
 ```latte
@@ -330,8 +335,27 @@ firstUpper .[filter]
 Див. також [capitalize |#capitalize], [lower |#lower] регістр, [upper |#upper] регістр.
 
 
-implode(string glue = '') .[filter]
------------------------------------
+group(string|int|\Closure $by): array .[filter]{data-version:3.0.16}
+--------------------------------------------------------------------
+Фільтр групує дані за різними критеріями.
+
+У цьому прикладі рядки таблиці групуються за стовпцем `categoryId`. На виході отримуємо масив масивів, де ключем є значення у стовпчику `categoryId`. Прочитайте [детальну інструкцію |cookbook/grouping].
+
+```latte
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Дивіться також [batch |#batch], функцію [group |functions#group] та тег [iterateWhile |tags#iterateWhile].
+
+
+implode(string $glue='') .[filter]
+----------------------------------
 Повертає рядок, який є конкатенацією рядків у масиві. Псевдонім для `join`.
 
 ```latte
@@ -346,8 +370,8 @@ implode(string glue = '') .[filter]
 ```
 
 
-indent(int level = 1, string char = "\t") .[filter]
----------------------------------------------------
+indent(int $level=1, string $char="\t") .[filter]
+-------------------------------------------------
 Відступає текст зліва на задану кількість табуляцій або інших символів, які ми вказуємо у другому необов'язковому аргументі. Порожні рядки не відступаються.
 
 ```latte
@@ -396,6 +420,68 @@ length .[filter]
 ```
 
 
+localDate(?string $format=null, ?string $date=null, ?string $time=null) .[filter]
+---------------------------------------------------------------------------------
+Форматує дату і час відповідно до [локалі |develop#locale], забезпечуючи узгоджене і локалізоване відображення часових даних у різних мовах і регіонах. Фільтр приймає дату у вигляді мітки часу UNIX, рядка або об'єкта `DateTimeInterface`.
+
+```latte
+{$date|localDate}                  {* 15. dubna 2024 *}
+{$date|format: yM}                 {* 4/2024 *}
+{$date|localDate: date: medium}    {* 15. 4. 2024 *}
+```
+
+Якщо ви використовуєте фільтр без жодних параметрів, він виведе дату в довгому форматі, як пояснюється далі.
+
+**a) Використання формату**
+
+Параметр `format` описує, які компоненти часу слід відображати. Він використовує літерні коди, де кількість повторень впливає на ширину виводу:
+
+| Рік | `y` / `yy` / `yyyy` | `2024` / `24` / `2024`
+| Місяць | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `сер` / `серпень`
+| День | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `нд` / `неділя`
+| Година | `j` / `H` / `h` | бажана / 24-годинна / 12-годинна
+| Хвилина | `m` / `mm` | `5` / `05` <small>(2 цифри в поєднанні з секундами)</small>
+| Секунда | `s` / `ss` | `8` / `08` <small>(2 цифри у поєднанні з хвилинами)</small>
+
+Порядок кодів у форматі не має значення, оскільки порядок компонентів буде відображено відповідно до умов локалізації. Таким чином, формат не залежить від локалі. Наприклад, формат `yyyyMMMMd` у локалі `en_US` виводить `April 15, 2024`, тоді як у локалі `cs_CZ` він виводить `15. dubna 2024`:
+
+| locale:  | uk-UA | en_US
+|---
+| `format: 'dMy'` | 10.08.2024 | 8/10/2024
+| `format: 'yM'` | 08.2024 | 8/2024
+| `format: 'yyyyMMMM'` | серпень 2024 р. | August 2024
+| `format: 'MMMM'` | серпень | August
+| `format: 'jm'` | 17:54 | 5:54 PM
+| `format: 'Hm'` | 17:54 | 17:54
+| `format: 'hm'` | 5:54 пп | 5:54 PM
+
+
+**b) Використання попередньо встановлених стилів**
+
+Параметри `date` і `time` визначають рівень деталізації відображення дати і часу. Ви можете вибрати один з декількох рівнів: `full`, `long`, `medium`, `short`. Ви можете відображати лише дату, лише час або обидва:
+
+| locale:  | uk-UA | en_US
+|---
+| `date: short` | 23.01.78 | 1/23/78
+| `date: medium` | 23 січ. 1978 р. | Jan 23, 1978
+| `date: long` | 23 січня 1978 р. | January 23, 1978
+| `date: full` | понеділок, 23 січня 1978 р. | Monday, January 23, 1978
+| `time: short` | 08:30 | 8:30 AM
+| `time: medium` | 08:30:59 | 8:30:59 AM
+| `time: long` | 08:30:59 GMT+1 | 8:30:59 AM GMT+1
+| `date: short, time: short` | 23.01.78, 08:30 | 1/23/78, 8:30 AM
+| `date: medium, time: short` | 23 січ. 1978 р., 08:30 | Jan 23, 1978, 8:30 AM
+| `date: long, time: short` | 23 січня 1978 р. о 08:30 | January 23, 1978 at 8:30 AM
+
+Для дати можна також використовувати префікс `relative-` (наприклад, `relative-short`), який для дат, близьких до теперішнього часу, покаже `yesterday`, `today` або `tomorrow`; в іншому випадку, він буде відображатися стандартним чином.
+
+```latte
+{$date|localDate: date: relative-short}    {* yesterday *}
+```
+
+Див. також [дата |#date].
+
+
 lower .[filter]
 ---------------
 Перетворює значення в нижній регістр. Потрібне розширення PHP `mbstring`.
@@ -416,8 +502,8 @@ nocheck .[filter]
 ```latte
 {var $link = 'javascript:window.close()'}
 
-<a href="{$link}">checked</a>
-<a href="{$link|nocheck}">unchecked</a>
+<a href={$link}>checked</a>
+<a href={$link|nocheck}>unchecked</a>
 ```
 
 Відбитки:
@@ -451,19 +537,67 @@ Unescaped: <b>hello</b>
 Неправильне використання фільтра `noescape` може призвести до XSS-уразливості! Ніколи не використовуйте його, якщо ви не впевнені в тому, що ви робите, і що рядок, який ви друкуєте, походить з надійного джерела.
 
 
-number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter]
-------------------------------------------------------------------------------------
-Форматує число до заданої кількості десяткових знаків. Ви також можете вказати символ десяткової крапки та роздільник тисяч.
+number(int $decimals=0, string $decPoint='.', string $thousandsSep=',') .[filter]
+---------------------------------------------------------------------------------
+Форматує число до вказаної кількості десяткових знаків. Якщо задано [локаль |develop#locale], використовуються відповідні роздільники десяткових і тисячних знаків.
 
 ```latte
-{1234.20 |number}              1,234
+{1234.20|number} 1,234
 {1234.20 |number:1}            1,234.2
 {1234.20 |number:2}            1,234.20
-{1234.20 |number:2, ',', ' '}  1 234,20
+{1234.20|number:2, ',', ' '}  1 234,20
 ```
 
 
-padLeft(int length, string pad = ' ') .[filter]
+number(string $format) .[filter]
+--------------------------------
+Параметр `format` дозволяє визначити зовнішній вигляд чисел точно відповідно до ваших потреб. Для цього потрібна встановлена [локаль |develop#locale]. Формат складається з декількох спеціальних символів, повний опис яких можна знайти в документації "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns:
+
+- <c id=6/> обов'язкова цифра, завжди відображається, навіть якщо це нуль
+- `#` необов'язкова цифра, відображається тільки якщо на цьому місці в числі є цифра
+- `@` значуща цифра, допомагає відобразити число з певною кількістю значущих цифр
+- `.` позначає, де повинен стояти десятковий роздільник (кома або крапка, залежно від локалі)
+- `,` використовується для відокремлення груп цифр, зазвичай тисяч
+- `%` множить число на 100 і додає знак відсотків
+
+Розглянемо кілька прикладів. У першому прикладі два знаки після коми є обов'язковими, у другому - необов'язковими. У третьому прикладі з обох боків додаються нулі, а в четвертому відображаються лише наявні цифри:
+
+```latte
+{1234.5|number: '#,##0.00'}     {* 1,234.50 *}
+{1234.5|number: '#,##0.##'}     {* 1,234.5 *}
+{1.23  |number: '000.000'}      {* 001.230 *}
+{1.2   |number: '##.##'}        {* 1.2 *}
+```
+
+Значущі цифри визначають, скільки цифр, незалежно від десяткової крапки, слід відображати, округлюючи число, якщо це необхідно:
+
+```latte
+{1234|number: '@@'}             {* 1200 *}
+{1234|number: '@@@'}            {* 1230 *}
+{1234|number: '@@@#'}           {* 1234 *}
+{1.2345|number: '@@@'}          {* 1.23 *}
+{0.00123|number: '@@'}          {* 0.0012 *}
+```
+
+Простий спосіб відобразити число у відсотках. Число множиться на 100 і додається знак `%`:
+
+```latte
+{0.1234|number: '#.##%'}        {* 12.34% *}
+```
+
+Ми можемо визначити різний формат для додатних і від'ємних чисел, розділених символом `;`. Таким чином, наприклад, додатні числа можуть відображатися зі знаком `+`:
+
+```latte
+{42|number: '#.##;(#.##)'}      {* 42 *}
+{-42|number: '#.##;(#.##)'}     {* (42) *}
+{42|number: '+#.##;-#.##'}      {* +42 *}
+{-42|number: '+#.##;-#.##'}     {* -42 *}
+```
+
+Пам'ятайте, що фактичний вигляд чисел може відрізнятися залежно від налаштувань локалі. Наприклад, у деяких країнах замість крапки в якості десяткового роздільника використовується кома. Цей фільтр автоматично враховує це, тому вам не потрібно про це турбуватися.
+
+
+padLeft(int $length, string $pad=' ') .[filter]
 -----------------------------------------------
 Доповнює рядок до певної довжини іншим рядком зліва.
 
@@ -472,7 +606,7 @@ padLeft(int length, string pad = ' ') .[filter]
 ```
 
 
-padRight(int length, string pad = ' ') .[filter]
+padRight(int $length, string $pad=' ') .[filter]
 ------------------------------------------------
 Заміщає рядок до певної довжини іншим рядком праворуч.
 
@@ -514,8 +648,8 @@ random .[filter]
 Дивіться також [first |#first], [last |#last].
 
 
-repeat(int count) .[filter]
----------------------------
+repeat(int $count) .[filter]
+----------------------------
 Повторює рядок x разів.
 
 ```latte
@@ -523,7 +657,7 @@ repeat(int count) .[filter]
 ```
 
 
-replace(string|array search, string replace = '') .[filter]
+replace(string|array $search, string $replace='') .[filter]
 -----------------------------------------------------------
 Замінює всі входження пошукового рядка на рядок заміни.
 
@@ -538,7 +672,7 @@ replace(string|array search, string replace = '') .[filter]
 ```
 
 
-replaceRE(string pattern, string replace = '') .[filter]
+replaceRE(string $pattern, string $replace='') .[filter]
 --------------------------------------------------------
 Замінює всі входження відповідно до регулярного виразу.
 
@@ -559,8 +693,8 @@ reverse .[filter]
 ```
 
 
-round(int precision = 0) .[filter]
-----------------------------------
+round(int $precision=0) .[filter]
+---------------------------------
 Округляє число до заданої точності.
 
 ```latte
@@ -573,7 +707,7 @@ round(int precision = 0) .[filter]
 Див. також [ceil |#ceil], [floor |#floor].
 
 
-slice(int start, int length = null, bool preserveKeys = false) .[filter]
+slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter]
 ------------------------------------------------------------------------
 Витягує фрагмент масиву або рядка.
 
@@ -591,9 +725,9 @@ slice(int start, int length = null, bool preserveKeys = false) .[filter]
 За замовчуванням фільтр перевпорядковує і скидає ключі цілочисельних масивів. Цю поведінку можна змінити, встановивши preserveKeys у true. Рядкові ключі завжди зберігаються, незалежно від цього параметра.
 
 
-sort  .[filter]
----------------
-Фільтр, який сортує масив і зберігає зв'язок індексів.
+sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter]
+--------------------------------------------------------------------------------------------------------------
+Фільтр сортує елементи масиву або ітератора зі збереженням їхніх асоціативних ключів. Якщо задано [локаль |develop#locale], сортування відбувається за її правилами, якщо не вказано власну функцію порівняння.
 
 ```latte
 {foreach ($names|sort) as $name}
@@ -609,12 +743,38 @@ sort  .[filter]
 {/foreach}
 ```
 
-Ви можете передати власну функцію порівняння як параметр:
+Ви можете вказати власну функцію порівняння для сортування (у прикладі показано, як змінити сортування від найбільшого до найменшого):
 
 ```latte
-{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
+{var $reverted = ($names|sort: fn($a, $b) => $b <=> $a)}
 ```
 
+Фільтр `|sort` також дозволяє сортувати елементи за ключем:
+
+```latte
+{foreach ($names|sort: byKey: true) as $name}
+	...
+{/foreach}
+```
+
+Якщо вам потрібно відсортувати таблицю за певним стовпцем, ви можете використовувати параметр `by`. Значення `'name'` у прикладі вказує, що сортування буде виконано за `$row->name` або `$row['name']`залежно від того, чи є `$row` масивом або об'єктом:
+
+```latte
+{foreach ($items|sort: by: 'name') as $item}
+	{$item->name}
+{/foreach}
+```
+
+Ви також можете визначити функцію зворотного виклику, яка визначає значення для сортування:
+
+```latte
+{foreach ($items|sort: by: fn($items) => $items->category->name) as $item}
+	{$item->name}
+{/foreach}
+```
+
+Параметр `byKey` можна використовувати так само.
+
 
 spaceless  .[filter]
 --------------------
@@ -646,8 +806,8 @@ stripHtml .[filter]
 Отриманий в результаті звичайний текст може містити символи, які представляють теги HTML, наприклад, `'&lt;p&gt;'|stripHtml` буде перетворено на `<p>`. Ніколи не виводьте отриманий текст у вигляді `|noescape`, оскільки це може призвести до уразливості.
 
 
-substr(int offset, int length = null) .[filter]
------------------------------------------------
+substr(int $offset, ?int $length=null) .[filter]
+------------------------------------------------
 Витягує фрагмент рядка. Цей фільтр було замінено на фільтр [фрагментів |#slice].
 
 ```latte
@@ -655,8 +815,8 @@ substr(int offset, int length = null) .[filter]
 ```
 
 
-translate(string message, ...args) .[filter]
---------------------------------------------
+translate(string $message, ...$args) .[filter]
+----------------------------------------------
 Перекладає вирази на інші мови. Щоб зробити фільтр доступним, вам потрібно [налаштувати пере |develop#TranslatorExtension]кладач. Ви також можете використовувати [теги для перекладу |tags#Translation].
 
 ```latte
@@ -665,8 +825,8 @@ translate(string message, ...args) .[filter]
 ```
 
 
-trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
--------------------------------------------------------
+trim(string $charlist=" \t\n\r\0\x0B\u{A0}") .[filter]
+------------------------------------------------------
 Видаляти початкові та кінцеві символи, за замовчуванням пробіли.
 
 ```latte
@@ -675,7 +835,7 @@ trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter]
 ```
 
 
-truncate(int length, string append = '…') .[filter]
+truncate(int $length, string $append='…') .[filter]
 ---------------------------------------------------
 Скорочує рядок до максимально заданої довжини, але намагається зберегти цілі слова. Якщо рядок укорочено, додає в кінці багатокрапку (це можна змінити за допомогою другого параметра).
 
diff --git a/latte/uk/functions.texy b/latte/uk/functions.texy
index dcd6d83ca4..8b272fbd6d 100644
--- a/latte/uk/functions.texy
+++ b/latte/uk/functions.texy
@@ -9,6 +9,8 @@
 | `divisibleBy`| [перевіряє, чи ділиться змінна на число |#divisibleBy]
 | `even` | [перевіряє, чи є дане число парним |#even]
 | `first` | [повертає перший елемент масиву або символ рядка |#first]
+| `group` | [групує дані за різними критеріями |#group]
+| `hasBlock` | [виявляє наявність блоку |#hasBlock]
 | `last` | [pповертає останній елемент масиву або символ рядка |#last]
 | `odd` | [перевіряє, чи є дане число непарним |#odd]
 | `slice` | [витягує фрагмент масиву або рядка |#slice]
@@ -73,8 +75,8 @@ even(int $value): bool .[method]
 ```
 
 
-first(string|array $value): mixed .[method]
--------------------------------------------
+first(string|iterable $value): mixed .[method]
+----------------------------------------------
 Повертає перший елемент масиву або символ рядка:
 
 ```latte
@@ -85,6 +87,36 @@ first(string|array $value): mixed .[method]
 Див. також [last |#last], [filter first |filters#first].
 
 
+group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16}
+------------------------------------------------------------------------------------
+Ця функція групує дані за різними критеріями.
+
+У цьому прикладі рядки таблиці групуються за стовпцем `categoryId`. Результатом є масив полів, де ключем є значення у стовпчику `categoryId`. Прочитайте [детальну інструкцію |cookbook/grouping].
+
+```latte
+{foreach group($items, categoryId) as $categoryId => $categoryItems}
+    <ul>
+        {foreach $categoryItems as $item}
+            <li>{$item->name}</li>
+        {/foreach}
+    </ul>
+{/foreach}
+```
+
+Дивіться також [групу |filters#group] фільтрів.
+
+
+hasBlock(string $name): bool .[method]{data-version:3.0.10}
+-----------------------------------------------------------
+Перевіряє, чи існує блок з вказаною назвою:
+
+```latte
+{if hasBlock(header)} ... {/if}
+```
+
+Див. також [перевірка існування блоку |template-inheritance#Checking Block Existence].
+
+
 last(string|array $value): mixed .[method]
 ------------------------------------------
 Повертає останній елемент масиву або символ рядка:
@@ -106,8 +138,8 @@ odd(int $value): bool .[method]
 ```
 
 
-slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method]
-----------------------------------------------------------------------------------------------------------
+slice(string|array $value, int $start, ?int $length=null, bool $preserveKeys=false): string|array .[method]
+-----------------------------------------------------------------------------------------------------------
 Витягує фрагмент масиву або рядка.
 
 ```latte
diff --git a/latte/uk/recipes.texy b/latte/uk/recipes.texy
index 29537ce07e..33db8bf8af 100644
--- a/latte/uk/recipes.texy
+++ b/latte/uk/recipes.texy
@@ -9,7 +9,7 @@
 
 - NetBeans IDE має вбудовану підтримку
 - PhpStorm: встановіть [плагін Latte |https://plugins.jetbrains.com/plugin/7457-latte] в `Settings > Plugins > Marketplace`
-- VS Code: знайдіть у маркерплейсі плагін "Nette Latte + Neon"
+- VS Code: пошук маркерів для плагіна [шаблонів |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] або [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]
 - Sublime Text 3: у Package Control знайдіть і встановіть пакет `Nette` і виберіть Latte in `View > Syntax`
 - у старих редакторах використовуйте підсвічування Smarty для файлів .latte
 
diff --git a/latte/uk/safety-first.texy b/latte/uk/safety-first.texy
index 46ffe3c360..567c5010b6 100644
--- a/latte/uk/safety-first.texy
+++ b/latte/uk/safety-first.texy
@@ -351,7 +351,7 @@ Latte автоматично перевіряє, чи містить змінн
 ```latte
 {var $link = 'javascript:attack()'}
 
-<a href="{$link}">click here</a>
+<a href={$link}>click here</a>
 ```
 
 Пише:
diff --git a/latte/uk/syntax.texy b/latte/uk/syntax.texy
index d8b174c598..6cfd21070d 100644
--- a/latte/uk/syntax.texy
+++ b/latte/uk/syntax.texy
@@ -98,7 +98,7 @@ Prints:
 Або за допомогою префікса `tag-` функціональність застосовується тільки до HTML-тегів:
 
 ```latte
-<p><a href="{$url}" n:tag-if="$url">Title</a></p>
+<p><a href={$url} n:tag-if="$url">Title</a></p>
 ```
 
 Залежно від значення змінної `$url` буде виведено таке:
@@ -155,6 +155,20 @@ Latte дозволяє викликати фільтри за допомогою
 ```
 
 
+Динамічні теги HTML .[#toc-dynamic-html-tags]
+=============================================
+
+Latte підтримує динамічні HTML-теги, які корисні, коли вам потрібна гнучкість у назвах тегів:
+
+```latte
+<h{$level}>Heading</h{$level}>
+```
+
+Наприклад, код вище може згенерувати `<h1>Heading</h1>` або `<h2>Heading</h2>` в залежності від значення змінної `$level`. Динамічні HTML-теги в Latte завжди повинні бути парними. Їх альтернативою є [n:tag |tags#n:tag].
+
+Оскільки Latte є безпечною системою шаблонів, вона перевіряє, що результуюче ім'я тегу є дійсним і не містить небажаних або шкідливих значень. Вона також гарантує, що ім'я кінцевого тегу завжди збігається з ім'ям початкового тегу.
+
+
 Коментарі .[#toc-comments]
 ==========================
 
diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy
index 4fe83f6b5a..c7abb10170 100644
--- a/latte/uk/tags.texy
+++ b/latte/uk/tags.texy
@@ -16,6 +16,7 @@
 | `{ifset}`... `{elseifset}`... `{/ifset}` | [умова ifset |#ifset-elseifset]
 | `{ifchanged}`... `{/ifchanged}` | [перевірка наявності змін |#ifchanged]
 | `{switch}` `{case}` `{default}` `{/switch}` | [умова switch |#switch-case-default]
+| `n:else` | [альтернативний контент для умов |#n:else]
 
 .[table-latte-tags language-latte]
 |## Loops
@@ -97,8 +98,8 @@
 |</m> `{link}` | [друкує посилання |application:creating-links#In-the-Presenter-Template]
 | `{plink}` | [друкує посилання на ведучого |application:creating-links#In-the-Presenter-Template]
 | `{control}` | [друкує компонент |application:components#Rendering]
-| `{snippet}`... `{/snippet}` | [фрагмент шаблону, який може бути відправлений за допомогою AJAX |application:ajax#Tag-snippet]
-| `{snippetArea}` | конверт сніпетів
+| `{snippet}`... `{/snippet}` | [фрагмент шаблону, який може бути відправлений за допомогою AJAX |application:ajax#snippets-in-latte]
+| `{snippetArea}` | [конверт сніпетів |application:ajax#snippet-areas]
 | `{cache}`... `{/cache}` | [кешує розділ шаблону |caching:#Caching-in-Latte]
 
 .[table-latte-tags language-latte]
@@ -108,9 +109,6 @@
 | `{input}` | [друкує елемент введення форми |forms:rendering#label-input]
 | `{inputError}` | [друкує повідомлення про помилку для елемента введення форми |forms:rendering#inputError]
 | `n:name` | [активує елемент введення HTML |forms:rendering#n:name]
-| `{formPrint}` | [генерує креслення форми Latte |forms:rendering#formPrint]
-| `{formPrintClass}` | [друкує PHP клас для даних форми |forms:in-presenter#Mapping-to-Classes]
-| `{formContext}`... `{/formContext}` | [частковий рендеринг форми |forms:rendering#special-cases]
 | `{formContainer}`... `{/formContainer}` | [рендеринг контейнера форми |forms:rendering#special-cases]
 
 
@@ -247,6 +245,20 @@ Age: {date('Y') - $birth}<br>
 Чудово.
 
 
+`n:else` .{data-version:3.0.11}
+-------------------------------
+
+Якщо ви запишете умову `{if} ... {/if}` у вигляді [n:атрибута |syntax#n:attributes], у вас буде можливість вказати альтернативну гілку за допомогою `n:else`:
+
+```latte
+<strong n:if="$count > 0">In stock {$count} items</strong>
+
+<em n:else>not available</em>
+```
+
+Атрибут `n:else` також можна використовувати у поєднанні з [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]та [`n:ifchanged` |#ifchanged].
+
+
 `{/if $cond}`
 -------------
 
@@ -280,7 +292,7 @@ Age: {date('Y') - $birth}<br>
 Використовуйте умову `{ifset $var}`, щоб визначити, чи існує змінна (або кілька змінних) і чи має вона ненульове значення. Насправді це те саме, що й `if (isset($var))` у PHP. Як і будь-який парний тег, цей може бути записаний у вигляді [n:attribute |syntax#n-attributes], тому покажемо його на прикладі:
 
 ```latte
-<meta name="robots" content="{$robots}" n:ifset="$robots">
+<meta name="robots" content={$robots} n:ifset="$robots">
 ```
 
 
@@ -470,7 +482,7 @@ Age: {date('Y') - $birth}<br>
 `{iterateWhile}`
 ----------------
 
-Спрощує групування лінійних даних під час ітерації в циклі foreach, виконуючи ітерацію у вкладеному циклі доти, доки виконується умова. [Читайте інструкції в книзі рецептів |cookbook/iteratewhile].
+Спрощує групування лінійних даних під час ітерації в циклі foreach, повторюючи її у вкладеному циклі, доки не буде виконано певну умову. Прочитайте [детальну інструкцію |cookbook/grouping].
 
 Він також може елегантно замінити `{first}` і `{last}` у прикладі вище:
 
@@ -489,6 +501,8 @@ Age: {date('Y') - $birth}<br>
 {/foreach}
 ```
 
+Дивіться також [пакетні |filters#batch] та [групові |filters#group] фільтри.
+
 
 `{for}`
 -------
@@ -991,6 +1005,8 @@ n:tag .[#toc-n-tag]
 <h3 class="main">...</h3>
 ```
 
+Оскільки Latte - це безпечна система шаблонів, вона перевіряє, що нове ім'я тегу є дійсним і не містить небажаних або шкідливих значень.
+
 
 n:ifcontent .[#toc-n-ifcontent]
 -------------------------------
diff --git a/latte/uk/template-inheritance.texy b/latte/uk/template-inheritance.texy
index 3563a28690..8f16189a33 100644
--- a/latte/uk/template-inheritance.texy
+++ b/latte/uk/template-inheritance.texy
@@ -132,7 +132,7 @@
 
 - Якщо ви використовуєте `{layout}` у шаблоні, він має бути першим тегом шаблону в цьому шаблоні.
 
-- Макет можна [шукати автоматично |develop#automatic-layout-lookup] (як у [презентаторах |application:templates#search-for-templates]). У цьому випадку, якщо шаблон не повинен мати макет, він вкаже на це тегом `{layout none}`.
+- Макет можна [шукати автоматично |develop#automatic-layout-lookup] (як у [презентаторах |application:templates#Template Lookup]). У цьому випадку, якщо шаблон не повинен мати макет, він вкаже на це тегом `{layout none}`.
 
 - Тег `{layout}` має псевдонім `{extends}`.
 
@@ -396,6 +396,14 @@ Hi, I am Mary.
 {/ifset}
 ```
 
+Існування блоків також повертається функцією [`hasBlock()` |functions#hasBlock]:
+
+```latte
+{if hasBlock(header) || hasBlock(footer)}
+	...
+{/if}
+```
+
 
 Поради .[#toc-tips]
 -------------------
@@ -415,7 +423,7 @@ Hi, I am Mary.
 Горизонтальне повторне використання `{import}` .{toc: Horizontal Reuse}
 =======================================================================
 
-Горизонтальне повторне використання - це третій механізм повторного використання та успадкування в Latte. Він дозволяє завантажувати блоки з інших шаблонів. Це схоже на створення PHP-файлу з допоміжними функціями або трейтом.
+Горизонтальне повторне використання - це третій механізм повторного використання та успадкування в Latte. Він дозволяє завантажувати блоки з інших шаблонів. Це схоже на створення файлу з допоміжними функціями в PHP, а потім завантаження його за допомогою `require`.
 
 Хоча успадкування шаблонів є однією з найпотужніших функцій Latte, воно обмежується простим успадкуванням - шаблон може розширювати лише один інший шаблон. Горизонтальне повторне використання - це спосіб досягти множинного успадкування.
 
@@ -447,7 +455,7 @@ Hi, I am Mary.
 
 Ви можете використовувати стільки виразів `{import}`, скільки хочете, у будь-якому даному шаблоні. Якщо два імпортованих шаблони визначають один і той самий блок, перемагає перший. Однак найвищий пріоритет віддається головному шаблону, який може перезаписати будь-який імпортований блок.
 
-Усі перевизначені блоки можна включати поступово, вставляючи їх як [батьківський блок |#Parent-Block]:
+Вміст перезаписаних блоків можна зберегти, вставивши його так само, як і [батьківський блок |#parent block]:
 
 ```latte
 {layout 'layout.latte'}
diff --git a/mail/bg/@home.texy b/mail/bg/@home.texy
index 5424d32152..337a611aef 100644
--- a/mail/bg/@home.texy
+++ b/mail/bg/@home.texy
@@ -74,7 +74,7 @@ $mail->setHtmlBody(
 Прикачени файлове .[#toc-attachments]
 -------------------------------------
 
-Разбира се, можете да прикачвате прикачени файлове към имейли. Използвайте командата `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Разбира се, можете да прикачвате прикачени файлове към имейли. Използвайте командата `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 //вмъкнете файла /path/to/example.zip в имейла като example.zip
diff --git a/mail/cs/@home.texy b/mail/cs/@home.texy
index bf63b65369..45a1700470 100644
--- a/mail/cs/@home.texy
+++ b/mail/cs/@home.texy
@@ -74,7 +74,7 @@ E-mail je něco jako pohlednice. Nikdy e-mailem neposílejte hesla ani jiné př
 Přílohy
 -------
 
-Do e-mailu lze samozřejmě vkládat přílohy. Slouží k tomu metoda `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Do e-mailu lze samozřejmě vkládat přílohy. Slouží k tomu metoda `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // vloží do e-mailu soubor /path/to/example.zip pod názvem example.zip
diff --git a/mail/de/@home.texy b/mail/de/@home.texy
index 4c01d1821c..418365dc32 100644
--- a/mail/de/@home.texy
+++ b/mail/de/@home.texy
@@ -74,7 +74,7 @@ E-Mails sind wie Postkarten. Senden Sie niemals Passwörter oder andere Anmeldei
 Anhänge .[#toc-attachments]
 ---------------------------
 
-Sie können natürlich auch Anhänge an E-Mails anhängen. Verwenden Sie dazu die `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Sie können natürlich auch Anhänge an E-Mails anhängen. Verwenden Sie dazu die `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // fügt die Datei /path/to/example.zip in die E-Mail unter dem Namen example.zip ein
diff --git a/mail/el/@home.texy b/mail/el/@home.texy
index c5ff6af3c1..b0b2e906bc 100644
--- a/mail/el/@home.texy
+++ b/mail/el/@home.texy
@@ -74,7 +74,7 @@ $mail->setHtmlBody(
 Συνημμένα αρχεία .[#toc-attachments]
 ------------------------------------
 
-Μπορείτε, φυσικά, να επισυνάπτετε συνημμένα αρχεία στο ηλεκτρονικό ταχυδρομείο. Χρησιμοποιήστε το `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Μπορείτε, φυσικά, να επισυνάπτετε συνημμένα αρχεία στο ηλεκτρονικό ταχυδρομείο. Χρησιμοποιήστε το `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // εισάγει το αρχείο /path/to/example.zip στο email με το όνομα example.zip
diff --git a/mail/en/@home.texy b/mail/en/@home.texy
index fbf75e52f8..02d90c4555 100644
--- a/mail/en/@home.texy
+++ b/mail/en/@home.texy
@@ -74,7 +74,7 @@ Emails are like postcards. Never send passwords or other credentials via email.
 Attachments
 -----------
 
-You can, of course, attach attachments to email. Use the `addAttachment(string $file, string $content = null, string $contentType = null)`.
+You can, of course, attach attachments to email. Use the `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // inserts the file /path/to/example.zip into the email under the name example.zip
diff --git a/mail/es/@home.texy b/mail/es/@home.texy
index daa3af6859..120119c43d 100644
--- a/mail/es/@home.texy
+++ b/mail/es/@home.texy
@@ -74,7 +74,7 @@ Los correos electrónicos son como postales. Nunca envíes contraseñas u otras
 Archivos adjuntos .[#toc-attachments]
 -------------------------------------
 
-Por supuesto, puedes adjuntar archivos al correo electrónico. Utilice la dirección `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Por supuesto, puedes adjuntar archivos al correo electrónico. Utilice la dirección `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // inserts the file /path/to/example.zip into the email under the name example.zip
diff --git a/mail/fr/@home.texy b/mail/fr/@home.texy
index be9d696844..9ae629ee8b 100644
--- a/mail/fr/@home.texy
+++ b/mail/fr/@home.texy
@@ -74,7 +74,7 @@ Les courriels sont comme des cartes postales. N'envoyez jamais de mots de passe
 Pièces jointes .[#toc-attachments]
 ----------------------------------
 
-Vous pouvez, bien entendu, joindre des pièces jointes à un courriel. Utilisez l'adresse `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Vous pouvez, bien entendu, joindre des pièces jointes à un courriel. Utilisez l'adresse `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // insère le fichier /path/to/example.zip dans l'email sous le nom example.zip
diff --git a/mail/hu/@home.texy b/mail/hu/@home.texy
index 4d2ce88d14..fcd1279e2d 100644
--- a/mail/hu/@home.texy
+++ b/mail/hu/@home.texy
@@ -74,7 +74,7 @@ Az e-mailek olyanok, mint a képeslapok. Soha ne küldjön jelszavakat vagy más
 Csatolmányok .[#toc-attachments]
 --------------------------------
 
-Természetesen csatolhat csatolmányokat is az e-mailhez. Használja a `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Természetesen csatolhat csatolmányokat is az e-mailhez. Használja a `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // beilleszti a /path/to/example.zip fájlt az e-mailbe a example.zip név alatt.
diff --git a/mail/it/@home.texy b/mail/it/@home.texy
index 55fb089c07..f59bf45fda 100644
--- a/mail/it/@home.texy
+++ b/mail/it/@home.texy
@@ -74,7 +74,7 @@ Le e-mail sono come cartoline. Non inviate mai password o altre credenziali via
 Allegati .[#toc-attachments]
 ----------------------------
 
-Naturalmente è possibile allegare allegati alle e-mail. Utilizzate l'indirizzo `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Naturalmente è possibile allegare allegati alle e-mail. Utilizzate l'indirizzo `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // inserisce il file /path/to/example.zip nella mail con il nome example.zip
diff --git a/mail/pl/@home.texy b/mail/pl/@home.texy
index 54ac4c1bec..0e60b4a989 100644
--- a/mail/pl/@home.texy
+++ b/mail/pl/@home.texy
@@ -74,7 +74,7 @@ E-mail jest jak pocztówka. Nigdy nie wysyłaj haseł ani innych danych dostępo
 Załączniki .[#toc-attachments]
 ------------------------------
 
-Do maila można oczywiście dodać załączniki. Odbywa się to za pomocą metody `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Do maila można oczywiście dodać załączniki. Odbywa się to za pomocą metody `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // wstawia do maila plik /path/to/example.zip pod nazwą example.zip
diff --git a/mail/pt/@home.texy b/mail/pt/@home.texy
index 6644a35da1..d3dc3475e5 100644
--- a/mail/pt/@home.texy
+++ b/mail/pt/@home.texy
@@ -74,7 +74,7 @@ Os e-mails são como cartões postais. Nunca envie senhas ou outras credenciais
 Anexos .[#toc-attachments]
 --------------------------
 
-Você pode, é claro, anexar anexos ao e-mail. Use o site `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Você pode, é claro, anexar anexos ao e-mail. Use o site `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // insere o arquivo /caminho/para/exemplo.zip no e-mail com o nome exemplo.zip
diff --git a/mail/ro/@home.texy b/mail/ro/@home.texy
index 11e5882075..52c544da38 100644
--- a/mail/ro/@home.texy
+++ b/mail/ro/@home.texy
@@ -74,7 +74,7 @@ E-mailurile sunt ca niște cărți poștale. Nu trimiteți niciodată parole sau
 Atașamente .[#toc-attachments]
 ------------------------------
 
-Puteți, desigur, să atașați atașamente la e-mail. Folosiți opțiunea `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Puteți, desigur, să atașați atașamente la e-mail. Folosiți opțiunea `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // inserează fișierul /path/to/example.zip în e-mail sub numele example.zip
diff --git a/mail/ru/@home.texy b/mail/ru/@home.texy
index f782650c0f..a4ba4398ca 100644
--- a/mail/ru/@home.texy
+++ b/mail/ru/@home.texy
@@ -74,7 +74,7 @@ $mail->setHtmlBody(
 Вложения .[#toc-attachments]
 ----------------------------
 
-Разумеется, вы можете прикреплять вложения к электронным письмам. Используйте команду `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Разумеется, вы можете прикреплять вложения к электронным письмам. Используйте команду `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // вставляет файл /path/to/example.zip в электронное письмо под именем example.zip
diff --git a/mail/sl/@home.texy b/mail/sl/@home.texy
index a322297f39..8c042f65b7 100644
--- a/mail/sl/@home.texy
+++ b/mail/sl/@home.texy
@@ -74,7 +74,7 @@ Elektronska sporočila so kot razglednice. Nikoli ne pošiljajte gesel ali drugi
 Priponke .[#toc-attachments]
 ----------------------------
 
-Elektronskemu sporočilu lahko seveda priložite priponke. Uporabite `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Elektronskemu sporočilu lahko seveda priložite priponke. Uporabite `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // vstavi datoteko /path/to/example.zip v e-pošto pod imenom example.zip
diff --git a/mail/tr/@home.texy b/mail/tr/@home.texy
index 55691e530d..9d77e6a2b3 100644
--- a/mail/tr/@home.texy
+++ b/mail/tr/@home.texy
@@ -74,7 +74,7 @@ E-postalar kartpostal gibidir. Parolaları veya diğer kimlik bilgilerini asla e
 Ekler .[#toc-attachments]
 -------------------------
 
-Elbette e-postaya ekler de ekleyebilirsiniz. `addAttachment(string $file, string $content = null, string $contentType = null)` adresini kullanın.
+Elbette e-postaya ekler de ekleyebilirsiniz. `addAttachment(string $file, ?string $content = null, ?string $contentType = null)` adresini kullanın.
 
 ```php
 // /path/to/example.zip dosyasını example.zip adı altında e-postaya ekler
diff --git a/mail/uk/@home.texy b/mail/uk/@home.texy
index ee34d14c1c..802b918506 100644
--- a/mail/uk/@home.texy
+++ b/mail/uk/@home.texy
@@ -74,7 +74,7 @@ $mail->setHtmlBody(
 Вкладення .[#toc-attachments]
 -----------------------------
 
-Зрозуміло, ви можете прикріплювати вкладення до електронних листів. Використовуйте команду `addAttachment(string $file, string $content = null, string $contentType = null)`.
+Зрозуміло, ви можете прикріплювати вкладення до електронних листів. Використовуйте команду `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.
 
 ```php
 // вставляє файл /path/to/example.zip в електронний лист під ім'ям example.zip
diff --git a/migrations/cs/@home.texy b/migrations/cs/@home.texy
index 9ef31ca6f9..18e175c7d9 100644
--- a/migrations/cs/@home.texy
+++ b/migrations/cs/@home.texy
@@ -1,6 +1,7 @@
 Přechod na novější verze
 ************************
 
+- [z Nette 3.1 na 3.2 |to-3-2]
 - [z Nette 3.0 na 3.1 |to-3-1]
 - [z Nette 2.4 na 3.0 |to-3-0]
 - [z Nette 2.3 na 2.4 |to-2-4]
diff --git a/migrations/cs/@left-menu.texy b/migrations/cs/@left-menu.texy
index 82c0d7e4a7..6f807d7d72 100644
--- a/migrations/cs/@left-menu.texy
+++ b/migrations/cs/@left-menu.texy
@@ -1,6 +1,7 @@
 Přechod na novější verze
 ************************
 - [Úvod |@home]
+- [Z verze 3.1 na 3.2 |to-3-2]
 - [Z verze 3.0 na 3.1 |to-3-1]
 - [Z verze 2.4 na 3.0 |to-3-0]
 - [Z verze 2.3 na 2.4 |to-2-4]
diff --git a/migrations/cs/to-2-3.texy b/migrations/cs/to-2-3.texy
index 2678fce526..bff8ab9808 100644
--- a/migrations/cs/to-2-3.texy
+++ b/migrations/cs/to-2-3.texy
@@ -1,14 +1,12 @@
 Přechod na verzi 2.3
 ********************
 
-Verzí Nette 2.3 se rozumí, že máte tyto balíčky nainstalované ve verze 2.3.*. Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer.
+Verzí Nette 2.3 se rozumí, že máte tyto balíčky nainstalované ve verzi 2.3.*:
 
 ```json
 "require": {
 	"nette/application": "2.3.*",
 	"nette/bootstrap": "2.3.*",
-	"nette/caching": "2.3.*",
-	"nette/database": "2.3.*",
 	"nette/di": "2.3.*",
 	"nette/forms": "2.3.*",
 	"nette/http": "2.3.*",
diff --git a/migrations/cs/to-2-4.texy b/migrations/cs/to-2-4.texy
index 7e9857cc16..4a12f4a9a9 100644
--- a/migrations/cs/to-2-4.texy
+++ b/migrations/cs/to-2-4.texy
@@ -3,14 +3,12 @@ Přechod na verzi 2.4
 
 Minimální požadovaná verze PHP je 5.6 (pro Latte a Tracy 5.4).
 
-Verzí Nette 2.4 se rozumí, že máte tyto balíčky nainstalované ve verze 2.4.* (resp. 2.5.*). Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer.
+Verzí Nette 2.4 se rozumí, že máte tyto balíčky nainstalované ve verzi 2.4.*:
 
 ```json
 "require": {
 	"nette/application": "2.4.*",
 	"nette/bootstrap": "2.4.*",
-	"nette/caching": "2.5.*",
-	"nette/database": "2.4.*",
 	"nette/di": "2.4.*",
 	"nette/forms": "2.4.*",
 	"nette/http": "2.4.*",
@@ -18,6 +16,8 @@ Verzí Nette 2.4 se rozumí, že máte tyto balíčky nainstalované ve verze 2.
 },
 ```
 
+Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje.
+
 
 Deprecated
 ==========
diff --git a/migrations/cs/to-3-0.texy b/migrations/cs/to-3-0.texy
index b0f3168f36..9eef7e537f 100644
--- a/migrations/cs/to-3-0.texy
+++ b/migrations/cs/to-3-0.texy
@@ -3,14 +3,12 @@ Přechod na verzi 3.0
 
 Minimální požadovaná verze PHP je 7.1.
 
-Verzí Nette 3.0 se rozumí, že máte tyto balíčky nainstalované ve verze 3.0.*. Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer.
+Verzí Nette 3.0 se rozumí, že máte tyto balíčky nainstalované ve verzi 3.0.*:
 
 ```json
 "require": {
 	"nette/application": "3.0.*",
 	"nette/bootstrap": "3.0.*",
-	"nette/caching": "3.0.*",
-	"nette/database": "3.0.*",
 	"nette/di": "3.0.*",
 	"nette/forms": "3.0.*",
 	"nette/http": "3.0.*",
@@ -18,6 +16,8 @@ Verzí Nette 3.0 se rozumí, že máte tyto balíčky nainstalované ve verze 3.
 },
 ```
 
+Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje.
+
 
 PHP 7.1 type hints
 ------------------
diff --git a/migrations/cs/to-3-1.texy b/migrations/cs/to-3-1.texy
index 87cb17b6d9..0b3fd295ef 100644
--- a/migrations/cs/to-3-1.texy
+++ b/migrations/cs/to-3-1.texy
@@ -3,22 +3,22 @@ Přechod na verzi 3.1
 
 Minimální požadovaná verze PHP je 7.2.
 
-Všechny změny názvů uvedené v tomto dokumentu znamenají, že původní název samozřejmě nadále existuje a funguje, jen je označený jako deprecated. Můžete se setkat s tím, že vám je bude IDE vizuálně označovat jako deprecated.
-
-Verzí Nette 3.1 se rozumí, že máte tyto balíčky nainstalované ve verze 3.1.*. Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer.
+Verzí Nette 3.1 se rozumí, že máte tyto balíčky nainstalované ve verze 3.1.*:
 
 ```json
 "require": {
 	"nette/application": "3.1.*",
 	"nette/bootstrap": "3.1.*",
-	"nette/caching": "3.1.*",
-	"nette/database": "3.1.*",
 	"nette/forms": "3.1.*",
 	"nette/http": "3.1.*",
 	"nette/security": "3.1.*",
 },
 ```
 
+Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje.
+
+Všemi změnami názvů uvedenými v tomto dokumentu se myslí, že původní názvy samozřejmě nadále existují a fungují, jen jsou označené jako deprecated. Můžete se setkat s tím, že vám je bude IDE vizuálně označovat jako deprecated.
+
 
 Názvy rozhraní
 --------------
diff --git a/migrations/cs/to-3-2.texy b/migrations/cs/to-3-2.texy
new file mode 100644
index 0000000000..d8ed7422e5
--- /dev/null
+++ b/migrations/cs/to-3-2.texy
@@ -0,0 +1,28 @@
+Přechod na verzi 3.2
+********************
+
+Minimální požadovaná verze PHP je 8.1.
+
+Verzí Nette 3.2 se rozumí, že máte tyto balíčky nainstalované ve verze 3.2.*:
+
+```json
+"require": {
+	"nette/application": "3.2.*",
+	"nette/bootstrap": "3.2.*",
+	"nette/forms": "3.2.*",
+	"nette/http": "3.3.*",
+	"nette/security": "3.2.*",
+},
+```
+
+Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje.
+
+
+Novinky
+-------
+
+Tato verze využívají všech vymožeností PHP 8. Kód tedy obsahuje všechny nové typehinty zavedené v PHP 8, typy u properties, nové jazykové featury a nativní funkce. Pokusil jsem se maximálně zachovat zpětnou kompatibilitu a tam, kde by přidání typu mohlo něco rozbít, jsem ho zatím nepřidával.
+
+Dále třídy až na výjimky přestaly využívat traitu Nette\SmartObject, protože její vylepšení po dlouhých letech proniklo do samotného PHP a už tak není potřeba.
+
+Finder se přestěhoval do balíčku `nette/utils`, odstraňte jej z composeru.
diff --git a/migrations/en/@home.texy b/migrations/en/@home.texy
index d49961c0f8..33b6c35c23 100644
--- a/migrations/en/@home.texy
+++ b/migrations/en/@home.texy
@@ -1,6 +1,7 @@
 Upgrade Guide
 *************
 
+- [from Nette 3.1 to 3.2 |to-3-2]
 - [from Nette 3.0 to 3.1 |to-3-1]
 - [from Nette 2.4 to 3.0 |to-3-0]
 - [from Nette 2.3 to 2.4 |to-2-4]
diff --git a/migrations/en/@left-menu.texy b/migrations/en/@left-menu.texy
index af1cd6e312..15d695bbc4 100644
--- a/migrations/en/@left-menu.texy
+++ b/migrations/en/@left-menu.texy
@@ -1,6 +1,7 @@
 Upgrade Guide
 *************
 - [Overview |@home]
+- [From 3.1 to 3.2 |to-3-2]
 - [From 3.0 to 3.1 |to-3-1]
 - [From 2.4 to 3.0 |to-3-0]
 - [From 2.3 to 2.4 |to-2-4]
diff --git a/migrations/en/to-2-3.texy b/migrations/en/to-2-3.texy
index 0abe9dcacd..ede630debb 100644
--- a/migrations/en/to-2-3.texy
+++ b/migrations/en/to-2-3.texy
@@ -1,14 +1,12 @@
 Migrating to Version 2.3
 ************************
 
-Nette version 2.3 means that you have these packages installed in version 2.3.*. Other packages may have higher or lower version numbers, compatibility is ensured by Composer.
+Nette 2.3 means that you have these packages installed in version 2.3.*:
 
 ```json
 "require": {
 	"nette/application": "2.3.*",
 	"nette/bootstrap": "2.3.*",
-	"nette/caching": "2.3.*",
-	"nette/database": "2.3.*",
 	"nette/di": "2.3.*",
 	"nette/forms": "2.3.*",
 	"nette/http": "2.3.*",
diff --git a/migrations/en/to-2-4.texy b/migrations/en/to-2-4.texy
index 40945dd76e..0f7a9257a7 100644
--- a/migrations/en/to-2-4.texy
+++ b/migrations/en/to-2-4.texy
@@ -3,14 +3,12 @@ Migrating to Version 2.4
 
 Minimum required PHP version is 5.6 (for Latte and Tracy 5.4).
 
-Nette version 2.4 means that you have these packages installed in version 2.4.* (or 2.5.*). Other packages may have higher or lower version numbers, compatibility is ensured by Composer.
+Nette version 2.4 means that you have these packages installed in version 2.4.*:
 
 ```json
 "require": {
 	"nette/application": "2.4.*",
 	"nette/bootstrap": "2.4.*",
-	"nette/caching": "2.5.*",
-	"nette/database": "2.4.*",
 	"nette/di": "2.4.*",
 	"nette/forms": "2.4.*",
 	"nette/http": "2.4.*",
@@ -18,6 +16,8 @@ Nette version 2.4 means that you have these packages installed in version 2.4.*
 },
 ```
 
+Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs.
+
 
 Deprecated Stuff
 ================
diff --git a/migrations/en/to-3-0.texy b/migrations/en/to-3-0.texy
index ebec235b37..c8011fe68a 100644
--- a/migrations/en/to-3-0.texy
+++ b/migrations/en/to-3-0.texy
@@ -3,14 +3,12 @@ Migrating to Version 3.0
 
 Minimum required PHP version is 7.1.
 
-Nette version 3.0 means that you have these packages installed in version 3.0.*. Other packages may have higher or lower version numbers, compatibility is ensured by Composer.
+Nette 3.0 means that you have these packages installed in version 3.0.*:
 
 ```json
 "require": {
 	"nette/application": "3.0.*",
 	"nette/bootstrap": "3.0.*",
-	"nette/caching": "3.0.*",
-	"nette/database": "3.0.*",
 	"nette/di": "3.0.*",
 	"nette/forms": "3.0.*",
 	"nette/http": "3.0.*",
@@ -18,6 +16,8 @@ Nette version 3.0 means that you have these packages installed in version 3.0.*.
 },
 ```
 
+Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs.
+
 
 PHP 7.1 Type Hints
 ------------------
diff --git a/migrations/en/to-3-1.texy b/migrations/en/to-3-1.texy
index c0e53998ee..f651b897da 100644
--- a/migrations/en/to-3-1.texy
+++ b/migrations/en/to-3-1.texy
@@ -3,22 +3,22 @@ Migrating to Version 3.1
 
 Minimum required PHP version is 7.2.
 
-All name changes mentioned in this document mean that the original name obviously still exists and works, it is just marked as deprecated. You may encounter the IDE visually marking them as deprecated.
-
-Nette version 3.1 means that you have these packages installed in version 3.1.*. Other packages may have higher or lower version numbers, compatibility is ensured by Composer.
+Nette version 3.1 means that you have these packages installed in version 3.1.*:
 
 ```json
 "require": {
 	"nette/application": "3.1.*",
 	"nette/bootstrap": "3.1.*",
-	"nette/caching": "3.1.*",
-	"nette/database": "3.1.*",
 	"nette/forms": "3.1.*",
 	"nette/http": "3.1.*",
 	"nette/security": "3.1.*",
 },
 ```
 
+Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs.
+
+All the name changes mentioned in this document mean that the original names still exist and work, of course, they are just marked as deprecated. You may encounter the IDE visually marking them as deprecated.
+
 
 Interface Names
 ---------------
@@ -65,7 +65,7 @@ Http
 - `Nette\Http\Request::getFile()` accepts array of keys and returns FileUpload|null
 - `Nette\Http\Session::getCookieParameters()` is deprecated
 - `Nette\Http\FileUpload::getName()` renamed to `getUntrustedName()`
-- `Nette\Http\Url`: deprecated getBasePath(), getBaseUrl(), getRelativeUrl() (tyto metody jsou součástí `UrlScript`)
+- `Nette\Http\Url`: deprecated `getBasePath()`, `getBaseUrl()`, `getRelativeUrl()` (these methods are part of `UrlScript`)
 - `Nette\Http\Response::$cookieHttpOnly` is deprecated
 - `Nette\Http\FileUpload::getImageSize()` returns pair `[width, height]`
 
diff --git a/migrations/en/to-3-2.texy b/migrations/en/to-3-2.texy
new file mode 100644
index 0000000000..2e33147c1e
--- /dev/null
+++ b/migrations/en/to-3-2.texy
@@ -0,0 +1,28 @@
+Migrating to Version 3.2
+************************
+
+Minimum required PHP version is 8.1.
+
+Nette version 3.2 means that you have these packages installed in version 3.2.*:
+
+```json
+"require": {
+	"nette/application": "3.2.*",
+	"nette/bootstrap": "3.2.*",
+	"nette/forms": "3.2.*",
+	"nette/http": "3.3.*",
+	"nette/security": "3.2.*",
+},
+```
+
+Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs.
+
+
+News
+----
+
+This version takes full advantage of all the features of PHP 8. So the code contains all the new typehints introduced in PHP 8, types for properties, new language features and native functions. I have tried to maintain backward compatibility as much as possible and where adding a type might break something, I have not added it yet.
+
+Furthermore, classes have, with a few exceptions, no longer use the Nette\SmartObject trait, as its enhancements after many years have made their way into PHP itself and are no longer needed.
+
+Finder has moved to the package `nette/utils`, remove it from composer.
diff --git a/neon/bg/@home.texy b/neon/bg/@home.texy
index 7825a8cde7..4b244620ff 100644
--- a/neon/bg/@home.texy
+++ b/neon/bg/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Връща `$value`, преобразуван в NEON. Параметърът `$blockMode` може да бъде подаден като true, което ще създаде многоредов изход. Параметърът `$indentation` задава символите, използвани за отстъпите (по подразбиране е tab).
 
diff --git a/neon/bg/format.texy b/neon/bg/format.texy
index 912e802462..03c6593461 100644
--- a/neon/bg/format.texy
+++ b/neon/bg/format.texy
@@ -119,11 +119,11 @@ country: USA
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 В PHP същата структура ще бъде записана по следния начин:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+В предишния случай написахме съпоставяне, чиито елементи бяха последователности. Сега нека опитаме да направим обратния опит и да създадем последователност, съдържаща мапинг:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Не е необходимо точките да са на отделни редове; те могат да бъдат разположени и по този начин:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+От вас зависи дали ще подравните булетите в колона, като използвате интервали или табулация.
+
 Тъй като PHP използва една и съща структура за съпоставки и последователности, т.е. масиви, двете могат да се комбинират. Този път отстъпите са същите:
 
 ```neon
diff --git a/neon/cs/@home.texy b/neon/cs/@home.texy
index 2f04820c6a..b570e235cf 100644
--- a/neon/cs/@home.texy
+++ b/neon/cs/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <cesta>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Vrací `$value` převedenou na NEON. Jako parametr `$blockMode` můžete předat true, čímž se vytvoří víceřádkový výstup. Parametr `$indentation` určuje znaky použité pro odsazení (výchozí je tabulátor).
 
diff --git a/neon/cs/format.texy b/neon/cs/format.texy
index 3535dbe153..7012e69d60 100644
--- a/neon/cs/format.texy
+++ b/neon/cs/format.texy
@@ -119,11 +119,11 @@ Hodnotami mapování a sekvencí mohou být jiné mapování a sekvence. Hlavní
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 V PHP by se stejná struktura zapsala jako:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+V předchozím případě jsme zapsali mapovaní, jehož prvky byly sekvence, teď to zkusíme obráceně a vytvoříme sekvenci obsahující mapování:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Není nutné, aby odrážky byly na samostatných řádcích, lze je umístit i tímto způsobem:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Je na vás, jestli klíče zarovnáte do sloupce pomocí mezer nebo použijete tabulátor.
+
 Protože v PHP se používá pro mapování i sekvence stejná struktura, tedy pole, lze obojí sloučit. Odsazení je tentokrát stejné:
 
 ```neon
diff --git a/neon/de/@home.texy b/neon/de/@home.texy
index 8ff52bc8dd..cb947a73a8 100644
--- a/neon/de/@home.texy
+++ b/neon/de/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Gibt `$value` in NEON konvertiert zurück. Als Parameter `$blockMode` können Sie true übergeben, was eine mehrzeilige Ausgabe erzeugt. Der Parameter `$indentation` gibt die für die Einrückung verwendeten Zeichen an (Standard ist tab).
 
diff --git a/neon/de/format.texy b/neon/de/format.texy
index c3898cf997..f741101004 100644
--- a/neon/de/format.texy
+++ b/neon/de/format.texy
@@ -119,11 +119,11 @@ Werte von Mappings und Sequenzen können andere Mappings und Sequenzen sein. Der
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 In PHP würde die gleiche Struktur wie folgt geschrieben werden:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+Im vorherigen Fall haben wir eine Abbildung geschrieben, deren Elemente Sequenzen waren. Versuchen wir es nun andersherum und erstellen eine Sequenz, die Mappings enthält:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Die Aufzählungspunkte müssen nicht unbedingt in separaten Zeilen stehen, sondern können auch auf diese Weise platziert werden:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Es bleibt Ihnen überlassen, ob Sie die Tasten in einer Spalte mit Leerzeichen oder mit einem Tabulator ausrichten.
+
 Da PHP die gleiche Struktur für Mapping und Sequenzen verwendet, nämlich Arrays, können beide zusammengeführt werden. Die Einrückung ist dieses Mal die gleiche:
 
 ```neon
diff --git a/neon/el/@home.texy b/neon/el/@home.texy
index 38e047f559..e61712f6f1 100644
--- a/neon/el/@home.texy
+++ b/neon/el/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Επιστρέφει το `$value` σε NEON. Ως παράμετρος `$blockMode` μπορείτε να περάσετε την true, η οποία θα δημιουργήσει έξοδο πολλαπλών γραμμών. Η παράμετρος `$indentation` καθορίζει τους χαρακτήρες που χρησιμοποιούνται για την εσοχή (προεπιλογή είναι το tab).
 
diff --git a/neon/el/format.texy b/neon/el/format.texy
index bf28f3a1d0..4c80868abc 100644
--- a/neon/el/format.texy
+++ b/neon/el/format.texy
@@ -119,11 +119,11 @@ country: USA
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 Στην PHP, η ίδια δομή θα γραφόταν ως εξής:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+Στην προηγούμενη περίπτωση, γράψαμε μια απεικόνιση της οποίας τα στοιχεία ήταν ακολουθίες. Τώρα, ας δοκιμάσουμε το αντίστροφο και ας δημιουργήσουμε μια ακολουθία που περιέχει απεικονίσεις:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Δεν είναι απαραίτητο τα κουκκίδες να βρίσκονται σε ξεχωριστές γραμμές- μπορούν επίσης να τοποθετηθούν με αυτόν τον τρόπο:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Εξαρτάται από εσάς αν θα ευθυγραμμίσετε τα πλήκτρα σε μια στήλη χρησιμοποιώντας διαστήματα ή ένα tab.
+
 Επειδή η PHP χρησιμοποιεί την ίδια δομή για την αντιστοίχιση και τις ακολουθίες, δηλαδή πίνακες, και οι δύο μπορούν να συγχωνευθούν. Η εσοχή είναι η ίδια αυτή τη φορά:
 
 ```neon
diff --git a/neon/en/@home.texy b/neon/en/@home.texy
index c560bffaf2..8fb97e8cac 100644
--- a/neon/en/@home.texy
+++ b/neon/en/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Returns `$value` converted to NEON. As the parameter `$blockMode` you can pass true, which will create multiline output. The parameter `$indentation` specifies the characters used for indentation (default is tab).
 
diff --git a/neon/en/format.texy b/neon/en/format.texy
index ec4a3d6a7d..45c9289b34 100644
--- a/neon/en/format.texy
+++ b/neon/en/format.texy
@@ -119,11 +119,11 @@ Values of mappings and sequences may be other mappings and sequences. The level
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 In PHP, the same structure would be written as:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+In the previous case, we wrote a mapping whose elements were sequences. Now, let's try it the other way around and create a sequence containing mappings:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+It's not necessary for the bullet points to be on separate lines; they can also be placed in this manner:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+It's up to you whether you align the keys in a column using spaces or a tab.
+
 Because PHP uses the same structure for mapping and sequences, that is, arrays, both can be merged. The indentation is the same this time:
 
 ```neon
diff --git a/neon/es/@home.texy b/neon/es/@home.texy
index be13729413..4722e32baa 100644
--- a/neon/es/@home.texy
+++ b/neon/es/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Devuelve `$value` convertido a NEON. Como parámetro `$blockMode` puede pasar true, que creará una salida multilínea. El parámetro `$indentation` especifica los caracteres utilizados para la sangría (por defecto es tabulador).
 
diff --git a/neon/es/format.texy b/neon/es/format.texy
index 3ba10dd7f1..cdc695c92a 100644
--- a/neon/es/format.texy
+++ b/neon/es/format.texy
@@ -119,11 +119,11 @@ Los valores de las correspondencias y secuencias pueden ser otras correspondenci
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 En PHP, la misma estructura se escribiría como:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+En el caso anterior, escribimos un mapeo cuyos elementos eran secuencias. Ahora, intentémoslo al revés y creemos una secuencia que contenga mapeos:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+No es necesario que las viñetas estén en líneas separadas; también pueden colocarse así:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Depende de ti si alineas las viñetas en una columna utilizando espacios o un tabulador.
+
 Debido a que PHP utiliza la misma estructura para mapeo y secuencias, es decir, arrays, ambos pueden ser fusionados. La indentación es la misma esta vez:
 
 ```neon
diff --git a/neon/fr/@home.texy b/neon/fr/@home.texy
index 8813535de9..c14170ad07 100644
--- a/neon/fr/@home.texy
+++ b/neon/fr/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Renvoie `$value` converti en NEON. Comme paramètre `$blockMode` vous pouvez passer true, ce qui créera une sortie multiligne. Le paramètre `$indentation` spécifie les caractères utilisés pour l'indentation (la tabulation par défaut).
 
diff --git a/neon/fr/format.texy b/neon/fr/format.texy
index 4d1d55c829..c6ffac6484 100644
--- a/neon/fr/format.texy
+++ b/neon/fr/format.texy
@@ -119,11 +119,11 @@ Les valeurs des mappings et des séquences peuvent être d'autres mappings et s
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 En PHP, la même structure s'écrirait comme suit :
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+Dans le cas précédent, nous avons écrit un mapping dont les éléments étaient des séquences. Essayons maintenant l'inverse et créons une séquence contenant des mappings :
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Il n'est pas nécessaire que les puces soient sur des lignes séparées ; elles peuvent également être placées de cette manière :
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Il vous appartient d'aligner les clés dans une colonne en utilisant des espaces ou une tabulation.
+
 Parce que PHP utilise la même structure pour le mapping et les séquences, c'est-à-dire les tableaux, les deux peuvent être fusionnés. L'indentation est la même cette fois :
 
 ```neon
diff --git a/neon/hu/@home.texy b/neon/hu/@home.texy
index de60f22bed..762dbd923a 100644
--- a/neon/hu/@home.texy
+++ b/neon/hu/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Visszaadja a `$value` fájlt NEON-ra konvertálva. A `$blockMode` paraméterként átadható a true, ami többsoros kimenetet hoz létre. A `$indentation` paraméter megadja a behúzáshoz használt karaktereket (alapértelmezett a tabulátor).
 
diff --git a/neon/hu/format.texy b/neon/hu/format.texy
index ee01eb5fea..a220212f7d 100644
--- a/neon/hu/format.texy
+++ b/neon/hu/format.texy
@@ -119,11 +119,11 @@ A leképezések és szekvenciák értékei lehetnek más leképezések és szekv
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 PHP-ben ugyanezt a struktúrát így írnánk le:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+Az előző esetben egy olyan leképezést írtunk, amelynek elemei szekvenciák voltak. Most próbáljuk meg fordítva, és hozzunk létre egy leképezéseket tartalmazó szekvenciát:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Nem szükséges, hogy a felsoroláspontok külön sorokban legyenek; így is elhelyezhetjük őket:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Öntől függ, hogy a kulcsokat szóközökkel vagy tabulátorral igazítja-e egy oszlopba.
+
 Mivel a PHP ugyanazt a struktúrát használja a leképezéshez és a szekvenciákhoz, azaz a tömböket, mindkettő összevonható. A behúzás ezúttal is ugyanaz:
 
 ```neon
diff --git a/neon/it/@home.texy b/neon/it/@home.texy
index cca2db9ae2..780064150c 100644
--- a/neon/it/@home.texy
+++ b/neon/it/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Restituisce `$value` convertito in NEON. Come parametro `$blockMode` si può passare true, che creerà un output multilinea. Il parametro `$indentation` specifica i caratteri utilizzati per l'indentazione (l'impostazione predefinita è tab).
 
diff --git a/neon/it/format.texy b/neon/it/format.texy
index 20b2520538..7ccb465f5d 100644
--- a/neon/it/format.texy
+++ b/neon/it/format.texy
@@ -119,11 +119,11 @@ I valori delle mappature e delle sequenze possono essere altre mappature e seque
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 In PHP, la stessa struttura sarebbe scritta come:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+Nel caso precedente, abbiamo scritto una mappatura i cui elementi erano sequenze. Proviamo ora a fare il contrario e a creare una sequenza contenente delle mappature:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Non è necessario che i punti elenco siano su righe separate; possono anche essere disposti in questo modo:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Sta a voi decidere se allineare i tasti in una colonna usando spazi o tabulazioni.
+
 Poiché PHP utilizza la stessa struttura per le mappature e le sequenze, cioè gli array, entrambi possono essere uniti. L'indentazione è la stessa questa volta:
 
 ```neon
diff --git a/neon/pl/@home.texy b/neon/pl/@home.texy
index cb6acdb3fb..1317df6e5a 100644
--- a/neon/pl/@home.texy
+++ b/neon/pl/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <cesta>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Zwraca `$value` przekonwertowany na NEON. Możesz przekazać true jako parametr `$blockMode`, aby utworzyć wyjście wieloliniowe. Parametr `$indentation` określa znaki używane do wcięć (domyślnie jest to tabulator).
 
diff --git a/neon/pl/format.texy b/neon/pl/format.texy
index dbb95707bd..1a0f8173b6 100644
--- a/neon/pl/format.texy
+++ b/neon/pl/format.texy
@@ -119,11 +119,11 @@ Wartości mapowania i sekwencji mogą być innymi mapowaniami i sekwencjami. Du
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 W PHP ta sama struktura zostałaby zapisana jako:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+W poprzednim przypadku napisaliśmy mapowanie, którego elementami były sekwencje. Teraz spróbujmy zrobić to na odwrót i stworzyć sekwencję zawierającą mapowania:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Nie jest konieczne, aby wypunktowania znajdowały się w osobnych wierszach; można je również umieścić w ten sposób:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Od Ciebie zależy, czy wyrównasz klawisze w kolumnie za pomocą spacji czy tabulatora.
+
 Ponieważ PHP używa tej samej struktury dla mapowania i sekwencji, czyli tablic, można je połączyć. Tym razem wcięcie jest takie samo:
 
 ```neon
diff --git a/neon/pt/@home.texy b/neon/pt/@home.texy
index 5b2111ba20..df3a57098b 100644
--- a/neon/pt/@home.texy
+++ b/neon/pt/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Retorna `$value` convertido para NEON. Como o parâmetro `$blockMode` você pode passar verdadeiro, o que criará uma saída multilinha. O parâmetro `$indentation` especifica os caracteres usados para indentação (o padrão é tabulação).
 
diff --git a/neon/pt/format.texy b/neon/pt/format.texy
index 62568cf71f..38a5cd832b 100644
--- a/neon/pt/format.texy
+++ b/neon/pt/format.texy
@@ -119,11 +119,11 @@ Os valores de mapeamentos e seqüências podem ser outros mapeamentos e seqüên
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 Em PHP, a mesma estrutura seria escrita como:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+No caso anterior, escrevemos um mapeamento cujos elementos eram sequências. Agora, vamos tentar o contrário e criar uma sequência contendo mapeamentos:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Não é necessário que os marcadores estejam em linhas separadas; eles também podem ser colocados dessa maneira:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Fica a seu critério alinhar as chaves em uma coluna usando espaços ou tabulação.
+
 Porque PHP usa a mesma estrutura para mapeamento e seqüências, ou seja, arrays, ambos podem ser fundidos. A indentação é a mesma desta vez:
 
 ```neon
diff --git a/neon/ro/@home.texy b/neon/ro/@home.texy
index adc84a2078..b37c1f9c08 100644
--- a/neon/ro/@home.texy
+++ b/neon/ro/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Returnează `$value` convertit în NEON. Ca parametru `$blockMode` puteți trece true, care va crea o ieșire multiliniară. Parametrul `$indentation` specifică caracterele utilizate pentru indentare (valoarea implicită este tab).
 
diff --git a/neon/ro/format.texy b/neon/ro/format.texy
index b04a4462a6..1bfdfea3d4 100644
--- a/neon/ro/format.texy
+++ b/neon/ro/format.texy
@@ -119,11 +119,11 @@ Valorile maparelor și secvențelor pot fi alte mape și secvențe. Nivelul de i
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 În PHP, aceeași structură ar fi scrisă astfel::
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+În cazul anterior, am scris o hartă ale cărei elemente erau secvențe. Acum, să încercăm invers și să creăm o secvență care să conțină mapare:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Nu este necesar ca punctele să fie pe linii separate; ele pot fi plasate și în acest mod:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Depinde de dvs. dacă aliniați cheile într-o coloană folosind spații sau o tabulație.
+
 Deoarece PHP utilizează aceeași structură pentru cartografiere și secvențe, adică array-uri, ambele pot fi îmbinate. Indentarea este aceeași de această dată:
 
 ```neon
diff --git a/neon/ru/@home.texy b/neon/ru/@home.texy
index afc65ca75c..8ee9d2f880 100644
--- a/neon/ru/@home.texy
+++ b/neon/ru/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Возвращает `$value`, преобразованный в NEON. В качестве параметра `$blockMode` можно передать true, что создаст многострочный вывод. Параметр `$indentation` задает символы, используемые для отступов (по умолчанию это tab).
 
diff --git a/neon/ru/format.texy b/neon/ru/format.texy
index fd87a2c992..82e51b2c1d 100644
--- a/neon/ru/format.texy
+++ b/neon/ru/format.texy
@@ -119,11 +119,11 @@ country: USA
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 В PHP та же структура была бы записана как:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+В предыдущем случае мы написали отображение, элементами которого были последовательности. Теперь попробуем сделать все наоборот и создать последовательность, содержащую отображения:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Не обязательно, чтобы пункты были расположены на отдельных строках, их можно расположить и таким образом:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Выравнивать ли ключи в колонке с помощью пробелов или табуляции - решать вам.
+
 Поскольку PHP использует одну и ту же структуру для отображения и последовательностей, то есть массивы, оба варианта могут быть объединены. На этот раз отступы одинаковы:
 
 ```neon
diff --git a/neon/sl/@home.texy b/neon/sl/@home.texy
index 125fe72f68..45a994a238 100644
--- a/neon/sl/@home.texy
+++ b/neon/sl/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Vrne `$value`, pretvorjeno v NEON. Kot parameter `$blockMode` lahko posredujete true, kar bo ustvarilo večvrstični izpis. Parameter `$indentation` določa znake, ki se uporabljajo za odtiskovanje (privzeto je tabulator).
 
diff --git a/neon/sl/format.texy b/neon/sl/format.texy
index 554940cd92..0ed6f8f8c4 100644
--- a/neon/sl/format.texy
+++ b/neon/sl/format.texy
@@ -119,11 +119,11 @@ Vrednosti preslikav in zaporedij so lahko druge preslikave in zaporedja. Pomembn
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 V jeziku PHP bi bila ista struktura zapisana kot:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+V prejšnjem primeru smo zapisali preslikavo, katere elementi so bila zaporedja. Zdaj poskusimo obratno in ustvarimo zaporedje, ki vsebuje preslikave:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Ni nujno, da so točke na ločenih vrsticah; lahko jih postavimo tudi na ta način:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Od vas je odvisno, ali jih boste v stolpcu poravnali s presledki ali tabulatorjem.
+
 Ker PHP uporablja enako strukturo za preslikave in zaporedja, tj. polja, je mogoče oboje združiti. Vstavljanje je tokrat enako:
 
 ```neon
diff --git a/neon/tr/@home.texy b/neon/tr/@home.texy
index f2bf1cb356..2b762e7fa8 100644
--- a/neon/tr/@home.texy
+++ b/neon/tr/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 NEON'a dönüştürülmüş `$value` döndürür. Parametre olarak `$blockMode` çok satırlı çıktı oluşturacak true değerini geçebilirsiniz. `$indentation` parametresi girinti için kullanılan karakterleri belirtir (varsayılan tab'dır).
 
diff --git a/neon/tr/format.texy b/neon/tr/format.texy
index 838533b0d5..d8a808509d 100644
--- a/neon/tr/format.texy
+++ b/neon/tr/format.texy
@@ -119,11 +119,11 @@ Eşlemelerin ve dizilerin değerleri başka eşlemeler ve diziler olabilir. Giri
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 PHP'de aynı yapı şu şekilde yazılacaktır:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+Önceki durumda, elemanları diziler olan bir eşleme yazmıştık. Şimdi de tam tersini deneyelim ve eşlemeleri içeren bir dizi oluşturalım:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Madde işaretlerinin ayrı satırlarda olması gerekli değildir; bu şekilde de yerleştirilebilirler:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Bir sütundaki tuşları boşluk veya sekme kullanarak hizalayıp hizalamayacağınız size bağlıdır.
+
 PHP eşleme ve diziler için aynı yapıyı, yani dizileri kullandığından, her ikisi de birleştirilebilir. Girintileme bu sefer aynıdır:
 
 ```neon
diff --git a/neon/uk/@home.texy b/neon/uk/@home.texy
index 26b3e05d9a..26178bdf6a 100644
--- a/neon/uk/@home.texy
+++ b/neon/uk/@home.texy
@@ -32,8 +32,8 @@ vendor/bin/neon-lint <path>
 ```
 
 
-encode(mixed $value, bool $blockMode=false): string .[method]
--------------------------------------------------------------
+encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method]
+---------------------------------------------------------------------------------------
 
 Повертає `$value`, перетворений у NEON. Як параметр `$blockMode` можна передати true, що створить багаторядковий вивід. Параметр `$indentation` задає символи, що використовуються для відступів (за замовчуванням це tab).
 
diff --git a/neon/uk/format.texy b/neon/uk/format.texy
index 000d5c051a..046bd099a2 100644
--- a/neon/uk/format.texy
+++ b/neon/uk/format.texy
@@ -119,11 +119,11 @@ country: USA
 
 ```neon
 pets:
- - Cat
- - Dog
+   - Cat
+   - Dog
 cars:
- - Volvo
- - Skoda
+   - Volvo
+   - Skoda
 ```
 
 У PHP та сама структура була б записана як:
@@ -161,6 +161,28 @@ item: [
 ]
 ```
 
+У попередньому випадку ми написали відображення, елементами якого були послідовності. Тепер давайте спробуємо зробити навпаки і створимо послідовність, що містить відображення:
+
+```neon
+-
+	name: John
+	age: 35
+-
+	name: Peter
+	age: 28
+```
+
+Не обов'язково, щоб маркери були на окремих рядках, їх можна розмістити і таким чином:
+
+```neon
+- name: John
+  age: 35
+- name: Peter
+  age: 28
+```
+
+Ви самі вирішуєте, як вирівнювати ключі в стовпчику - за допомогою пробілів чи табуляції.
+
 Оскільки PHP використовує одну й ту саму структуру для відображення і послідовностей, тобто масиви, обидва варіанти можуть бути об'єднані. Цього разу відступи однакові:
 
 ```neon
diff --git a/nette/bg/@home.texy b/nette/bg/@home.texy
index 186b0c1b59..feabd53f9c 100644
--- a/nette/bg/@home.texy
+++ b/nette/bg/@home.texy
@@ -84,11 +84,11 @@
 - [помощни средства:JSON |utils:JSON]
 - [NEON |neon:]
 - [Събиране на пароли |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Типове PHP |utils:type]
 - [Strings |utils:Strings]
 - [Валидатори |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...други |utils:]
 </div>
diff --git a/nette/bg/installation.texy b/nette/bg/installation.texy
index a669e5b3ab..8ca67baa2e 100644
--- a/nette/bg/installation.texy
+++ b/nette/bg/installation.texy
@@ -20,7 +20,7 @@ Nette предлага колекция от полезни и усъвърше
 composer require nette/utils
 ```
 
-Предпочитате ли графичен интерфейс? Разгледайте [ръководството за |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] инсталиране на пакети в средата PhpStrom.
+Предпочитате ли графичен интерфейс? Разгледайте [ръководството за |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] инсталиране на пакети в средата PhpStorm.
 
 
 Как да започнете нов проект с Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/bg/introduction-to-object-oriented-programming.texy b/nette/bg/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..7d6e3af2ab
--- /dev/null
+++ b/nette/bg/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Въведение в обектно-ориентираното програмиране
+**********************************************
+
+.[perex]
+Терминът "ООП" означава обектно-ориентирано програмиране, което е начин за организиране и структуриране на кода. ООП ни позволява да разглеждаме една програма като колекция от обекти, които комуникират помежду си, а не като последователност от команди и функции.
+
+В ООП "обект" е единица, която съдържа данни и функции, които работят с тези данни. Обектите се създават въз основа на "класове", които могат да се разбират като проекти или шаблони за обекти. След като разполагаме с клас, можем да създадем негов "екземпляр", който е конкретен обект, създаден от този клас.
+
+Нека разгледаме как можем да създадем прост клас в PHP. Когато дефинираме клас, използваме ключовата дума "class", последвана от името на класа, и след това къдрави скоби, които ограждат функциите на класа (наречени "методи") и променливите на класа (наречени "свойства" или "атрибути"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+В този пример създадохме клас на име `Car` с една функция (или "метод"), наречена `honk`.
+
+Всеки клас трябва да реши само една основна задача. Ако един клас решава твърде много задачи, може да е подходящо да го разделите на по-малки, специализирани класове.
+
+Обикновено класовете се съхраняват в отделни файлове, за да се запази организацията на кода и да се улесни навигацията в него. Името на файла трябва да съвпада с името на класа, така че за класа `Car` името на файла ще бъде `Car.php`.
+
+При именуването на класовете е добре да се следва конвенцията "PascalCase", което означава, че всяка дума в името започва с главна буква и няма подчертавания или други разделители. Методите и свойствата следват конвенцията "camelCase", което означава, че започват с малка буква.
+
+Някои методи в PHP имат специални роли и се предхождат от `__` (две подчертавания). Един от най-важните специални методи е "конструкторът", обозначен като `__construct`. Конструкторът е метод, който се извиква автоматично при създаването на нова инстанция на даден клас.
+
+Често използваме конструктора, за да зададем първоначалното състояние на даден обект. Например, когато създавате обект, представляващ човек, може да използвате конструктора, за да зададете неговата възраст, име или други атрибути.
+
+Нека видим как да използваме конструктор в PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+В този пример класът `Person` има свойство (променлива) `$age` и конструктор, който задава това свойство. След това методът `howOldAreYou()` осигурява достъп до възрастта на лицето.
+
+Псевдопроменливата `$this` се използва вътре в класа за достъп до свойствата и методите на обекта.
+
+Ключовата дума `new` се използва за създаване на нов екземпляр на даден клас. В горния пример създадохме ново лице на възраст 25 години.
+
+Можете също така да зададете стойности по подразбиране за параметрите на конструктора, ако те не са зададени при създаването на обект. Например:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+В този пример, ако не посочите възраст при създаването на обект `Person`, ще бъде използвана стойността по подразбиране 20.
+
+Хубавото е, че дефиницията на свойството с инициализацията му чрез конструктора може да бъде съкратена и опростена по следния начин:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+За пълнота, в допълнение към конструкторите обектите могат да имат деструктори (метод `__destruct`), които се извикват преди обектът да бъде освободен от паметта.
+
+
+Пространства от имена .[#toc-namespaces]
+----------------------------------------
+
+Пространствата от имена ни позволяват да организираме и групираме свързани класове, функции и константи, като избягваме конфликти в наименованията. Можете да си ги представите като папки на компютъра, където всяка папка съдържа файлове, свързани с конкретен проект или тема.
+
+Пространствата от имена са особено полезни в по-големи проекти или при използване на библиотеки на трети страни, където могат да възникнат конфликти в наименованията на класовете.
+
+Представете си, че в проекта ви има клас с име `Car` и искате да го поставите в пространство от имена, наречено `Transport`. Ще го направите по следния начин:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Ако искате да използвате класа `Car` в друг файл, трябва да посочите от кое пространство от имена произхожда класът:
+
+```php
+$car = new Transport\Car;
+```
+
+За улеснение можете да посочите в началото на файла кой клас от определено пространство от имена искате да използвате, което ви позволява да създавате екземпляри, без да посочвате пълния път:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Наследяване .[#toc-inheritance]
+-------------------------------
+
+Наследяването е инструмент на обектно-ориентираното програмиране, който позволява създаването на нови класове на базата на съществуващи, като се наследяват техните свойства и методи и се разширяват или предефинират при необходимост. Наследяването осигурява повторна използваемост на кода и йерархичност на класовете.
+
+Казано по-просто, ако имаме един клас и искаме да създадем друг, производен от него, но с някои модификации, можем да "наследим" новия клас от оригиналния.
+
+В PHP наследяването се реализира с помощта на ключовата дума `extends`.
+
+Нашият клас `Person` съхранява информация за възрастта. Можем да имаме друг клас, `Student`, който разширява `Person` и добавя информация за областта на обучение.
+
+Нека разгледаме един пример:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Как работи този код?
+
+- Използвахме ключовата дума `extends`, за да разширим класа `Person`, което означава, че класът `Student` наследява всички методи и свойства от `Person`.
+
+- Ключовата дума `parent::` ни позволява да извикваме методи от родителския клас. В този случай извикахме конструктора от класа `Person`, преди да добавим наша собствена функционалност към класа `Student`. И по същия начин - метода на `printInformation()` класа-родител, преди да изведем информацията за учениците.
+
+Наследяването е предназначено за ситуации, в които между класовете има връзка "е а". Например, клас `Student` е клас `Person`. Котката е животно. То ни позволява в случаите, когато в кода очакваме един обект (например "Човек"), да използваме вместо него производен обект (например "Ученик").
+
+От съществено значение е да осъзнаем, че основната цел на наследяването **не е** да предотврати дублирането на кода. Напротив, неправилното използване на наследяването може да доведе до сложен и труден за поддържане код. Ако между класовете няма връзка "е а", трябва да помислим за композиция вместо за наследяване.
+
+Обърнете внимание, че методите `printInformation()` в класовете `Person` и `Student` извеждат малко по-различна информация. Можем да добавим и други класове (например `Employee`), които ще предоставят други реализации на този метод. Възможността обекти от различни класове да реагират на един и същ метод по различни начини се нарича полиморфизъм:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Композиция .[#toc-composition]
+------------------------------
+
+Композицията е техника, при която вместо да наследяваме свойства и методи от друг клас, просто използваме негова инстанция в нашия клас. Това ни позволява да комбинираме функционалностите и свойствата на няколко класа, без да създаваме сложни структури на наследяване.
+
+Например, имаме клас `Engine` и клас `Car`. Вместо да кажем "Колата е двигател", казваме "Колата има двигател", което е типична композиционна връзка.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Тук `Car` не притежава всички свойства и методи на `Engine`, но има достъп до тях чрез свойството `$engine`.
+
+Предимството на композицията е по-голямата гъвкавост на дизайна и по-добрата адаптивност към бъдещи промени.
+
+
+Видимост .[#toc-visibility]
+---------------------------
+
+В PHP можете да дефинирате "видимост" за свойствата, методите и константите на класа. Видимостта определя къде можете да получите достъп до тези елементи.
+
+1. **Публично:** Ако даден елемент е отбелязан като `public`, това означава, че имате достъп до него отвсякъде, дори извън класа.
+
+2. **Защитен:** Елемент, маркиран като `protected`, е достъпен само в рамките на класа и всички негови наследници (класове, които наследяват от него).
+
+3. **Приватно:** Ако даден елемент е обозначен като `private`, можете да имате достъп до него само в рамките на класа, в който е дефиниран.
+
+Ако не посочите видимост, PHP автоматично ще я зададе на `public`.
+
+Нека разгледаме примерен код:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Продължаваме с наследяването на класове:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+В този случай методът `printProperties()` в `ChildClass` има достъп до публичните и защитените свойства, но няма достъп до частните свойства на родителския клас.
+
+Данните и методите трябва да са възможно най-скрити и достъпни само чрез определен интерфейс. Това ви позволява да променяте вътрешната имплементация на класа, без да засягате останалата част от кода.
+
+
+Финална ключова дума .[#toc-final-keyword]
+------------------------------------------
+
+В PHP можем да използваме ключовата дума `final`, ако искаме да предотвратим наследяването или пренаписването на даден клас, метод или константа. Когато даден клас е маркиран като `final`, той не може да бъде разширяван. Когато даден метод е маркиран като `final`, той не може да бъде презаписван в подклас.
+
+Знанието, че даден клас или метод вече няма да бъде променян, ни позволява да правим промени по-лесно, без да се притесняваме за потенциални конфликти. Например можем да добавим нов метод, без да се страхуваме, че някой потомък вече има метод със същото име, което ще доведе до колизия. Или пък можем да променим параметрите на метод, отново без риск да предизвикаме несъответствие с надграден метод в наследник.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+В този пример опитът за наследяване от крайния клас `FinalClass` ще доведе до грешка.
+
+
+Статични свойства и методи .[#toc-static-properties-and-methods]
+----------------------------------------------------------------
+
+Когато говорим за "статични" елементи на даден клас в PHP, имаме предвид методи и свойства, които принадлежат на самия клас, а не на конкретна инстанция на класа. Това означава, че не е необходимо да създавате инстанция на класа, за да имате достъп до тях. Вместо това ги извиквате или получавате достъп до тях директно чрез името на класа.
+
+Имайте предвид, че тъй като статичните елементи принадлежат на класа, а не на неговите инстанции, не можете да използвате псевдопроменливата `$this` вътре в статичните методи.
+
+Използването на статични свойства води до [затрупан код, пълен с капани |dependency-injection:global-state], затова никога не трябва да ги използвате и тук няма да показваме пример. От друга страна, статичните методи са полезни. Ето един пример:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+В този пример създадохме клас `Calculator` с два статични метода. Можем да извикаме тези методи директно, без да създаваме инстанция на класа, като използваме оператора `::`. Статичните методи са особено полезни за операции, които не зависят от състоянието на конкретна инстанция на класа.
+
+
+Константи на класа .[#toc-class-constants]
+------------------------------------------
+
+В рамките на класовете имаме възможност да дефинираме константи. Константите са стойности, които никога не се променят по време на изпълнението на програмата. За разлика от променливите, стойността на една константа остава непроменена.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+В този пример имаме клас `Car` с константата `NumberOfWheels`. Когато получаваме достъп до константата вътре в класа, можем да използваме ключовата дума `self` вместо името на класа.
+
+
+Интерфейси на обекти .[#toc-object-interfaces]
+----------------------------------------------
+
+Интерфейсите на обектите действат като "договори" за класовете. Ако един клас трябва да имплементира обектния интерфейс, той трябва да съдържа всички методи, които интерфейсът дефинира. Това е чудесен начин да се гарантира, че определени класове се придържат към един и същ "договор" или структура.
+
+В PHP интерфейсите се дефинират с помощта на ключовата дума `interface`. Всички методи, дефинирани в даден интерфейс, са публични (`public`). Когато даден клас имплементира интерфейс, той използва ключовата дума `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Ако даден клас имплементира интерфейс, но не са дефинирани всички очаквани методи, PHP ще хвърли грешка.
+
+Един клас може да имплементира няколко интерфейса едновременно, което е различно от наследяването, при което класът може да наследява само от един клас:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Абстрактни класове .[#toc-abstract-classes]
+-------------------------------------------
+
+Абстрактните класове служат като базови шаблони за други класове, но не можете да създавате техни екземпляри директно. Те съдържат комбинация от пълни методи и абстрактни методи, които нямат определено съдържание. Класовете, които наследяват от абстрактни класове, трябва да предоставят дефиниции за всички абстрактни методи от родителя.
+
+Използваме ключовата дума `abstract`, за да дефинираме абстрактен клас.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+В този пример имаме абстрактен клас с един обикновен и един абстрактен метод. След това имаме клас `Child`, който наследява от `AbstractClass` и предоставя имплементация за абстрактния метод.
+
+По какво се различават интерфейсите и абстрактните класове? Абстрактните класове могат да съдържат както абстрактни, така и конкретни методи, докато интерфейсите само определят кои методи трябва да имплементира класът, но не предоставят имплементация. Един клас може да наследи само един абстрактен клас, но може да имплементира произволен брой интерфейси.
+
+
+Проверка на типа .[#toc-type-checking]
+--------------------------------------
+
+В програмирането е изключително важно да се уверим, че данните, с които работим, са от правилния тип. В PHP разполагаме с инструменти, които осигуряват тази сигурност. Проверката на това дали данните са от правилния тип се нарича "проверка на типа".
+
+Типове, които можем да срещнем в PHP:
+
+1. **Основни типове**: Те включват `int` (цели числа), `float` (числа с плаваща запетая), `bool` (булеви стойности), `string` (низове), `array` (масиви) и `null`.
+2. **Класове**: Когато искаме дадена стойност да бъде инстанция на определен клас.
+3. **Интерфейси**: Определя набор от методи, които даден клас трябва да имплементира. Стойност, която отговаря на даден интерфейс, трябва да има тези методи.
+4. **Смесени типове**: Можем да укажем, че дадена променлива може да има няколко разрешени типа.
+5. **Void**: Този специален тип указва, че функцията или методът не връщат никаква стойност.
+
+Нека да видим как да модифицираме кода, за да включим типовете:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+По този начин гарантираме, че нашият код очаква и работи с данни от правилния тип, което ни помага да предотвратим потенциални грешки.
+
+Някои типове не могат да бъдат записани директно в PHP. В този случай те се изписват в коментара phpDoc, който е стандартният формат за документиране на PHP код, започващ с `/**` и завършващ с `*/`. Той ви позволява да добавяте описания на класове, методи и т.н. А също и да се изброяват сложни типове, като се използват така наречените анотации `@var`, `@param` и `@return`. Тези типове след това се използват от инструментите за статичен анализ на кода, но не се проверяват от самия PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Сравнение и идентичност .[#toc-comparison-and-identity]
+-------------------------------------------------------
+
+В PHP можете да сравнявате обекти по два начина:
+
+1. Сравняване на стойности `==`: Проверява се дали обектите са от един и същи клас и имат еднакви стойности в свойствата си.
+2. Сравнение на идентичността `===`: Проверява се дали става въпрос за една и съща инстанция на обекта.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Операторът на `instanceof` .[#toc-the-instanceof-operator]
+----------------------------------------------------------
+
+Операторът `instanceof` ви позволява да определите дали даден обект е инстанция на определен клас, потомък на този клас или дали реализира определен интерфейс.
+
+Представете си, че имаме клас `Person` и друг клас `Student`, който е потомък на `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+От изводите е видно, че обектът `$student` се счита за инстанция на двата класа `Student` и `Person`.
+
+
+Флуентни интерфейси .[#toc-fluent-interfaces]
+---------------------------------------------
+
+"Флуентен интерфейс" е техника в ООП, която позволява верижно свързване на методи с едно извикване. Това често опростява и изяснява кода.
+
+Ключовият елемент на плавния интерфейс е, че всеки метод във веригата връща референция към текущия обект. Това се постига чрез използване на `return $this;` в края на метода. Този стил на програмиране често се свързва с методите, наречени "setters", които задават стойностите на свойствата на даден обект.
+
+Нека да видим как може да изглежда един плавен интерфейс за изпращане на имейли:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+В този пример методите `setFrom()`, `setRecipient()` и `setMessage()` се използват за задаване на съответните стойности (изпращач, получател, съдържание на съобщението). След задаването на всяка от тези стойности методите връщат текущия обект (`$email`), което ни позволява да верижно да използваме друг метод след него. Накрая извикваме метода `send()`, който всъщност изпраща електронното писмо.
+
+Благодарение на плавните интерфейси можем да пишем код, който е интуитивен и лесно четим.
+
+
+Копиране с `clone` .[#toc-copying-with-clone]
+---------------------------------------------
+
+В PHP можем да създадем копие на даден обект, като използваме оператора `clone`. По този начин получаваме нов екземпляр с идентично съдържание.
+
+Ако при копирането на обект трябва да променим някои от неговите свойства, можем да дефинираме специален метод `__clone()` в класа. Този метод се извиква автоматично, когато обектът се клонира.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+В този пример имаме клас `Sheep` с едно свойство `$name`. Когато клонираме екземпляр на този клас, методът `__clone()` гарантира, че името на клонираната овца ще получи префикс "Clone of".
+
+
+Признаци .[#toc-traits]
+-----------------------
+
+Чертите в PHP са инструмент, който позволява споделянето на методи, свойства и константи между класовете и предотвратява дублирането на код. Можете да си ги представите като механизъм за "копиране и поставяне" (Ctrl-C и Ctrl-V), при който съдържанието на дадена черта се "вмъква" в класовете. Това ви позволява да използвате повторно кода, без да се налага да създавате сложни йерархии от класове.
+
+Нека разгледаме прост пример за използване на черти в PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+В този пример имаме черта, наречена `Honking`, която съдържа един метод `honk()`. След това имаме два класа: `Car` и `Truck`, като и двата използват чертата `Honking`. В резултат на това и двата класа "притежават" метода `honk()` и можем да го извикаме върху обекти и от двата класа.
+
+Характеристиките позволяват лесно и ефективно споделяне на код между класовете. Те не влизат в йерархията на наследяване, т.е. `$car instanceof Honking` ще върне `false`.
+
+
+Изключения
+----------
+
+Изключенията в ООП ни позволяват да се справяме с грешките и неочакваните ситуации в нашия код. Те са обекти, които носят информация за грешка или необичайна ситуация.
+
+В PHP имаме вграден клас `Exception`, който служи за основа на всички изключения. Той има няколко метода, които ни позволяват да получим повече информация за изключението, например съобщение за грешка, файла и реда, където е възникнала грешката, и т.н.
+
+Когато в кода възникне грешка, можем да "хвърлим" изключението, като използваме ключовата дума `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Когато функцията `division()` получи null като втори аргумент, тя хвърля изключение със съобщение за грешка `'Division by zero!'`. За да предотвратим срив на програмата при хвърляне на изключението, го улавяме в блока `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Кодът, който може да хвърли изключение, е обвит в блок `try`. Ако изключението бъде хвърлено, изпълнението на кода се премества в блок `catch`, където можем да обработим изключението (например да напишем съобщение за грешка).
+
+След блоковете `try` и `catch` можем да добавим незадължителен блок `finally`, който се изпълнява винаги, независимо дали изключението е хвърлено или не (дори ако използваме `return`, `break` или `continue` в блока `try` или `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Можем също така да създадем свои собствени класове за изключения (йерархия), които наследяват класа Exception. Като пример, разгледайте едно просто банково приложение, което позволява депозити и тегления:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+За един блок `try` могат да бъдат зададени няколко блока `catch`, ако очаквате различни видове изключения.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+В този пример е важно да се отбележи редът на блоковете `catch`. Тъй като всички изключения се наследяват от `BankingException`, ако имахме този блок първи, всички изключения щяха да бъдат уловени в него, без кодът да достига до следващите блокове `catch`. Затова е важно по-специфичните изключения (т.е. тези, които се наследяват от други) да бъдат по-нагоре в реда на блоковете `catch` от родителските си изключения.
+
+
+Итерации .[#toc-iterations]
+---------------------------
+
+В PHP можете да правите цикли през обекти с помощта на цикъла `foreach`, подобно на цикъла през масив. За да работи това, обектът трябва да реализира специален интерфейс.
+
+Първият вариант е да имплементирате интерфейса `Iterator`, който има методи `current()` за връщане на текущата стойност, `key()` за връщане на ключа, `next()` за преминаване към следващата стойност, `rewind()` за преминаване към началото и `valid()` за проверка дали вече сме в края.
+
+Другият вариант е да реализираме интерфейс `IteratorAggregate`, който има само един метод `getIterator()`. Той или връща заместващ обект, който ще осигури обхождането, или може да бъде генератор, който е специална функция, използваща `yield`, за да връща последователно ключове и стойности:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Най-добри практики .[#toc-best-practices]
+-----------------------------------------
+
+След като вече сте усвоили основните принципи на обектно-ориентираното програмиране, е изключително важно да се съсредоточите върху най-добрите практики в ООП. Те ще ви помогнат да пишете код, който е не само функционален, но и четим, разбираем и лесен за поддържане.
+
+1) **Отделяне на проблемите**: Всеки клас трябва да има ясно определена отговорност и да се занимава само с една основна задача. Ако даден клас върши твърде много неща, може да е подходящо да го разделите на по-малки, специализирани класове.
+2) **Екапсулиране**: Данните и методите трябва да са възможно най-скрити и достъпни само чрез определен интерфейс. Това ви позволява да променяте вътрешната имплементация на даден клас, без да засягате останалата част от кода.
+3) **Вкачване на зависимостта**: Вместо да създавате зависимости директно в класа, трябва да ги "инжектирате" отвън. За по-задълбочено разбиране на този принцип препоръчваме [главите, посветени на "Инжектиране на зависимости" (Dependency Injection) |dependency-injection:introduction].
diff --git a/nette/bg/troubleshooting.texy b/nette/bg/troubleshooting.texy
index 6b42d2660b..b21f1f4d64 100644
--- a/nette/bg/troubleshooting.texy
+++ b/nette/bg/troubleshooting.texy
@@ -18,7 +18,7 @@ Nette не работи, показва бяла страница .[#toc-nette-i
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // вашия IP адрес.
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Tracy ще ви информира защо не може да регистри
 Когато всички страници (с изключение на началната страница) връщат грешка 404, това изглежда като проблем с конфигурацията на сървъра за [красиви URL адреси |#How to Configure a Server for Nice URLs?].
 
 
+Как да деактивирам кеша по време на разработка? .[#toc-how-to-disable-cache-during-development]
+-----------------------------------------------------------------------------------------------
+Nette е умен и не е необходимо да деактивирате кеширането в него. По време на разработката той автоматично актуализира кеша, когато има промяна в шаблона или конфигурацията на DI контейнера. Освен това режимът за разработка се активира чрез автоматично откриване, така че обикновено не е необходимо да конфигурирате нищо [или само IP адреса |application:bootstrap#development-vs-production-mode].
+
+При отстраняване на грешки в маршрутизатора препоръчваме да се деактивира кешът на браузъра, където например може да се съхраняват пренасочвания: отворете Developer Tools (Ctrl+Shift+I или Cmd+Option+I) и в панела Network (Мрежа) поставете отметка в квадратчето за деактивиране на кеша.
+
+
 Грешка `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Тази грешка се появява, ако сте обновили PHP до версия 8.1, но използвате Nette, която не е съвместима с нея. Решението е да се обнови Nette до по-нова версия с помощта на `composer update`. Nette поддържа PHP 8.1 от версия 3.0. Ако използвате по-стара версия (можете да разберете това, като погледнете `composer.json`), [обновете Nette |migrations:en] или останете с PHP 8.0.
@@ -67,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on
 
 За да стартирате приложението в хостинг услуга, трябва да зададете document-root в тази директория в конфигурацията на хостинга. Или ако на хостинга има готова папка за публичната директория с различно име (например `web`, `public_html` и т.н.), просто преименувайте `www/`.
 
-Единственото** решение е да се "отървете" от папката `www/`, като използвате правила във файла `.htaccess` или в маршрутизатора. Ако хостингът ви не позволява да зададете корен на документа в поддиректория (т.е. да създавате директории едно ниво над публичната директория), потърсете друга. В противен случай поемате значителен риск за сигурността. Това е като да живееш в апартамент, в който не можеш да затвориш входната врата и тя винаги е отворена.
+Решението не е** да се предотврати достъпът до всички папки с изключение на `www/` чрез правила във файла `.htaccess` или в маршрутизатора. Ако хостингът ви не позволява задаване на коренната директория на документа в поддиректория (т.е. създаване на директории на ниво над публичната директория), трябва да потърсите друга хостинг услуга. В противен случай бихте се изложили на значителни рискове за сигурността. Това е все едно да живеете в апартамент, в който входната врата не може да се затвори и винаги е широко отворена.
 
 
 Как да настроя сървъра за красиви URL адреси? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/cs/@home.texy b/nette/cs/@home.texy
index ec7373b9d4..9d81baaa96 100644
--- a/nette/cs/@home.texy
+++ b/nette/cs/@home.texy
@@ -84,11 +84,11 @@ Utilities
 - [utils:JSON]
 - [NEON|neon:]
 - [Hashování hesel |security:passwords]
-- [SmartObject |utils:smartobject]
 - [PHP typy |utils:type]
 - [Řetězce |utils:strings]
 - [Validátory |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...další |utils:]
 </div>
diff --git a/nette/cs/installation.texy b/nette/cs/installation.texy
index b2d4b99c94..6f5455879f 100644
--- a/nette/cs/installation.texy
+++ b/nette/cs/installation.texy
@@ -20,7 +20,7 @@ Nette nabízí kolekci užitečných a vyspělých balíčků (knihoven) pro PHP
 composer require nette/utils
 ```
 
-Preferujete grafické rozhraní? Prohlédněte si [návod|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] na instalaci balíčků v prostředí PhpStrom.
+Preferujete grafické rozhraní? Prohlédněte si [návod|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] na instalaci balíčků v prostředí PhpStorm.
 
 
 Jak založit nový projekt s Nette
diff --git a/nette/cs/introduction-to-object-oriented-programming.texy b/nette/cs/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..e7c34e9e30
--- /dev/null
+++ b/nette/cs/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Úvod do objektově orientovaného programování
+********************************************
+
+.[perex]
+Termín "OOP" označuje objektově orientované programování, což je způsob, jak organizovat a strukturovat kód. OOP nám umožňuje vidět program jako soubor objektů, které komunikují mezi sebou, místo sledu příkazů a funkcí.
+
+V OOP je "objekt" jednotka, která obsahuje data a funkce, které s těmito daty pracují. Objekty jsou vytvořeny podle "tříd", které můžeme chápat jako návrhy nebo šablony pro objekty. Když máme třídu, můžeme vytvořit její "instanci", což je konkrétní objekt vytvořený podle této třídy.
+
+Pojďme si ukázat, jak můžeme vytvořit jednoduchou třídu v PHP. Při definování třídy použijeme klíčové slovo "class", následované názvem třídy a pak složenými závorkami, které obklopují funkce (říká se jim "metody") a proměnné třídy (říká se jim "vlastnosti" nebo anglicky "property"):
+
+```php
+class Auto
+{
+	function zatrub()
+	{
+		echo 'Bip bip!';
+	}
+}
+```
+
+V tomto příkladě jsme vytvořili třídu s názvem `Auto` s jednou funkcí (nebo "metodou") nazvanou `zatrub`.
+
+Každá třída by měla řešit pouze jeden hlavní úkol. Pokud třída dělá příliš mnoho věcí, může být vhodné ji rozdělit na menší, specializované třídy.
+
+Třídy obvykle ukládáme do samostatných souborů, aby byl kód organizovaný a snadno se v něm orientovalo. Název souboru by měl odpovídat názvu třídy, takže pro třídu `Auto` by název souboru byl `Auto.php`.
+
+Při pojmenování tříd je dobré držet se konvence "PascalCase", což znamená, že každé slovo v názvu začíná velkým písmenem a nejsou mezi nimi žádné podtržítka nebo jiné oddělovače. Metody a vlastnosti používají konvenci "camelCase", to znamená, že začínají malým písmenem.
+
+Některé metody v PHP mají speciální úlohy a jsou označené předponou `__` (dvě podtržítka). Jednou z nejdůležitějších speciálních metod je "konstruktor", který je označen jako `__construct`. Konstruktor je metoda, která se automaticky zavolá, když vytváříte novou instanci třídy.
+
+Konstruktor často používáme k nastavení počátečního stavu objektu. Například, když vytváříte objekt reprezentující osobu, můžete využit konstruktor k nastavení jejího věku, jména nebo jiných vlastností.
+
+Pojďme si ukázat, jak použít konstruktor v PHP:
+
+```php
+class Osoba
+{
+	private $vek;
+
+	function __construct($vek)
+	{
+		$this->vek = $vek;
+	}
+
+	function kolikJeTiLet()
+	{
+		return $this->vek;
+	}
+}
+
+$osoba = new Osoba(25);
+echo $osoba->kolikJeTiLet(); // Vypíše: 25
+```
+
+V tomto příkladě třída `Osoba` má vlastnost (proměnnou) `$vek` a dále konstruktor, který nastavuje tuto vlastnost. Metoda `kolikJeTiLet()` pak umožňuje přístup k věku osoby.
+
+Pseudoproměnná `$this` se používá uvnitř třídy pro přístup k vlastnostem a metodám objektu.
+
+Klíčové slovo `new` se používá k vytvoření nové instance třídy. Ve výše uvedeném příkladu jsme vytvořili novou osobu s věkem 25.
+
+Můžete také nastavit výchozí hodnoty pro parametry konstruktoru, pokud nejsou při vytváření objektu specifikovány. Například:
+
+```php
+class Osoba
+{
+	private $vek;
+
+	function __construct($vek = 20)
+	{
+		$this->vek = $vek;
+	}
+
+	function kolikJeTiLet()
+	{
+		return $this->vek;
+	}
+}
+
+$osoba = new Osoba;  // pokud nepředáváme žádný argument, lze závorky vynechat
+echo $osoba->kolikJeTiLet(); // Vypíše: 20
+```
+
+V tomto příkladě, pokud nezadáte věk při vytváření objektu `Osoba`, bude použita výchozí hodnota 20.
+
+Příjemné je, že definice vlastnosti s její inicializací přes konstruktor se dá takto zkrátit a zjednodušit:
+
+```php
+class Osoba
+{
+	function __construct(
+		private $vek = 20,
+	) {
+	}
+}
+```
+
+Pro úplnost, kromě konstruktorů mohou mít objekty i destruktory (metoda `__destruct`), které se zavolají před tím, než je objekt uvolněn z paměti.
+
+
+Jmenné prostory
+---------------
+
+Jmenné prostory (neboli "namespaces" v angličtině) nám umožňují organizovat a seskupovat související třídy, funkce a konstanty, a zároveň se vyhýbat konfliktům v názvech. Můžete si je představit jako složky v počítači, kde každá složka obsahuje soubory, které patří k určitému projektu nebo tématu.
+
+Jmenné prostory jsou obzvlášť užitečné ve větších projektech nebo když používáte knihovny od třetích stran, kde by mohly vzniknout konflikty v názvech tříd.
+
+Představte si, že máte třídu s názvem `Auto` ve vašem projektu a chcete ji umístit do jmenného prostoru nazvaného `Doprava`. Uděláte to takto:
+
+```php
+namespace Doprava;
+
+class Auto
+{
+	function zatrub()
+	{
+		echo 'Bip bip!';
+	}
+}
+```
+
+Pokud chcete použít třídu `Auto` v jiném souboru, musíte specifikovat, z jakého jmenného prostoru třída pochází:
+
+```php
+$auto = new Doprava\Auto;
+```
+
+Pro zjednodušení můžete na začátku souboru uvést, kterou třídu z daného jmenného prostoru chcete používat, což umožňuje vytvářet instance bez nutnosti uvádět celou cestu:
+
+```php
+use Doprava\Auto;
+
+$auto = new Auto;
+```
+
+
+Dědičnost
+---------
+
+Dědičnost je nástrojem objektově orientovaného programování, který umožňuje vytvářet nové třídy na základě již existujících tříd, přebírat jejich vlastnosti a metody a rozšiřovat nebo předefinovat je podle potřeby. Dědičnost umožňuje zajistit kódovou znovupoužitelnost a hierarchii tříd.
+
+Zjednodušeně řečeno, pokud máme jednu třídu a chtěli bychom vytvořit další, od ní odvozenou, ale s několika změnami, můžeme novou třídu "zdědit" z původní třídy.
+
+V PHP dědičnost realizujeme pomocí klíčového slova `extends`.
+
+Naše třída `Osoba` uchovává informaci o věku. Můžeme mít další třídu `Student`, která rozšiřuje `Osobu` a přidává informaci o oboru studia.
+
+Podívejme se na příklad:
+
+```php
+class Osoba
+{
+	private $vek;
+
+	function __construct($vek)
+	{
+		$this->vek = $vek;
+	}
+
+	function vypisInformace()
+	{
+		echo "Věk: {$this->vek} let\n";
+	}
+}
+
+class Student extends Osoba
+{
+	private $obor;
+
+	function __construct($vek, $obor)
+	{
+		parent::__construct($vek);
+		$this->obor = $obor;
+	}
+
+	function vypisInformace()
+	{
+		parent::vypisInformace();
+		echo "Obor studia: {$this->obor} \n";
+	}
+}
+
+$student = new Student(20, 'Informatika');
+$student->vypisInformace();
+```
+
+Jak tento kód funguje?
+
+- Použili jsme klíčové slovo `extends` k rozšíření třídy `Osoba`, což znamená, že třída `Student` zdědí všechny metody a vlastnosti z `Osoby`.
+
+- Klíčové slovo `parent::` nám umožňuje volat metody z nadřazené třídy. V tomto případě jsme volali konstruktor z třídy `Osoba` před přidáním vlastní funkcionality do třídy `Student`. A obdobně i metodu `vypisInformace()` předka před vypsáním informací o studentovi.
+
+Dědičnost je určená pro situace, kdy existuje vztah "je" mezi třídami. Například `Student` je `Osoba`. Kočka je zvíře. Dává nám možnost v případech, kdy v kódu očekáváme jeden objekt (např. "Osoba"), použít místo něj objekt zděděný (např. "Student").
+
+Je důležité si uvědomit, že hlavním účelem dědičnosti **není** zabránit duplikaci kódu. Naopak, nesprávné využití dědičnosti může vést k složitému a těžko udržitelnému kódu. Pokud vztah "je" mezi třídami neexistuje, měli bychom místo dědičnosti uvažovat o kompozici.
+
+Všimněte si, že metody `vypisInformace()` ve třídách `Osoba` a `Student` vypisují trochu jiné informace. A můžeme doplnit další třídy (například `Zamestnanec`), které budou poskytovat další implementace této metody. Schopnost objektů různých tříd reagovat na stejnou metodu různými způsoby se nazývá polymorfismus:
+
+```php
+$osoby = [
+	new Osoba(30),
+	new Student(20, 'Informatika'),
+	new Zamestnanec(45, 'Ředitel'),
+];
+
+foreach ($osoby as $osoba) {
+	$osoba->vypisInformace();
+}
+```
+
+
+Kompozice
+---------
+
+Kompozice je technika, kdy místo toho, abychom zdědili vlastnosti a metody jiné třídy, jednoduše využijeme její instanci v naší třídě. Toto nám umožňuje kombinovat funkcionality a vlastnosti více tříd bez nutnosti vytvářet složité dědičné struktury.
+
+Podívejme se na příklad. Máme třídu `Motor` a třídu `Auto`. Místo toho, abychom říkali "Auto je Motor", říkáme "Auto má Motor", což je typický vztah kompozice.
+
+```php
+class Motor
+{
+	function zapni()
+	{
+		echo 'Motor běží.';
+	}
+}
+
+class Auto
+{
+	private $motor;
+
+	function __construct()
+	{
+		$this->motor = new Motor;
+	}
+
+	function start()
+	{
+		$this->motor->zapni();
+		echo 'Auto je připraveno k jízdě!';
+	}
+}
+
+$auto = new Auto;
+$auto->start();
+```
+
+Zde `Auto` nemá všechny vlastnosti a metody `Motoru`, ale má k němu přístup prostřednictvím vlastnosti `$motor`.
+
+Výhodou kompozice je větší flexibilita v designu a lepší možnost úprav v budoucnosti.
+
+
+Viditelnost
+-----------
+
+V PHP můžete definovat "viditelnost" pro vlastnosti, metody a konstanty třídy. Viditelnost určuje, odkud můžete přistupovat k těmto prvkům.
+
+1. **Public:** Pokud je prvek označen jako `public`, znamená to, že k němu můžete přistupovat odkudkoli, i mimo třídu.
+
+2. **Protected:** Prvek s označením `protected` je přístupný pouze v rámci dané třídy a všech jejích potomků (tříd, které dědí od této třídy).
+
+3. **Private:** Pokud je prvek `private`, můžete k němu přistupovat pouze zevnitř třídy, ve které byl definována.
+
+Pokud nespecifikujete viditelnost, PHP ji automaticky nastaví na `public`.
+
+Podívejme se na ukázkový kód:
+
+```php
+class UkazkaViditelnosti
+{
+	public $verejnaVlastnost = 'Veřejná';
+	protected $chranenaVlastnost = 'Chráněná';
+	private $soukromaVlastnost = 'Soukromá';
+
+	public function vypisVlastnosti()
+	{
+		echo $this->verejnaVlastnost;  // Funguje
+		echo $this->chranenaVlastnost; // Funguje
+		echo $this->soukromaVlastnost; // Funguje
+	}
+}
+
+$objekt = new UkazkaViditelnosti;
+$objekt->vypisVlastnosti();
+echo $objekt->verejnaVlastnost;      // Funguje
+// echo $objekt->chranenaVlastnost;  // Vyhodí chybu
+// echo $objekt->soukromaVlastnost;  // Vyhodí chybu
+```
+
+Pokračujeme s děděním třídy:
+
+```php
+class PotomekTridy extends UkazkaViditelnosti
+{
+	public function vypisVlastnosti()
+	{
+		echo $this->verejnaVlastnost;   // Funguje
+		echo $this->chranenaVlastnost;  // Funguje
+		// echo $this->soukromaVlastnost;  // Vyhodí chybu
+	}
+}
+```
+
+V tomto případě metoda `vypisVlastnosti()` v třídě `PotomekTřídy` může přistupovat k veřejným a chráněným vlastnostem, ale nemůže přistupovat k privátním vlastnostem rodičovské třídy.
+
+Data a metody by měly být co nejvíce skryté a přístupné pouze prostřednictvím definovaného rozhraní. To vám umožní měnit interní implementaci třídy bez ovlivnění zbytku kódu.
+
+
+Klíčové slovo `final`
+---------------------
+
+V PHP můžeme použít klíčové slovo `final`, pokud chceme zabránit třídě, metodě nebo konstantě být zděděna nebo přepsána. Když označíme třídu jako `final`, nemůže být rozšířena. Když označíme metodu jako `final`, nemůže být v potomkovské třídě přepsána.
+
+Vědomí, že určitá třída nebo metoda nebude dále upravována, nám umožňuje snáze provádět úpravy, aniž bychom se museli obávat možných konfliktů. Například můžeme přidat novou metodu bez obav, že by některý její potomek už stejně pojmenovanou metodu měl a došlo by ke kolizi. Nebo metodě můžeme pozměnit jejich parametry, neboť opět nehrozí, že způsobíme nesoulad s přepsanou metodou v potomkovi.
+
+```php
+final class FinalniTrida
+{
+}
+
+// Následující kód vyvolá chybu, protože nemůžeme zdědit od finalní třídy.
+class PotomekFinalniTridy extends FinalniTrida
+{
+}
+```
+
+V tomto příkladu pokus o zdědění od finalní třídy `FinalniTrida` vyvolá chybu.
+
+
+Statické vlastnosti a metody
+----------------------------
+
+Když v PHP mluvíme o "statických" prvcích třídy, myslíme tím metody a vlastnosti, které náleží samotné třídě, a ne konkrétní instanci této třídy. To znamená, že nemusíte vytvářet instanci třídy, abyste k nim měli přístup. Místo toho je voláte nebo přistupujete k nim přímo přes název třídy.
+
+Mějte na paměti, že jelikož statické prvky patří k třídě, a ne k jejím instancím, nemůžete uvnitř statických metod používat pseudoproměnnou `$this`.
+
+Používání statických vlastností vede k [nepřehlednému kódu plnému záludností|dependency-injection:global-state], proto byste je neměli nikdy použít a ani tu nebudeme ukazovat příklad použití. Naproti tomu statické metody jsou užitečné. Příklad použití:
+
+```php
+class Kalkulator
+{
+	public static function scitani($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function odecitani($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Použití statické metody bez vytvoření instance třídy
+echo Kalkulator::scitani(5, 3); // Výsledek: 8
+echo Kalkulator::odecitani(5, 3); // Výsledek: 2
+```
+
+V tomto příkladu jsme vytvořili třídu `Kalkulator` s dvěma statickými metodami. Tyto metody můžeme volat přímo bez vytvoření instance třídy pomocí `::` operátoru. Statické metody jsou obzvláště užitečné pro operace, které nezávisí na stavu konkrétní instance třídy.
+
+
+Třídní konstanty
+----------------
+
+V rámci tříd máme možnost definovat konstanty. Konstanty jsou hodnoty, které se nikdy nezmění během běhu programu. Na rozdíl od proměnných, hodnota konstanty zůstává stále stejná.
+
+```php
+class Auto
+{
+	public const PocetKol = 4;
+
+	public function zobrazPocetKol(): int
+	{
+		echo self::PocetKol;
+	}
+}
+
+echo Auto::PocetKol;  // Výstup: 4
+```
+
+V tomto příkladu máme třídu `Auto` s konstantou `PocetKol`. Když chceme přistupovat ke konstantě uvnitř třídy, můžeme použít klíčové slovo `self` místo názvu třídy.
+
+
+Objektová rozhraní
+------------------
+
+Objektová rozhraní fungují jako "smlouvy" pro třídy. Pokud má třída implementovat objektové rozhraní, musí obsahovat všechny metody, které toto rozhraní definuje. Je to skvělý způsob, jak zajistit, že určité třídy dodržují stejnou "smlouvu" nebo strukturu.
+
+V PHP se rozhraní definuje klíčovým slovem `interface`. Všechny metody definované v rozhraní jsou veřejné (`public`). Když třída implementuje rozhraní, používá klíčové slovo `implements`.
+
+```php
+interface Zvire
+{
+	function vydejZvuk();
+}
+
+class Kocka implements Zvire
+{
+	public function vydejZvuk()
+	{
+		echo 'Mňau';
+	}
+}
+
+$kocka = new Kocka;
+$kocka->vydejZvuk();
+```
+
+Pokud třída implementuje rozhraní, ale nejsou v ní definované všechny očekávané metody, PHP vyhodí chybu.
+
+Třída může implementovat více rozhraní najednou, což je rozdíl oproti dědičnosti, kde může třída dědit pouze od jedné třídy:
+
+```php
+interface Hlidac
+{
+	function hlidejDum();
+}
+
+class Pes implements Zvire, Hlidac
+{
+	public function vydejZvuk()
+	{
+		echo 'Haf';
+	}
+
+	public function hlidejDum()
+	{
+		echo 'Pes bedlivě střeží dům';
+	}
+}
+```
+
+
+Abstraktní třídy
+----------------
+
+Abstraktní třídy slouží jako základní šablony pro jiné třídy, ale nemůžete vytvářet jejich instance přímo. Obsahují kombinaci kompletních metod a abstraktních metod, které nemají definovaný obsah. Třídy, které dědí z abstraktních tříd, musí poskytnout definice pro všechny abstraktní metody z předka.
+
+K definování abstraktní třídy používáme klíčové slovo `abstract`.
+
+```php
+abstract class AbstraktniTrida
+{
+	public function obycejnaMetoda()
+	{
+		echo 'Toto je obyčejná metoda';
+	}
+
+	abstract public function abstraktniMetoda();
+}
+
+class Potomek extends AbstraktniTrida
+{
+	public function abstraktniMetoda()
+	{
+		echo 'Toto je implementace abstraktní metody';
+	}
+}
+
+$instance = new Potomek;
+$instance->obycejnaMetoda();
+$instance->abstraktniMetoda();
+```
+
+V tomto příkladu máme abstraktní třídu s jednou obyčejnou a jednou abstraktní metodou. Poté máme třídu `Potomek`, která dědí z `AbstraktniTrida` a poskytuje implementaci pro abstraktní metodu.
+
+Jak se vlastně liší rozhraní a abstraktních tříd? Abstraktní třídy mohou obsahovat jak abstraktní, tak konkrétní metody, zatímco rozhraní pouze definují, jaké metody musí třída implementovat, ale neposkytují žádnou implementaci. Třída může dědit jen od jedné abstraktní třídy, ale může implementovat libovolný počet rozhraní.
+
+
+Typová kontrola
+---------------
+
+V programování je velmi důležité mít jistotu, že data, se kterými pracujeme, jsou správného typu. V PHP máme nástroje, které nám toto zajišťují. Ověřování, zda data mají správný typ, se nazývá "typová kontrola".
+
+Typy, na které můžeme v PHP narazit:
+
+1. **Základní typy**: Zahrnují `int` (celá čísla), `float` (desetinná čísla), `bool` (pravdivostní hodnoty), `string` (řetězce), `array` (pole) a `null`.
+2. **Třídy**: Pokud chceme, aby hodnota byla instancí specifické třídy.
+3. **Rozhraní**: Definuje soubor metod, které třída musí implementovat. Hodnota, která splňuje rozhraní, musí mít tyto metody.
+4. **Smíšené typy**: Můžeme určit, že proměnná může mít více povolených typů.
+5. **Void**: Tento speciální typ označuje, že funkce či metoda nevrací žádnou hodnotu.
+
+Pojďme si ukázat, jak upravit kód, aby zahrnoval typy:
+
+```php
+class Osoba
+{
+	private int $vek;
+
+	public function __construct(int $vek)
+	{
+		$this->vek = $vek;
+	}
+
+	public function vypisVek(): void
+	{
+		echo "Této osobě je {$this->vek} let.";
+	}
+}
+
+/**
+ * Funkce, která přijímá objekt třídy Osoba a vypíše věk osoby.
+ */
+function vypisVekOsoby(Osoba $osoba): void
+{
+	$osoba->vypisVek();
+}
+```
+
+Tímto způsobem jsme zajistili, že náš kód očekává a pracuje s daty správného typu, což nám pomáhá předcházet potenciálním chybám.
+
+Některé typy nelze v PHP přímo zapsat. V takovém případě se uvádí v phpDoc komentáři, což je standardní formát pro dokumentaci PHP kódu začínající `/**` a končící `*/`. Umožňuje přidávat popisy tříd, metod a tak dále. A také uvádět komplexní typy pomocí tzv. anotací `@var`, `@param` a `@return`. Tyto typy pak využívají nástroje pro statickou analýzu kódu, ale samotné PHP je nekontroluje.
+
+```php
+class Seznam
+{
+	/** @var array<Osoba>  zápis říká, že jde o pole objektů Osoba */
+	private array $osoby = [];
+
+	public function pridatOsobu(Osoba $osoba): void
+	{
+		$this->osoby[] = $osoba;
+	}
+}
+```
+
+
+Porovnávání a identita
+----------------------
+
+V PHP můžete porovnávat objekty dvěma způsoby:
+
+1. Porovnání hodnot `==`: Zkontroluje, zda mají objekty jsou stejné třídy a mají stejné hodnoty ve svých vlastnostech.
+2. Identita `===`: Zkontroluje, zda jde o stejnou instanci objektu.
+
+```php
+class Auto
+{
+	public string $znacka;
+
+	public function __construct(string $znacka)
+	{
+		$this->znacka = $znacka;
+	}
+}
+
+$auto1 = new Auto('Skoda');
+$auto2 = new Auto('Skoda');
+$auto3 = $auto1;
+
+var_dump($auto1 == $auto2);   // true, protože mají stejnou hodnotu
+var_dump($auto1 === $auto2);  // false, protože nejsou stejná instance
+var_dump($auto1 === $auto3);  // true, protože $auto3 je stejná instance jako $auto1
+```
+
+
+Operátor `instanceof`
+---------------------
+
+Operátor `instanceof` umožňuje zjistit, zda je daný objekt instancí určité třídy, potomka této třídy, nebo zda implementuje určité rozhraní.
+
+Představme si, že máme třídu `Osoba` a další třídu `Student`, která je potomkem třídy `Osoba`:
+
+```php
+class Osoba
+{
+	private int $vek;
+
+	public function __construct(int $vek)
+	{
+		$this->vek = $vek;
+	}
+}
+
+class Student extends Osoba
+{
+	private string $obor;
+
+	public function __construct(int $vek, string $obor)
+	{
+		parent::__construct($vek);
+		$this->obor = $obor;
+	}
+}
+
+$student = new Student(20, 'Informatika');
+
+// Ověření, zda je $student instancí třídy Student
+var_dump($student instanceof Student);  // Výstup: bool(true)
+
+// Ověření, zda je $student instancí třídy Osoba (protože Student je potomek Osoba)
+var_dump($student instanceof Osoba);     // Výstup: bool(true)
+```
+
+Z výstupů je patrné, že objekt `$student` je současně považován za instanci obou tříd - `Student` i `Osoba`.
+
+
+Fluent Interfaces
+-----------------
+
+"Plynulé rozhraní" (anglicky "Fluent Interface") je technika v OOP, která umožňuje řetězit metody dohromady v jednom volání. Tím se často zjednoduší a zpřehlední kód.
+
+Klíčovým prvkem plynulého rozhraní je, že každá metoda v řetězu vrací odkaz na aktuální objekt. Toho dosáhneme tak, že na konci metody použijeme `return $this;`. Tento styl programování je často spojován s metodami zvanými "setters", které nastavují hodnoty vlastností objektu.
+
+Ukážeme si, jak může vypadat plynulé rozhraní na příkladu odesílání emailů:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+V tomto příkladě metody `setFrom()`, `setRecipient()` a `setMessage()` slouží k nastavení odpovídajících hodnot (odesílatele, příjemce, obsahu zprávy). Po nastavení každé z těchto hodnot nám metody vrací aktuální objekt (`$email`), což nám umožňuje řetězit další metodu za ní. Nakonec voláme metodu `send()`, která email skutečně odesílá.
+
+Díky plynulým rozhraním můžeme psát kód, který je intuitivní a snadno čitelný.
+
+
+Kopírování pomocí `clone`
+-------------------------
+
+V PHP můžeme vytvořit kopii objektu pomocí operátoru `clone`. Tímto způsobem dostaneme novou instanci s totožným obsahem.
+
+Pokud potřebujeme při kopírování objektu upravit některé jeho vlastnosti, můžeme ve třídě definovat speciální metodu `__clone()`. Tato metoda se automaticky zavolá, když je objekt klonován.
+
+```php
+class Ovce
+{
+	public string $jmeno;
+
+	public function __construct(string $jmeno)
+	{
+		$this->jmeno = $jmeno;
+	}
+
+	public function __clone()
+	{
+		$this->jmeno = 'Klon ' . $this->jmeno;
+	}
+}
+
+$original = new Ovce('Dolly');
+echo $original->jmeno . "\n";  // Vypíše: Dolly
+
+$klon = clone $original;
+echo $klon->jmeno . "\n";      // Vypíše: Klon Dolly
+```
+
+V tomto příkladu máme třídu `Ovce` s jednou vlastností `$jmeno`. Když klonujeme instanci této třídy, metoda `__clone()` se postará o to, aby název klonované ovce získal předponu "Klon".
+
+
+Traity
+------
+
+Traity v PHP jsou nástrojem, který umožňuje sdílet metody, vlastnosti a konstanty mezi třídami a zabránit duplicitě kódu. Můžete si je představit jako mechanismus "kopírovat a vložit" (Ctrl-C a Ctrl-V), kdy se obsah trait "vkládá" do tříd. To vám umožní znovupoužívat kód bez nutnosti vytvářet komplikované hierarchie tříd.
+
+Pojďme si ukázat jednoduchý příklad, jak používat traity v PHP:
+
+```php
+trait Troubeni
+{
+	public function zatrub()
+	{
+		echo 'Bip bip!';
+	}
+}
+
+class Auto
+{
+	use Troubeni;
+}
+
+class Nakladak
+{
+	use Troubeni;
+}
+
+$auto = new Auto;
+$auto->zatrub(); // Vypíše 'Bip bip!'
+
+$nakladak = new Nakladak;
+$nakladak->zatrub(); // Také vypíše 'Bip bip!'
+```
+
+V tomto příkladu máme traitu nazvanou `Troubeni`, která obsahuje jednu metodu `zatrub()`. Poté máme dvě třídy: `Auto` a `Nakladak`, které obě používají traitu `Troubeni`. Díky tomu obě třídy "mají" metodu `zatrub()`, a můžeme ji volat na objektech obou tříd.
+
+Traity vám umožní snadno a efektivně sdílet kód mezi třídami. Přitom nevstupují do dědičné hierarchie, tj. `$auto instanceof Troubeni` vrátí `false`.
+
+
+Výjimky
+-------
+
+Výjimky v OOP nám umožňují elegantně zpracovávat chyby a neočekávané situace v našem kódu. Jsou to objekty, které nesou informace o chybě nebo neobvyklé situaci.
+
+V PHP máme vestavěnou třídu `Exception`, která slouží jako základ pro všechny výjimky. Ta má několik metod, které nám umožňují získat více informací o výjimce, jako je zpráva o chybě, soubor a řádek, kde k chybě došlo, atd.
+
+Když v kódu nastane chyba, můžeme "vyhodit" výjimku pomocí klíčového slova `throw`.
+
+```php
+function deleni(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Dělení nulou!');
+	}
+	return $a / $b;
+}
+```
+
+Když funkce `deleni()` dostane jako druhý argument nulu, vyhodí výjimku s chybovou zprávou `'Dělení nulou!'`. Abychom zabránili pádu programu při vyhození výjimky, zachytíme ji v bloku `try/catch`:
+
+```php
+try {
+	echo deleni(10, 0);
+} catch (Exception $e) {
+	echo 'Výjimka zachycena: '. $e->getMessage();
+}
+```
+
+Kód, který může vyhodit výjimku, je zabalen do bloku `try`. Pokud je výjimka vyhozena, provádění kódu se přesune do bloku `catch`, kde můžeme výjimku zpracovat (např. vypsat chybovou zprávu).
+
+Po blocích `try` a `catch` můžeme přidat nepovinný blok `finally`, který se provede vždy, ať už byla výjimka vyhozena nebo ne (dokonce i v případě, že v bloku `try` nebo `catch` použijeme příkaz `return`, `break` nebo `continue`):
+
+```php
+try {
+	echo deleni(10, 0);
+} catch (Exception $e) {
+	echo 'Výjimka zachycena: '. $e->getMessage();
+} finally {
+	// Kód, který se provede vždy, ať už byla výjimka vyhozena nebo ne
+}
+```
+
+Můžeme také vytvořit vlastní třídy (hierarchii) výjimek, které dědí od třídy Exception. Jako příklad si představme jednoduchou bankovní aplikaci, která umožňuje provádět vklady a výběry:
+
+```php
+class BankovniVyjimka extends Exception {}
+class NedostatekProstredkuVyjimka extends BankovniVyjimka {}
+class PrekroceniLimituVyjimka extends BankovniVyjimka {}
+
+class BankovniUcet
+{
+	private int $zustatek = 0;
+	private int $denniLimit = 1000;
+
+	public function vlozit(int $castka): int
+	{
+		$this->zustatek += $castka;
+		return $this->zustatek;
+	}
+
+	public function vybrat(int $castka): int
+	{
+		if ($castka > $this->zustatek) {
+			throw new NedostatekProstredkuVyjimka('Na účtu není dostatek prostředků.');
+		}
+
+		if ($castka > $this->denniLimit) {
+			throw new PrekroceniLimituVyjimka('Byl překročen denní limit pro výběry.');
+		}
+
+		$this->zustatek -= $castka;
+		return $this->zustatek;
+	}
+}
+```
+
+Pro jeden blok `try` lze uvést více bloků `catch`, pokud očekáváte různé typy výjimek.
+
+```php
+$ucet = new BankovniUcet;
+$ucet->vlozit(500);
+
+try {
+	$ucet->vybrat(1500);
+} catch (PrekroceniLimituVyjimka $e) {
+	echo $e->getMessage();
+} catch (NedostatekProstredkuVyjimka $e) {
+	echo $e->getMessage();
+} catch (BankovniVyjimka $e) {
+	echo 'Vyskytla se chyba při provádění operace.';
+}
+```
+
+V tomto příkladu je důležité si všimnout pořadí bloků `catch`. Protože všechny výjimky dědí od `BankovniVyjimka`, pokud bychom tento blok měli první, zachytily by se v něm všechny výjimky, aniž by se kód dostal k následujícím `catch` blokům. Proto je důležité mít specifičtější výjimky (tj. ty, které dědí od jiných) v bloku `catch` výše v pořadí než jejich rodičovské výjimky.
+
+
+Iterace
+-------
+
+V PHP můžete procházet objekty pomocí `foreach` smyčky, podobně jako procházíte pole. Aby to fungovalo, objekt musí implementovat speciální rozhraní.
+
+První možností je implementovat rozhraní `Iterator`, které má metody `current()` vracející aktuální hodnotu, `key()` vracející klíč, `next()` přesouvající se na další hodnotu, `rewind()` přesouvající se na začátek a `valid()` zjišťující, zda ještě nejsme na konci.
+
+Druhou možností je implementovat rozhraní `IteratorAggregate`, které má jen jednu metodu `getIterator()`. Ta buď vrací zástupný objekt, který bude zajišťovat procházení, nebo může představovat generátor, což je speciální funkce, ve které se používá `yield` pro postupné vracení klíčů a hodnot:
+
+```php
+class Osoba
+{
+	public function __construct(
+		public int $vek,
+	) {
+	}
+}
+
+class Seznam implements IteratorAggregate
+{
+	private array $osoby = [];
+
+	public function pridatOsobu(Osoba $osoba): void
+	{
+		$this->osoby[] = $osoba;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->osoby as $osoba) {
+			yield $osoba;
+		}
+	}
+}
+
+$seznam = new Seznam;
+$seznam->pridatOsobu(new Osoba(30));
+$seznam->pridatOsobu(new Osoba(25));
+
+foreach ($seznam as $osoba) {
+	echo "Věk: {$osoba->vek} let \n";
+}
+```
+
+
+Správné postupy
+---------------
+
+Když máte za sebou základní principy objektově orientovaného programování, je důležité se zaměřit na správné postupy v OOP. Ty vám pomohou psat kód, který je nejen funkční, ale také čitelný, srozumitelný a snadno udržovatelný.
+
+1) **Oddělení zájmů (Separation of Concerns)**: Každá třída by měla mít jasně definovanou odpovědnost a měla by řešit pouze jeden hlavní úkol. Pokud třída dělá příliš mnoho věcí, může být vhodné ji rozdělit na menší, specializované třídy.
+2) **Zapouzdření (Encapsulation)**: Data a metody by měly být co nejvíce skryté a přístupné pouze prostřednictvím definovaného rozhraní. To vám umožní měnit interní implementaci třídy bez ovlivnění zbytku kódu.
+3) **Předávání závislostí (Dependency Injection)**: Místo toho, abyste vytvořili závislosti přímo v třídě, měli byste je "injektovat" z vnějšku. Pro hlubší porozumění tomuto principu doporučujeme [kapitoly o Dependency Injection|dependency-injection:introduction].
diff --git a/nette/cs/troubleshooting.texy b/nette/cs/troubleshooting.texy
index 6f17c414a7..5e4973f910 100644
--- a/nette/cs/troubleshooting.texy
+++ b/nette/cs/troubleshooting.texy
@@ -18,7 +18,7 @@ Důvod chyby vždy vyčtete v logu v adresáři `log/`. Pokud se ale v chybové
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // vaše IP adresa
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Chyba 404, nefunguje routování
 Když všechny stránky (kromě homepage) vrací chybu 404, vypadá to na problém s konfigurací serveru pro [hezká URL |#Jak nastavit server pro hezká URL?].
 
 
+Jak vypnout cache během vývoje?
+-------------------------------
+Nette je chytré a nemusíte v něm vypínat kešování. Při vývoji totiž automaticky aktualizuje cache při každé změně šablony nebo konfigurace DI kontejneru. Vývojový režimu se navíc zapíná autodetekcí, takže obvykle není potřeba konfigurovat nic, [nebo jen IP adresu |application:bootstrap#vyvojarsky-vs-produkcni-rezim].
+
+Při ladění routeru doporučujeme vypnout cache v prohlížeči, ve které mohou být uložené například přesměrování: otevřete si Developer Tools (Ctrl+Shift+I nebo Cmd+Option+I) a v panelu Network (Síť) zaškrtněne vypnutí cache.
+
+
 Chyba `#[\ReturnTypeWillChange] attribute should be used`
 ---------------------------------------------------------
 Tato chyba se objeví, pokud jste aktualizovali PHP na verzi 8.1, ale používáte Nette, která s ní není kompatibilní. Řešením je tedy aktualizovat Nette na novější verzi pomocí `composer update`. Nette podporuje PHP 8.1 od verze 3.0. Pokud používáte verzi starší (zjistíte pohledem do `composer.json`), [upgradujte Nette |migrations:] nebo zůstaňte u PHP 8.0.
@@ -67,7 +74,7 @@ Adresář `www/` používaný u ukázkových projektů v Nette představuje tzv.
 
 Pro zprovoznění aplikace na hostingu je potřeba, abyste v konfiguraci hostingu nastavili tzv. document-root do tohoto adresáře. Nebo, pokud hosting má pro veřejný adresář předpřipravenou složku s jiným názvem (například `web`, `public_html` atd.), tak `www/` jednoduše přejmenujte.
 
-Řešením **naopak není** „zbavit“ se složky `www/` pomocí pravidel v souboru `.htaccess` nebo v routeru. Pokud by hosting neumožňoval nastavit document-root do podadresáře (tj. vytvářet adresáře o úroveň výš nad veřejným adresářem), poohlédněte se po jiném. Šli byste jinak do značného bezpečnostního rizika. Bylo by to jako bydlet v bytě, kde nejdou zavřít vstupní dveře a jsou stále dokořán.
+Řešením **naopak není** zamezit přístupu do všech složek kromě `www/` pomocí pravidel v souboru `.htaccess` nebo v routeru. Pokud by hosting neumožňoval nastavit document-root do podadresáře (tj. vytvářet adresáře o úroveň výš nad veřejným adresářem), poohlédněte se po jiném. Šli byste jinak do značného bezpečnostního rizika. Bylo by to jako bydlet v bytě, kde nejdou zavřít vstupní dveře a jsou stále dokořán.
 
 
 Jak nastavit server pro hezká URL?
diff --git a/nette/cs/vulnerability-protection.texy b/nette/cs/vulnerability-protection.texy
index fa2d349d49..d5323d3566 100644
--- a/nette/cs/vulnerability-protection.texy
+++ b/nette/cs/vulnerability-protection.texy
@@ -59,12 +59,12 @@ public function handleXyz()
 }
 ```
 
-V PHP 8 můžete použít také atributy:
+V Nette Application 3.2 můžete použít také atributy:
 
 ```php
-use Nette\Application\Attributes\CrossOrigin;
+use Nette\Application\Attributes\Requires;
 
-#[CrossOrigin]
+#[Requires(sameOrigin: false)]
 public function handleXyz()
 {
 }
diff --git a/nette/de/@home.texy b/nette/de/@home.texy
index b8ef3cad0f..9b30ddb609 100644
--- a/nette/de/@home.texy
+++ b/nette/de/@home.texy
@@ -84,11 +84,11 @@ Dienstprogramme
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Passwort-Hashing |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [PHP Typen |utils:type]
 - [Zeichenketten |utils:Strings]
 - [Prüfer |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...andere |utils:]
 </div>
diff --git a/nette/de/installation.texy b/nette/de/installation.texy
index 6e419e22e7..f4c428ca07 100644
--- a/nette/de/installation.texy
+++ b/nette/de/installation.texy
@@ -20,7 +20,7 @@ Nette bietet eine Sammlung von nützlichen und anspruchsvollen Paketen (Biblioth
 composer require nette/utils
 ```
 
-Bevorzugen Sie eine grafische Oberfläche? Sehen Sie sich die [Anleitung |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] zur Installation von Paketen in der PhpStrom-Umgebung an.
+Bevorzugen Sie eine grafische Oberfläche? Sehen Sie sich die [Anleitung |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] zur Installation von Paketen in der PhpStorm-Umgebung an.
 
 
 Wie man ein neues Projekt mit Nette startet .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/de/introduction-to-object-oriented-programming.texy b/nette/de/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..d9bc24c1da
--- /dev/null
+++ b/nette/de/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Einführung in die objektorientierte Programmierung
+**************************************************
+
+.[perex]
+Der Begriff "OOP" steht für Object-Oriented Programming (objektorientierte Programmierung), eine Methode zur Organisation und Strukturierung von Code. OOP ermöglicht es uns, ein Programm als eine Sammlung von Objekten zu betrachten, die miteinander kommunizieren, und nicht als eine Abfolge von Befehlen und Funktionen.
+
+In OOP ist ein "Objekt" eine Einheit, die Daten und Funktionen enthält, die mit diesen Daten arbeiten. Objekte werden auf der Grundlage von "Klassen" erstellt, die als Entwürfe oder Vorlagen für Objekte verstanden werden können. Sobald wir eine Klasse haben, können wir ihre "Instanz" erstellen, d. h. ein spezifisches Objekt, das aus dieser Klasse besteht.
+
+Schauen wir uns an, wie wir eine einfache Klasse in PHP erstellen können. Bei der Definition einer Klasse verwenden wir das Schlüsselwort "class", gefolgt vom Klassennamen und geschweiften Klammern, die die Funktionen der Klasse (genannt "Methoden") und die Variablen der Klasse (genannt "Eigenschaften" oder "Attribute") einschließen:
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+In diesem Beispiel haben wir eine Klasse namens `Car` mit einer Funktion (oder "Methode") namens `honk` erstellt.
+
+Jede Klasse sollte nur eine Hauptaufgabe lösen. Wenn eine Klasse zu viele Aufgaben hat, kann es sinnvoll sein, sie in kleinere, spezialisierte Klassen aufzuteilen.
+
+Klassen werden in der Regel in separaten Dateien gespeichert, damit der Code übersichtlich bleibt und leicht zu navigieren ist. Der Dateiname sollte mit dem Klassennamen übereinstimmen, für die Klasse `Car` wäre der Dateiname also `Car.php`.
+
+Bei der Benennung von Klassen sollte man sich an die "PascalCase"-Konvention halten, d. h. jedes Wort im Namen beginnt mit einem Großbuchstaben, und es gibt keine Unterstriche oder andere Trennzeichen. Methoden und Eigenschaften folgen der "camelCase"-Konvention, das heißt, sie beginnen mit einem Kleinbuchstaben.
+
+Einige Methoden in PHP haben besondere Funktionen und werden mit `__` (zwei Unterstrichen) eingeleitet. Eine der wichtigsten Spezialmethoden ist der "Konstruktor", der mit `__construct` gekennzeichnet ist. Der Konstruktor ist eine Methode, die automatisch aufgerufen wird, wenn eine neue Instanz einer Klasse erstellt wird.
+
+Wir verwenden den Konstruktor häufig, um den Anfangszustand eines Objekts festzulegen. Wenn Sie beispielsweise ein Objekt erstellen, das eine Person darstellt, können Sie den Konstruktor verwenden, um deren Alter, Namen oder andere Attribute festzulegen.
+
+Schauen wir uns an, wie man einen Konstruktor in PHP verwendet:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+In diesem Beispiel hat die Klasse `Person` eine Eigenschaft (Variable) `$age` und einen Konstruktor, der diese Eigenschaft setzt. Die Methode `howOldAreYou()` ermöglicht dann den Zugriff auf das Alter der Person.
+
+Die Pseudovariable `$this` wird innerhalb der Klasse für den Zugriff auf die Eigenschaften und Methoden des Objekts verwendet.
+
+Das Schlüsselwort `new` wird verwendet, um eine neue Instanz einer Klasse zu erstellen. Im obigen Beispiel haben wir eine neue Person im Alter von 25 Jahren erstellt.
+
+Sie können auch Standardwerte für Konstruktorparameter festlegen, wenn diese bei der Erstellung eines Objekts nicht angegeben werden. Zum Beispiel:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Wenn Sie in diesem Beispiel bei der Erstellung eines `Person` Objekts kein Alter angeben, wird der Standardwert von 20 verwendet.
+
+Das Schöne daran ist, dass die Eigenschaftsdefinition mit ihrer Initialisierung über den Konstruktor wie folgt verkürzt und vereinfacht werden kann:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Der Vollständigkeit halber sei erwähnt, dass Objekte neben Konstruktoren auch Destruktoren haben können (Methode `__destruct`), die aufgerufen werden, bevor das Objekt aus dem Speicher freigegeben wird.
+
+
+Namespaces .[#toc-namespaces]
+-----------------------------
+
+Namensräume ermöglichen es uns, verwandte Klassen, Funktionen und Konstanten zu organisieren und zu gruppieren und gleichzeitig Benennungskonflikte zu vermeiden. Man kann sie sich wie Ordner auf einem Computer vorstellen, wobei jeder Ordner Dateien enthält, die sich auf ein bestimmtes Projekt oder Thema beziehen.
+
+Namensräume sind besonders nützlich in größeren Projekten oder bei der Verwendung von Bibliotheken von Drittanbietern, wo es zu Konflikten bei der Benennung von Klassen kommen kann.
+
+Stellen Sie sich vor, Sie haben in Ihrem Projekt eine Klasse mit dem Namen `Car`, die Sie in einen Namensraum mit dem Namen `Transport` einfügen möchten. Sie würden folgendermaßen vorgehen:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Wenn Sie die Klasse `Car` in einer anderen Datei verwenden wollen, müssen Sie angeben, aus welchem Namespace die Klasse stammt:
+
+```php
+$car = new Transport\Car;
+```
+
+Zur Vereinfachung können Sie am Anfang der Datei angeben, welche Klasse aus einem bestimmten Namespace Sie verwenden wollen, so dass Sie Instanzen erstellen können, ohne den vollständigen Pfad angeben zu müssen:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Vererbung .[#toc-inheritance]
+-----------------------------
+
+Die Vererbung ist ein Werkzeug der objektorientierten Programmierung, das es ermöglicht, neue Klassen auf der Grundlage bestehender Klassen zu erstellen, deren Eigenschaften und Methoden zu erben und sie bei Bedarf zu erweitern oder neu zu definieren. Die Vererbung gewährleistet die Wiederverwendbarkeit des Codes und die Klassenhierarchie.
+
+Einfach ausgedrückt: Wenn wir eine Klasse haben und eine andere davon abgeleitete Klasse mit einigen Änderungen erstellen möchten, können wir die neue Klasse von der ursprünglichen Klasse "erben".
+
+In PHP wird die Vererbung mit dem Schlüsselwort `extends` realisiert.
+
+Unsere Klasse `Person` speichert Altersinformationen. Wir können eine weitere Klasse, `Student`, erstellen, die `Person` erweitert und Informationen über das Studienfach hinzufügt.
+
+Schauen wir uns ein Beispiel an:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Wie funktioniert dieser Code?
+
+- Wir haben das Schlüsselwort `extends` verwendet, um die Klasse `Person` zu erweitern, d.h. die Klasse `Student` erbt alle Methoden und Eigenschaften von `Person`.
+
+- Mit dem Schlüsselwort `parent::` können wir Methoden der übergeordneten Klasse aufrufen. In diesem Fall haben wir den Konstruktor der Klasse `Person` aufgerufen, bevor wir der Klasse `Student` unsere eigenen Funktionen hinzugefügt haben. Ähnlich verhält es sich mit der Vorgängermethode `printInformation()`, bevor wir die Schülerinformationen auflisten.
+
+Vererbung ist für Situationen gedacht, in denen es eine "ist ein"-Beziehung zwischen Klassen gibt. Zum Beispiel ist eine `Student` eine `Person`. Eine Katze ist ein Tier. Sie ermöglicht es uns, in Fällen, in denen wir ein Objekt (z. B. "Person") im Code erwarten, stattdessen ein abgeleitetes Objekt zu verwenden (z. B. "Student").
+
+Es ist wichtig zu erkennen, dass der Hauptzweck der Vererbung **nicht** darin besteht, doppelten Code zu verhindern. Im Gegenteil, der Missbrauch von Vererbung kann zu komplexem und schwer zu wartendem Code führen. Wenn es keine "ist ein"-Beziehung zwischen Klassen gibt, sollten wir Komposition anstelle von Vererbung in Betracht ziehen.
+
+Beachten Sie, dass die Methoden `printInformation()` in den Klassen `Person` und `Student` leicht unterschiedliche Informationen ausgeben. Und wir können weitere Klassen hinzufügen (z. B. `Employee`), die andere Implementierungen dieser Methode bereitstellen werden. Die Fähigkeit von Objekten verschiedener Klassen, auf dieselbe Methode auf unterschiedliche Weise zu reagieren, wird als Polymorphismus bezeichnet:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Komposition .[#toc-composition]
+-------------------------------
+
+Komposition ist eine Technik, bei der wir, anstatt Eigenschaften und Methoden einer anderen Klasse zu erben, einfach deren Instanz in unserer Klasse verwenden. Auf diese Weise können wir Funktionalitäten und Eigenschaften mehrerer Klassen kombinieren, ohne komplexe Vererbungsstrukturen zu schaffen.
+
+Ein Beispiel: Wir haben eine Klasse `Engine` und eine Klasse `Car`. Anstatt zu sagen "Ein Auto ist ein Motor", sagen wir "Ein Auto hat einen Motor", was eine typische Kompositionsbeziehung ist.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+In diesem Fall verfügt die Klasse `Car` nicht über alle Eigenschaften und Methoden der Klasse `Engine`, aber sie hat über die Eigenschaft `$engine` Zugang zu ihnen.
+
+Der Vorteil der Komposition ist eine größere Flexibilität bei der Gestaltung und eine bessere Anpassungsfähigkeit an künftige Änderungen.
+
+
+Sichtbarkeit .[#toc-visibility]
+-------------------------------
+
+In PHP können Sie "Sichtbarkeit" für Klasseneigenschaften, Methoden und Konstanten definieren. Die Sichtbarkeit bestimmt, wo Sie auf diese Elemente zugreifen können.
+
+1. **Öffentlich:** Wenn ein Element als `public` gekennzeichnet ist, bedeutet dies, dass Sie von überall darauf zugreifen können, auch außerhalb der Klasse.
+
+2. **Geschützt:** Ein als `protected` gekennzeichnetes Element ist nur innerhalb der Klasse und aller ihrer Nachkommen (Klassen, die von ihr erben) zugänglich.
+
+3. **Privat:** Wenn ein Element als `private` gekennzeichnet ist, kann man nur innerhalb der Klasse, in der es definiert wurde, darauf zugreifen.
+
+Wenn Sie die Sichtbarkeit nicht angeben, setzt PHP sie automatisch auf `public`.
+
+Schauen wir uns einen Beispielcode an:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Fortsetzung der Klassenvererbung:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+In diesem Fall kann die Methode `printProperties()` in der `ChildClass` auf die öffentlichen und geschützten Eigenschaften zugreifen, aber nicht auf die privaten Eigenschaften der übergeordneten Klasse.
+
+Daten und Methoden sollten so versteckt wie möglich sein und nur über eine definierte Schnittstelle zugänglich sein. Auf diese Weise können Sie die interne Implementierung der Klasse ändern, ohne dass sich dies auf den restlichen Code auswirkt.
+
+
+Final-Schlüsselwort .[#toc-final-keyword]
+-----------------------------------------
+
+In PHP können wir das Schlüsselwort `final` verwenden, wenn wir verhindern wollen, dass eine Klasse, Methode oder Konstante geerbt oder überschrieben wird. Wenn eine Klasse als `final` markiert ist, kann sie nicht erweitert werden. Wenn eine Methode als `final` markiert ist, kann sie in einer Unterklasse nicht überschrieben werden.
+
+Wenn wir wissen, dass eine bestimmte Klasse oder Methode nicht mehr geändert wird, können wir leichter Änderungen vornehmen, ohne uns Gedanken über mögliche Konflikte zu machen. Wir können zum Beispiel eine neue Methode hinzufügen, ohne befürchten zu müssen, dass ein Nachkomme bereits eine Methode mit demselben Namen hat, was zu einer Kollision führen würde. Oder wir können die Parameter einer Methode ändern, ohne das Risiko einer Inkonsistenz mit einer überschriebenen Methode in einem Nachfahren einzugehen.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+In diesem Beispiel führt der Versuch, von der endgültigen Klasse `FinalClass` zu erben, zu einem Fehler.
+
+
+Statische Eigenschaften und Methoden .[#toc-static-properties-and-methods]
+--------------------------------------------------------------------------
+
+Wenn wir in PHP von "statischen" Elementen einer Klasse sprechen, meinen wir Methoden und Eigenschaften, die zur Klasse selbst gehören, nicht zu einer bestimmten Instanz der Klasse. Das bedeutet, dass Sie keine Instanz der Klasse erstellen müssen, um auf sie zuzugreifen. Stattdessen können Sie sie direkt über den Klassennamen aufrufen oder auf sie zugreifen.
+
+Da statische Elemente zur Klasse und nicht zu ihren Instanzen gehören, können Sie die Pseudovariable `$this` nicht in statischen Methoden verwenden.
+
+Die Verwendung von statischen Eigenschaften führt zu [verschleiertem Code voller Fallstricke |dependency-injection:global-state], so dass Sie sie niemals verwenden sollten, und wir werden hier auch kein Beispiel zeigen. Andererseits sind statische Methoden nützlich. Hier ist ein Beispiel:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+In diesem Beispiel haben wir eine Klasse `Calculator` mit zwei statischen Methoden erstellt. Wir können diese Methoden direkt aufrufen, ohne eine Instanz der Klasse mit dem `::` Operator zu erstellen. Statische Methoden sind besonders nützlich für Operationen, die nicht vom Zustand einer bestimmten Klasseninstanz abhängen.
+
+
+Klassenkonstanten .[#toc-class-constants]
+-----------------------------------------
+
+Innerhalb von Klassen haben wir die Möglichkeit, Konstanten zu definieren. Konstanten sind Werte, die sich während der Ausführung des Programms nicht ändern. Im Gegensatz zu Variablen bleibt der Wert einer Konstante gleich.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+In diesem Beispiel haben wir eine Klasse `Car` mit der Konstante `NumberOfWheels`. Beim Zugriff auf die Konstante innerhalb der Klasse können wir das Schlüsselwort `self` anstelle des Klassennamens verwenden.
+
+
+Objektschnittstellen .[#toc-object-interfaces]
+----------------------------------------------
+
+Objektschnittstellen fungieren als "Verträge" für Klassen. Wenn eine Klasse eine Objektschnittstelle implementieren soll, muss sie alle Methoden enthalten, die die Schnittstelle definiert. Auf diese Weise kann man sicherstellen, dass sich bestimmte Klassen an denselben "Vertrag" oder dieselbe Struktur halten.
+
+In PHP werden Schnittstellen mit dem Schlüsselwort `interface` definiert. Alle Methoden, die in einer Schnittstelle definiert sind, sind öffentlich (`public`). Wenn eine Klasse eine Schnittstelle implementiert, verwendet sie das Schlüsselwort `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Wenn eine Klasse eine Schnittstelle implementiert, aber nicht alle erwarteten Methoden definiert sind, wird PHP einen Fehler ausgeben.
+
+Eine Klasse kann mehrere Schnittstellen auf einmal implementieren, was sich von der Vererbung unterscheidet, bei der eine Klasse nur von einer Klasse erben kann:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Abstrakte Klassen .[#toc-abstract-classes]
+------------------------------------------
+
+Abstrakte Klassen dienen als Basisvorlagen für andere Klassen, aber Sie können ihre Instanzen nicht direkt erstellen. Sie enthalten eine Mischung aus vollständigen Methoden und abstrakten Methoden, die keinen definierten Inhalt haben. Klassen, die von abstrakten Klassen erben, müssen Definitionen für alle abstrakten Methoden der Elternklasse bereitstellen.
+
+Wir verwenden das Schlüsselwort `abstract`, um eine abstrakte Klasse zu definieren.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+In diesem Beispiel haben wir eine abstrakte Klasse mit einer regulären und einer abstrakten Methode. Dann haben wir eine Klasse `Child`, die von `AbstractClass` erbt und eine Implementierung für die abstrakte Methode bereitstellt.
+
+Was ist der Unterschied zwischen Schnittstellen und abstrakten Klassen? Abstrakte Klassen können sowohl abstrakte als auch konkrete Methoden enthalten, während Schnittstellen nur festlegen, welche Methoden die Klasse implementieren muss, aber keine Implementierung anbieten. Eine Klasse kann nur von einer abstrakten Klasse erben, kann aber eine beliebige Anzahl von Schnittstellen implementieren.
+
+
+Typ-Prüfung .[#toc-type-checking]
+---------------------------------
+
+Beim Programmieren ist es wichtig, sicherzustellen, dass die Daten, mit denen wir arbeiten, vom richtigen Typ sind. In PHP gibt es Werkzeuge, die diese Sicherheit bieten. Die Überprüfung, ob die Daten vom richtigen Typ sind, nennt man "Typüberprüfung".
+
+Typen, denen wir in PHP begegnen können:
+
+1. **Basistypen**: Dazu gehören `int` (Ganzzahlen), `float` (Gleitkommazahlen), `bool` (boolesche Werte), `string` (Strings), `array` (Arrays) und `null`.
+2. **Klassen**: Wenn ein Wert eine Instanz einer bestimmten Klasse sein soll.
+3. **Schnittstellen**: Definiert eine Reihe von Methoden, die eine Klasse implementieren muss. Ein Wert, der eine Schnittstelle erfüllt, muss über diese Methoden verfügen.
+4. **Mischtypen**: Wir können festlegen, dass eine Variable mehrere zulässige Typen haben kann.
+5. **Void**: Dieser spezielle Typ gibt an, dass eine Funktion oder Methode keinen Wert zurückgibt.
+
+Schauen wir uns an, wie wir den Code ändern können, um Typen einzubeziehen:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Auf diese Weise stellen wir sicher, dass unser Code Daten des richtigen Typs erwartet und mit ihnen arbeitet, was uns hilft, mögliche Fehler zu vermeiden.
+
+Einige Typen können nicht direkt in PHP geschrieben werden. In diesem Fall werden sie im phpDoc-Kommentar aufgeführt, dem Standardformat für die Dokumentation von PHP-Code, das mit `/**` beginnt und mit `*/` endet. Es ermöglicht Ihnen, Beschreibungen von Klassen, Methoden usw. hinzuzufügen. Außerdem können Sie komplexe Typen mit den so genannten Annotationen `@var`, `@param` und `@return` auflisten. Diese Typen werden dann von statischen Code-Analyse-Tools verwendet, aber nicht von PHP selbst überprüft.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Vergleich und Identität .[#toc-comparison-and-identity]
+-------------------------------------------------------
+
+In PHP können Sie Objekte auf zwei Arten vergleichen:
+
+1. Wertevergleich `==`: Es wird geprüft, ob die Objekte der gleichen Klasse angehören und die gleichen Werte in ihren Eigenschaften haben.
+2. Identität `===`: Prüft, ob es sich um die gleiche Instanz des Objekts handelt.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Der `instanceof` Operator .[#toc-the-instanceof-operator]
+---------------------------------------------------------
+
+Mit dem Operator `instanceof` können Sie feststellen, ob ein bestimmtes Objekt eine Instanz einer bestimmten Klasse ist, ein Nachkomme dieser Klasse oder ob es eine bestimmte Schnittstelle implementiert.
+
+Stellen Sie sich vor, wir haben eine Klasse `Person` und eine weitere Klasse `Student`, die ein Nachkomme von `Person` ist:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Aus den Ausgaben ist ersichtlich, dass das Objekt `$student` als Instanz der Klassen `Student` und `Person` betrachtet wird.
+
+
+Fließende Schnittstellen .[#toc-fluent-interfaces]
+--------------------------------------------------
+
+Eine "Fluent Interface" ist eine Technik in der OOP, die es ermöglicht, Methoden in einem einzigen Aufruf zu verketten. Dies vereinfacht und verdeutlicht oft den Code.
+
+Das Schlüsselelement einer fließenden Schnittstelle ist, dass jede Methode in der Kette einen Verweis auf das aktuelle Objekt zurückgibt. Dies wird durch die Verwendung von `return $this;` am Ende der Methode erreicht. Dieser Programmierstil wird häufig mit Methoden in Verbindung gebracht, die "Setter" genannt werden und die Werte der Eigenschaften eines Objekts festlegen.
+
+Schauen wir uns an, wie eine fließende Schnittstelle für das Senden von E-Mails aussehen könnte:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+In diesem Beispiel werden die Methoden `setFrom()`, `setRecipient()` und `setMessage()` verwendet, um die entsprechenden Werte (Absender, Empfänger, Nachrichteninhalt) zu setzen. Nach dem Setzen jedes dieser Werte geben die Methoden das aktuelle Objekt (`$email`) zurück, so dass wir eine weitere Methode dahinter verketten können. Schließlich rufen wir die Methode `send()` auf, die die E-Mail tatsächlich versendet.
+
+Dank der fließenden Schnittstellen können wir Code schreiben, der intuitiv und leicht lesbar ist.
+
+
+Kopieren mit `clone` .[#toc-copying-with-clone]
+-----------------------------------------------
+
+In PHP können wir eine Kopie eines Objekts mit dem Operator `clone` erstellen. Auf diese Weise erhalten wir eine neue Instanz mit identischem Inhalt.
+
+Wenn wir beim Kopieren eines Objekts einige seiner Eigenschaften ändern müssen, können wir eine spezielle Methode `__clone()` in der Klasse definieren. Diese Methode wird automatisch aufgerufen, wenn das Objekt geklont wird.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+In diesem Beispiel haben wir eine Klasse `Sheep` mit einer Eigenschaft `$name`. Wenn wir eine Instanz dieser Klasse klonen, sorgt die Methode `__clone()` dafür, dass der Name des geklonten Schafs das Präfix "Clone of" erhält.
+
+
+Eigenschaften .[#toc-traits]
+----------------------------
+
+Traits in PHP sind ein Werkzeug, das die gemeinsame Nutzung von Methoden, Eigenschaften und Konstanten zwischen Klassen ermöglicht und die Duplizierung von Code verhindert. Man kann sie sich wie einen "Kopieren und Einfügen"-Mechanismus vorstellen (Strg-C und Strg-V), bei dem der Inhalt eines Traits in Klassen "eingefügt" wird. So können Sie Code wiederverwenden, ohne komplizierte Klassenhierarchien erstellen zu müssen.
+
+Werfen wir einen Blick auf ein einfaches Beispiel für die Verwendung von Traits in PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+In diesem Beispiel haben wir einen Trait namens `Honking`, der eine Methode `honk()` enthält. Dann haben wir zwei Klassen: `Car` und `Truck`, die beide den Trait `Honking` verwenden. Infolgedessen "besitzen" beide Klassen die Methode `honk()`, und wir können sie für Objekte beider Klassen aufrufen.
+
+Traits ermöglichen eine einfache und effiziente gemeinsame Nutzung von Code zwischen Klassen. Sie greifen nicht in die Vererbungshierarchie ein, d. h. `$car instanceof Honking` gibt `false` zurück.
+
+
+Ausnahmen
+---------
+
+Ausnahmen in der OOP ermöglichen es uns, Fehler und unerwartete Situationen in unserem Code anständig zu behandeln. Sie sind Objekte, die Informationen über einen Fehler oder eine ungewöhnliche Situation enthalten.
+
+In PHP haben wir eine eingebaute Klasse `Exception`, die als Basis für alle Ausnahmen dient. Sie verfügt über mehrere Methoden, mit denen wir weitere Informationen über die Ausnahme erhalten können, z. B. die Fehlermeldung, die Datei und die Zeile, in der der Fehler aufgetreten ist, usw.
+
+Wenn ein Fehler im Code auftritt, können wir die Ausnahme mit dem Schlüsselwort `throw` "werfen".
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Wenn die Funktion `division()` null als zweites Argument erhält, löst sie eine Ausnahme mit der Fehlermeldung `'Division by zero!'` aus. Um zu verhindern, dass das Programm abstürzt, wenn die Ausnahme ausgelöst wird, fangen wir sie im Block `try/catch` ab:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Code, der eine Ausnahme auslösen kann, wird in einen Block `try` eingeschlossen. Wenn die Ausnahme ausgelöst wird, geht die Codeausführung in einen Block `catch` über, in dem wir die Ausnahme behandeln können (z. B. eine Fehlermeldung schreiben).
+
+Nach den Blöcken `try` und `catch` kann ein optionaler Block `finally` eingefügt werden, der immer ausgeführt wird, unabhängig davon, ob die Ausnahme ausgelöst wurde oder nicht (auch wenn `return`, `break` oder `continue` im Block `try` oder `catch` verwendet wird):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Wir können auch unsere eigenen Ausnahmeklassen (Hierarchie) erstellen, die von der Klasse Exception erben. Betrachten wir als Beispiel eine einfache Bankanwendung, die Einzahlungen und Abhebungen erlaubt:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Mehrere `catch` Blöcke können für einen einzigen `try` Block angegeben werden, wenn Sie verschiedene Arten von Ausnahmen erwarten.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+In diesem Beispiel ist es wichtig, die Reihenfolge der `catch` Blöcke zu beachten. Da alle Ausnahmen von `BankingException` erben, würden alle Ausnahmen in diesem Block abgefangen werden, ohne dass der Code die nachfolgenden Blöcke von `catch` erreicht. Daher ist es wichtig, spezifischere Ausnahmen (d. h. solche, die von anderen erben) in der Reihenfolge der `catch` -Blöcke höher anzusiedeln als ihre übergeordneten Ausnahmen.
+
+
+Wiederholungen .[#toc-iterations]
+---------------------------------
+
+In PHP können Sie mit der `foreach` Schleife durch Objekte laufen, ähnlich wie Sie durch ein Array laufen. Damit dies funktioniert, muss das Objekt eine spezielle Schnittstelle implementieren.
+
+Die erste Möglichkeit besteht darin, die Schnittstelle `Iterator` zu implementieren, die über die Methoden `current()`, die den aktuellen Wert zurückgeben, `key()`, die den Schlüssel zurückgeben, `next()`, die zum nächsten Wert springen, `rewind()`, die zum Anfang springen, und `valid()`, die überprüft, ob wir schon am Ende sind, verfügt.
+
+Die andere Möglichkeit besteht darin, eine Schnittstelle `IteratorAggregate` zu implementieren, die nur eine Methode `getIterator()` hat. Diese gibt entweder ein Platzhalterobjekt zurück, das die Durchquerung ermöglicht, oder sie kann ein Generator sein, eine spezielle Funktion, die `yield` verwendet, um Schlüssel und Werte nacheinander zurückzugeben:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Bewährte Praktiken .[#toc-best-practices]
+-----------------------------------------
+
+Sobald Sie die Grundprinzipien der objektorientierten Programmierung beherrschen, ist es wichtig, sich auf die besten Praktiken der OOP zu konzentrieren. Diese helfen Ihnen, Code zu schreiben, der nicht nur funktional, sondern auch lesbar, verständlich und leicht zu warten ist.
+
+1) **Trennung von Belangen**: Jede Klasse sollte eine klar definierte Verantwortung haben und sich nur mit einer Hauptaufgabe befassen. Wenn eine Klasse zu viele Aufgaben hat, kann es sinnvoll sein, sie in kleinere, spezialisierte Klassen aufzuteilen.
+2) **Kapselung**: Daten und Methoden sollten so versteckt wie möglich sein und nur über eine definierte Schnittstelle zugänglich sein. Auf diese Weise können Sie die interne Implementierung einer Klasse ändern, ohne dass sich dies auf den restlichen Code auswirkt.
+3) **Dependency Injection**: Anstatt Abhängigkeiten direkt innerhalb einer Klasse zu schaffen, sollten Sie sie von außen "injizieren". Für ein tieferes Verständnis dieses Prinzips empfehlen wir die [Kapitel über Dependency Injection |dependency-injection:introduction].
diff --git a/nette/de/troubleshooting.texy b/nette/de/troubleshooting.texy
index 3f6bad0a91..c969b14507 100644
--- a/nette/de/troubleshooting.texy
+++ b/nette/de/troubleshooting.texy
@@ -18,7 +18,7 @@ Sie können den Grund für den Fehler immer im Verzeichnis `log/` finden. Wenn d
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // Ihre IP-Adresse
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Fehler 404, Routing funktioniert nicht .[#toc-error-404-routing-not-working]
 Wenn alle Seiten (außer der Homepage) einen 404-Fehler zurückgeben, sieht es nach einem Serverkonfigurationsproblem für [hübsche URLs |#How to Configure a Server for Nice URLs?] aus.
 
 
+Wie kann man den Cache während der Entwicklung deaktivieren? .[#toc-how-to-disable-cache-during-development]
+------------------------------------------------------------------------------------------------------------
+Nette ist intelligent, und Sie müssen das Caching nicht deaktivieren. Während der Entwicklung wird der Cache automatisch aktualisiert, sobald eine Änderung in der Vorlage oder der DI-Container-Konfiguration vorgenommen wird. Außerdem wird der Entwicklungsmodus durch automatische Erkennung aktiviert, so dass normalerweise nichts konfiguriert werden muss, [auch nicht die IP-Adresse |application:bootstrap#development-vs-production-mode].
+
+Bei der Fehlersuche im Router empfiehlt es sich, den Browser-Cache zu deaktivieren, in dem z. B. Umleitungen gespeichert sein könnten: Öffnen Sie die Entwicklertools (Strg+Umschalt+I oder Cmd+Option+I) und aktivieren Sie im Bereich Netzwerk das Kontrollkästchen zur Deaktivierung des Cache.
+
+
 Fehler `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Dieser Fehler tritt auf, wenn Sie PHP auf Version 8.1 aktualisiert haben, aber Nette verwenden, das damit nicht kompatibel ist. Die Lösung besteht also darin, Nette mit `composer update` auf eine neuere Version zu aktualisieren. Nette unterstützt PHP 8.1 seit Version 3.0. Wenn Sie eine ältere Version verwenden (Sie können dies unter `composer.json` herausfinden), [aktualisieren Sie Nette |migrations:en] oder bleiben Sie bei PHP 8.0.
@@ -67,7 +74,7 @@ Das Verzeichnis `www/`, das in den Beispielprojekten in Nette verwendet wird, is
 
 Um die Anwendung auf dem Hosting laufen zu lassen, müssen Sie das document-root in der Hosting-Konfiguration auf dieses Verzeichnis setzen. Oder, wenn das Hosting einen vorgefertigten Ordner für das öffentliche Verzeichnis mit einem anderen Namen hat (zum Beispiel `web`, `public_html` usw.), benennen Sie einfach `www/` um.
 
-Die Lösung **ist** nicht, den Ordner `www/` durch Regeln in der Datei `.htaccess` oder im Router "loszuwerden". Wenn das Hosting Ihnen nicht erlaubt, document-root auf ein Unterverzeichnis zu setzen (d.h. Verzeichnisse eine Ebene über dem öffentlichen Verzeichnis zu erstellen), suchen Sie nach einem anderen. Andernfalls würden Sie ein erhebliches Sicherheitsrisiko eingehen. Das wäre so, als würden Sie in einer Wohnung leben, deren Eingangstür Sie nicht schließen können und die immer weit offen steht.
+Die Lösung **ist** nicht, den Zugriff auf alle Verzeichnisse außer `www/` durch Regeln in der Datei `.htaccess` oder im Router zu verhindern. Wenn Ihr Hosting nicht erlaubt, das Stammverzeichnis für Dokumente auf ein Unterverzeichnis zu setzen (d. h. Verzeichnisse eine Ebene über dem öffentlichen Verzeichnis anzulegen), sollten Sie sich nach einem anderen Hosting-Dienst umsehen. Andernfalls würden Sie sich einem erheblichen Sicherheitsrisiko aussetzen. Das wäre so, als würden Sie in einer Wohnung leben, deren Eingangstür nicht geschlossen werden kann und immer offen steht.
 
 
 Wie konfiguriert man einen Server für schöne URLs? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/el/@home.texy b/nette/el/@home.texy
index 24a21d5a36..2923d00186 100644
--- a/nette/el/@home.texy
+++ b/nette/el/@home.texy
@@ -84,11 +84,11 @@ Nette Τεκμηρίωση
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Κρυπτογράφηση κωδικού πρόσβασης |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Τύποι PHP |utils:type]
 - [Strings |utils:Strings]
 - [Επικυρωτές |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...άλλα |utils:]
 </div>
diff --git a/nette/el/installation.texy b/nette/el/installation.texy
index d99ca71ff0..bf7a84e962 100644
--- a/nette/el/installation.texy
+++ b/nette/el/installation.texy
@@ -20,7 +20,7 @@
 composer require nette/utils
 ```
 
-Προτιμάτε ένα γραφικό περιβάλλον εργασίας; Ανατρέξτε στον [οδηγό |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] για την εγκατάσταση πακέτων στο περιβάλλον PhpStrom.
+Προτιμάτε ένα γραφικό περιβάλλον εργασίας; Ανατρέξτε στον [οδηγό |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] για την εγκατάσταση πακέτων στο περιβάλλον PhpStorm.
 
 
 Πώς να ξεκινήσετε ένα νέο έργο με τη Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/el/introduction-to-object-oriented-programming.texy b/nette/el/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..fdffc10a6e
--- /dev/null
+++ b/nette/el/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Εισαγωγή στον αντικειμενοστραφή προγραμματισμό
+**********************************************
+
+.[perex]
+Ο όρος "OOP" σημαίνει αντικειμενοστραφής προγραμματισμός, ο οποίος είναι ένας τρόπος οργάνωσης και δόμησης του κώδικα. Ο OOP μας επιτρέπει να βλέπουμε ένα πρόγραμμα ως μια συλλογή αντικειμένων που επικοινωνούν μεταξύ τους, αντί για μια ακολουθία εντολών και συναρτήσεων.
+
+Στο OOP, ένα "αντικείμενο" είναι μια μονάδα που περιέχει δεδομένα και συναρτήσεις που λειτουργούν με αυτά τα δεδομένα. Τα αντικείμενα δημιουργούνται με βάση "κλάσεις", οι οποίες μπορούν να εκληφθούν ως σχέδια ή πρότυπα για αντικείμενα. Αφού έχουμε μια κλάση, μπορούμε να δημιουργήσουμε την "παρουσία" της, η οποία είναι ένα συγκεκριμένο αντικείμενο κατασκευασμένο από αυτή την κλάση.
+
+Ας δούμε πώς μπορούμε να δημιουργήσουμε μια απλή κλάση στην PHP. Όταν ορίζουμε μια κλάση, χρησιμοποιούμε τη λέξη-κλειδί "class", ακολουθούμενη από το όνομα της κλάσης και στη συνέχεια από τις τεθλασμένες αγκύλες που περικλείουν τις συναρτήσεις της κλάσης (που ονομάζονται "μέθοδοι") και τις μεταβλητές της κλάσης (που ονομάζονται "ιδιότητες" ή "χαρακτηριστικά"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Σε αυτό το παράδειγμα, δημιουργήσαμε μια κλάση με όνομα `Car` με μια συνάρτηση (ή "μέθοδο") που ονομάζεται `honk`.
+
+Κάθε τάξη θα πρέπει να επιλύει μόνο μία κύρια εργασία. Εάν μια τάξη κάνει πάρα πολλά πράγματα, μπορεί να είναι σκόπιμο να χωριστεί σε μικρότερες, εξειδικευμένες τάξεις.
+
+Οι κλάσεις συνήθως αποθηκεύονται σε ξεχωριστά αρχεία για να διατηρείται ο κώδικας οργανωμένος και εύκολος στην πλοήγηση. Το όνομα του αρχείου πρέπει να ταιριάζει με το όνομα της κλάσης, οπότε για την κλάση `Car`, το όνομα του αρχείου θα είναι `Car.php`.
+
+Όταν ονομάζετε κλάσεις, είναι καλό να ακολουθείτε τη σύμβαση "PascalCase", δηλαδή κάθε λέξη στο όνομα αρχίζει με κεφαλαίο γράμμα και δεν υπάρχουν υπογραμμίσεις ή άλλα διαχωριστικά. Οι μέθοδοι και οι ιδιότητες ακολουθούν τη σύμβαση "camelCase", δηλαδή ξεκινούν με πεζά γράμματα.
+
+Ορισμένες μέθοδοι στην PHP έχουν ειδικούς ρόλους και προτάσσονται με `__` (δύο υπογράμμιση). Μία από τις πιο σημαντικές ειδικές μεθόδους είναι ο "κατασκευαστής", με την ένδειξη `__construct`. Ο κατασκευαστής είναι μια μέθοδος που καλείται αυτόματα κατά τη δημιουργία μιας νέας περίπτωσης μιας κλάσης.
+
+Συχνά χρησιμοποιούμε τον κατασκευαστή για να ορίσουμε την αρχική κατάσταση ενός αντικειμένου. Για παράδειγμα, κατά τη δημιουργία ενός αντικειμένου που αναπαριστά ένα άτομο, μπορεί να χρησιμοποιήσετε τον κατασκευαστή για να ορίσετε την ηλικία, το όνομα ή άλλα χαρακτηριστικά του.
+
+Ας δούμε πώς μπορείτε να χρησιμοποιήσετε έναν κατασκευαστή στην PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+Σε αυτό το παράδειγμα, η κλάση `Person` έχει μια ιδιότητα (μεταβλητή) `$age` και έναν κατασκευαστή που ορίζει αυτή την ιδιότητα. Η μέθοδος `howOldAreYou()` παρέχει στη συνέχεια πρόσβαση στην ηλικία του ατόμου.
+
+Η ψευδομεταβλητή `$this` χρησιμοποιείται μέσα στην κλάση για την πρόσβαση στις ιδιότητες και τις μεθόδους του αντικειμένου.
+
+Η λέξη-κλειδί `new` χρησιμοποιείται για τη δημιουργία μιας νέας περίπτωσης μιας κλάσης. Στο παραπάνω παράδειγμα, δημιουργήσαμε ένα νέο άτομο ηλικίας 25 ετών.
+
+Μπορείτε επίσης να ορίσετε προεπιλεγμένες τιμές για τις παραμέτρους του κατασκευαστή, εάν δεν έχουν καθοριστεί κατά τη δημιουργία ενός αντικειμένου. Για παράδειγμα:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Σε αυτό το παράδειγμα, αν δεν καθορίσετε μια ηλικία κατά τη δημιουργία ενός αντικειμένου `Person`, θα χρησιμοποιηθεί η προεπιλεγμένη τιμή 20.
+
+Το ωραίο είναι ότι ο ορισμός της ιδιότητας με την αρχικοποίησή της μέσω του κατασκευαστή μπορεί να συντομευτεί και να απλοποιηθεί ως εξής:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Για λόγους πληρότητας, εκτός από τους κατασκευαστές, τα αντικείμενα μπορούν να έχουν καταστροφείς (μέθοδος `__destruct`) που καλούνται πριν από την αποδέσμευση του αντικειμένου από τη μνήμη.
+
+
+Χώροι ονομάτων .[#toc-namespaces]
+---------------------------------
+
+Οι χώροι ονομάτων μας επιτρέπουν να οργανώνουμε και να ομαδοποιούμε συναφείς κλάσεις, συναρτήσεις και σταθερές αποφεύγοντας συγκρούσεις ονομάτων. Μπορείτε να τα φανταστείτε όπως τους φακέλους σε έναν υπολογιστή, όπου κάθε φάκελος περιέχει αρχεία που σχετίζονται με ένα συγκεκριμένο έργο ή θέμα.
+
+Οι χώροι ονομάτων είναι ιδιαίτερα χρήσιμοι σε μεγαλύτερα έργα ή όταν χρησιμοποιείτε βιβλιοθήκες τρίτων, όπου μπορεί να προκύψουν συγκρούσεις ονοματοδοσίας κλάσεων.
+
+Φανταστείτε ότι έχετε μια κλάση με όνομα `Car` στο έργο σας και θέλετε να την τοποθετήσετε σε ένα χώρο ονομάτων με όνομα `Transport`. Θα το κάνατε ως εξής:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Αν θέλετε να χρησιμοποιήσετε την κλάση `Car` σε ένα άλλο αρχείο, πρέπει να καθορίσετε από ποιο χώρο ονομάτων προέρχεται η κλάση:
+
+```php
+$car = new Transport\Car;
+```
+
+Για λόγους απλούστευσης, μπορείτε να καθορίσετε στην αρχή του αρχείου ποια κλάση από ένα συγκεκριμένο χώρο ονομάτων θέλετε να χρησιμοποιήσετε, επιτρέποντάς σας να δημιουργήσετε περιπτώσεις χωρίς να αναφέρετε την πλήρη διαδρομή:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Κληρονομικότητα .[#toc-inheritance]
+-----------------------------------
+
+Η κληρονομικότητα είναι ένα εργαλείο του αντικειμενοστρεφούς προγραμματισμού που επιτρέπει τη δημιουργία νέων κλάσεων με βάση τις υπάρχουσες, κληρονομώντας τις ιδιότητες και τις μεθόδους τους και επεκτείνοντας ή επαναπροσδιορίζοντας τες ανάλογα με τις ανάγκες. Η κληρονομικότητα εξασφαλίζει την επαναχρησιμοποίηση του κώδικα και την ιεραρχία των κλάσεων.
+
+Με απλά λόγια, αν έχουμε μια κλάση και θέλουμε να δημιουργήσουμε μια άλλη που να προέρχεται από αυτήν αλλά με κάποιες τροποποιήσεις, μπορούμε να "κληρονομήσουμε" τη νέα κλάση από την αρχική.
+
+Στην PHP, η κληρονομικότητα υλοποιείται με τη χρήση της λέξης-κλειδί `extends`.
+
+Η κλάση μας `Person` αποθηκεύει πληροφορίες για την ηλικία. Μπορούμε να έχουμε μια άλλη κλάση, την `Student`, η οποία επεκτείνει την `Person` και προσθέτει πληροφορίες σχετικά με τον τομέα σπουδών.
+
+Ας δούμε ένα παράδειγμα:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Πώς λειτουργεί αυτός ο κώδικας;
+
+- Χρησιμοποιήσαμε τη λέξη-κλειδί `extends` για να επεκτείνουμε την κλάση `Person`, δηλαδή η κλάση `Student` κληρονομεί όλες τις μεθόδους και τις ιδιότητες από την `Person`.
+
+- Η λέξη-κλειδί `parent::` μας επιτρέπει να καλούμε μεθόδους από τη γονική κλάση. Σε αυτή την περίπτωση, καλέσαμε τον κατασκευαστή από την κλάση `Person` πριν προσθέσουμε τη δική μας λειτουργικότητα στην κλάση `Student`. Και ομοίως, τη μέθοδο του προγόνου `printInformation()` πριν καταχωρίσουμε τις πληροφορίες του μαθητή.
+
+Η κληρονομικότητα προορίζεται για καταστάσεις όπου υπάρχει μια σχέση "είναι ένα" μεταξύ κλάσεων. Για παράδειγμα, μια `Student` είναι μια `Person`. Μια γάτα είναι ένα ζώο. Μας επιτρέπει σε περιπτώσεις όπου περιμένουμε ένα αντικείμενο (π.χ. "Person") στον κώδικα να χρησιμοποιήσουμε αντί αυτού ένα παράγωγο αντικείμενο (π.χ. "Student").
+
+Είναι σημαντικό να συνειδητοποιήσουμε ότι ο πρωταρχικός σκοπός της κληρονομικότητας **δεν** είναι να αποτρέψει την επανάληψη του κώδικα. Αντιθέτως, η κακή χρήση της κληρονομικότητας μπορεί να οδηγήσει σε πολύπλοκο και δύσκολα συντηρήσιμο κώδικα. Εάν δεν υπάρχει σχέση "είναι ένα" μεταξύ των κλάσεων, θα πρέπει να εξετάσουμε τη σύνθεση αντί της κληρονομικότητας.
+
+Σημειώστε ότι οι μέθοδοι `printInformation()` στις κλάσεις `Person` και `Student` δίνουν ελαφρώς διαφορετικές πληροφορίες. Και μπορούμε να προσθέσουμε άλλες κλάσεις (όπως η `Employee`) που θα παρέχουν άλλες υλοποιήσεις αυτής της μεθόδου. Η ικανότητα των αντικειμένων διαφορετικών κλάσεων να ανταποκρίνονται στην ίδια μέθοδο με διαφορετικούς τρόπους ονομάζεται πολυμορφισμός:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Σύνθεση .[#toc-composition]
+---------------------------
+
+Η σύνθεση είναι μια τεχνική κατά την οποία, αντί να κληρονομούμε ιδιότητες και μεθόδους από μια άλλη κλάση, απλά χρησιμοποιούμε την εμφάνισή της στην κλάση μας. Αυτό μας επιτρέπει να συνδυάζουμε λειτουργίες και ιδιότητες πολλών κλάσεων χωρίς να δημιουργούμε πολύπλοκες δομές κληρονομικότητας.
+
+Για παράδειγμα, έχουμε μια κλάση `Engine` και μια κλάση `Car`. Αντί να πούμε "Ένα αυτοκίνητο είναι ένας κινητήρας", λέμε "Ένα αυτοκίνητο έχει έναν κινητήρα", που είναι μια τυπική σχέση σύνθεσης.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Εδώ, η `Car` δεν έχει όλες τις ιδιότητες και τις μεθόδους της `Engine`, αλλά έχει πρόσβαση σε αυτές μέσω της ιδιότητας `$engine`.
+
+Το πλεονέκτημα της σύνθεσης είναι η μεγαλύτερη ευελιξία σχεδιασμού και η καλύτερη προσαρμοστικότητα για μελλοντικές αλλαγές.
+
+
+Ορατότητα .[#toc-visibility]
+----------------------------
+
+Στην PHP, μπορείτε να ορίσετε "ορατότητα" για ιδιότητες, μεθόδους και σταθερές κλάσεων. Η ορατότητα καθορίζει πού μπορείτε να έχετε πρόσβαση σε αυτά τα στοιχεία.
+
+1. **Δημόσιο:** Εάν ένα στοιχείο χαρακτηρίζεται ως `public`, σημαίνει ότι μπορείτε να έχετε πρόσβαση σε αυτό από οπουδήποτε, ακόμη και εκτός της κλάσης.
+
+2. **Προστατευμένο:** Ένα στοιχείο που επισημαίνεται ως `protected` είναι προσβάσιμο μόνο μέσα στην κλάση και σε όλους τους απογόνους της (κλάσεις που κληρονομούν από αυτήν).
+
+3. **Ιδιωτικό:** Εάν ένα στοιχείο είναι `private`, μπορείτε να έχετε πρόσβαση σε αυτό μόνο μέσα από την κλάση στην οποία ορίστηκε.
+
+Αν δεν καθορίσετε ορατότητα, η PHP θα την ορίσει αυτόματα σε `public`.
+
+Ας δούμε ένα παράδειγμα κώδικα:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Συνεχίζοντας με την κληρονομικότητα των κλάσεων:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+Σε αυτή την περίπτωση, η μέθοδος `printProperties()` στην `ChildClass` μπορεί να έχει πρόσβαση στις δημόσιες και προστατευόμενες ιδιότητες, αλλά δεν μπορεί να έχει πρόσβαση στις ιδιωτικές ιδιότητες της γονικής κλάσης.
+
+Τα δεδομένα και οι μέθοδοι θα πρέπει να είναι όσο το δυνατόν πιο κρυφά και προσβάσιμα μόνο μέσω μιας καθορισμένης διεπαφής. Αυτό σας επιτρέπει να αλλάξετε την εσωτερική υλοποίηση της κλάσης χωρίς να επηρεάζεται ο υπόλοιπος κώδικας.
+
+
+Λέξη-κλειδί Final .[#toc-final-keyword]
+---------------------------------------
+
+Στην PHP, μπορούμε να χρησιμοποιήσουμε τη λέξη-κλειδί `final` αν θέλουμε να αποτρέψουμε μια κλάση, μέθοδο ή σταθερά από το να κληρονομηθεί ή να αντικατασταθεί. Όταν μια κλάση χαρακτηρίζεται ως `final`, δεν μπορεί να επεκταθεί. Όταν μια μέθοδος χαρακτηρίζεται ως `final`, δεν μπορεί να αντικατασταθεί σε μια υποκλάση.
+
+Γνωρίζοντας ότι μια συγκεκριμένη κλάση ή μέθοδος δεν θα τροποποιείται πλέον, μπορούμε να κάνουμε αλλαγές πιο εύκολα χωρίς να ανησυχούμε για πιθανές συγκρούσεις. Για παράδειγμα, μπορούμε να προσθέσουμε μια νέα μέθοδο χωρίς να φοβόμαστε ότι ένας απόγονος μπορεί να έχει ήδη μια μέθοδο με το ίδιο όνομα, οδηγώντας σε σύγκρουση. Ή μπορούμε να αλλάξουμε τις παραμέτρους μιας μεθόδου, και πάλι χωρίς τον κίνδυνο να προκαλέσουμε ασυνέπεια με μια μέθοδο που έχει παρακαμφθεί σε έναν απόγονο.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+Σε αυτό το παράδειγμα, η απόπειρα κληρονόμησης από την τελική κλάση `FinalClass` θα οδηγήσει σε σφάλμα.
+
+
+Στατικές ιδιότητες και μέθοδοι .[#toc-static-properties-and-methods]
+--------------------------------------------------------------------
+
+Όταν μιλάμε για "στατικά" στοιχεία μιας κλάσης στην PHP, εννοούμε μεθόδους και ιδιότητες που ανήκουν στην ίδια την κλάση και όχι σε μια συγκεκριμένη περίπτωση της κλάσης. Αυτό σημαίνει ότι δεν χρειάζεται να δημιουργήσετε μια παρουσία της κλάσης για να αποκτήσετε πρόσβαση σε αυτά. Αντ' αυτού, τις καλείτε ή τις προσπελαύνετε απευθείας μέσω του ονόματος της κλάσης.
+
+Λάβετε υπόψη ότι, εφόσον τα στατικά στοιχεία ανήκουν στην κλάση και όχι στις περιπτώσεις της, δεν μπορείτε να χρησιμοποιήσετε την ψευδομεταβλητή `$this` μέσα σε στατικές μεθόδους.
+
+Η χρήση στατικών ιδιοτήτων οδηγεί σε [συγκεχυμένο κώδικα γεμάτο παγίδες |dependency-injection:global-state], γι' αυτό δεν πρέπει ποτέ να τις χρησιμοποιείτε και δεν θα δείξουμε ένα παράδειγμα εδώ. Από την άλλη πλευρά, οι στατικές μέθοδοι είναι χρήσιμες. Ακολουθεί ένα παράδειγμα:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+Σε αυτό το παράδειγμα, δημιουργήσαμε μια κλάση `Calculator` με δύο στατικές μεθόδους. Μπορούμε να καλέσουμε αυτές τις μεθόδους απευθείας χωρίς να δημιουργήσουμε μια περίπτωση της κλάσης χρησιμοποιώντας τον τελεστή `::`. Οι στατικές μέθοδοι είναι ιδιαίτερα χρήσιμες για λειτουργίες που δεν εξαρτώνται από την κατάσταση μιας συγκεκριμένης περίπτωσης της κλάσης.
+
+
+Σταθερές κλάσης .[#toc-class-constants]
+---------------------------------------
+
+Μέσα στις κλάσεις, έχουμε τη δυνατότητα να ορίσουμε σταθερές. Οι σταθερές είναι τιμές που δεν αλλάζουν ποτέ κατά τη διάρκεια της εκτέλεσης του προγράμματος. Σε αντίθεση με τις μεταβλητές, η τιμή μιας σταθεράς παραμένει η ίδια.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+Σε αυτό το παράδειγμα, έχουμε μια κλάση `Car` με τη σταθερά `NumberOfWheels`. Όταν έχουμε πρόσβαση στη σταθερά μέσα στην κλάση, μπορούμε να χρησιμοποιήσουμε τη λέξη-κλειδί `self` αντί για το όνομα της κλάσης.
+
+
+Διεπαφές αντικειμένων .[#toc-object-interfaces]
+-----------------------------------------------
+
+Οι διεπαφές αντικειμένων λειτουργούν ως "συμβόλαια" για τις κλάσεις. Εάν μια κλάση πρόκειται να υλοποιήσει μια διεπαφή αντικειμένου, πρέπει να περιέχει όλες τις μεθόδους που ορίζει η διεπαφή. Είναι ένας πολύ καλός τρόπος για να διασφαλιστεί ότι ορισμένες κλάσεις τηρούν το ίδιο "συμβόλαιο" ή την ίδια δομή.
+
+Στην PHP, οι διεπαφές ορίζονται χρησιμοποιώντας τη λέξη-κλειδί `interface`. Όλες οι μέθοδοι που ορίζονται σε μια διεπαφή είναι δημόσιες (`public`). Όταν μια κλάση υλοποιεί μια διεπαφή, χρησιμοποιεί τη λέξη-κλειδί `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Εάν μια κλάση υλοποιεί μια διασύνδεση, αλλά δεν έχουν οριστεί όλες οι αναμενόμενες μέθοδοι, η PHP θα εκπέμψει ένα σφάλμα.
+
+Μια κλάση μπορεί να υλοποιήσει πολλές διεπαφές ταυτόχρονα, κάτι που διαφέρει από την κληρονομικότητα, όπου μια κλάση μπορεί να κληρονομήσει μόνο από μια κλάση:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Αφηρημένες κλάσεις .[#toc-abstract-classes]
+-------------------------------------------
+
+Οι αφηρημένες κλάσεις χρησιμεύουν ως πρότυπα βάσης για άλλες κλάσεις, αλλά δεν μπορείτε να δημιουργήσετε άμεσα τις περιπτώσεις τους. Περιέχουν ένα μείγμα από πλήρεις μεθόδους και αφηρημένες μεθόδους που δεν έχουν καθορισμένο περιεχόμενο. Οι κλάσεις που κληρονομούν από αφηρημένες κλάσεις πρέπει να παρέχουν ορισμούς για όλες τις αφηρημένες μεθόδους του γονέα.
+
+Χρησιμοποιούμε τη λέξη-κλειδί `abstract` για να ορίσουμε μια αφηρημένη κλάση.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+Σε αυτό το παράδειγμα, έχουμε μια αφηρημένη κλάση με μια κανονική και μια αφηρημένη μέθοδο. Στη συνέχεια έχουμε μια κλάση `Child` που κληρονομεί από την `AbstractClass` και παρέχει μια υλοποίηση για την αφηρημένη μέθοδο.
+
+Σε τι διαφέρουν οι διεπαφές και οι αφηρημένες κλάσεις; Οι αφηρημένες κλάσεις μπορούν να περιέχουν τόσο αφηρημένες όσο και συγκεκριμένες μεθόδους, ενώ οι διεπαφές ορίζουν μόνο ποιες μεθόδους πρέπει να υλοποιεί η κλάση, αλλά δεν παρέχουν καμία υλοποίηση. Μια κλάση μπορεί να κληρονομήσει από μία μόνο αφηρημένη κλάση, αλλά μπορεί να υλοποιήσει οποιονδήποτε αριθμό διεπαφών.
+
+
+Έλεγχος τύπου .[#toc-type-checking]
+-----------------------------------
+
+Στον προγραμματισμό, είναι ζωτικής σημασίας να διασφαλίζουμε ότι τα δεδομένα με τα οποία εργαζόμαστε έχουν τον σωστό τύπο. Στην PHP, διαθέτουμε εργαλεία που παρέχουν αυτή τη διασφάλιση. Η επαλήθευση ότι τα δεδομένα είναι σωστού τύπου ονομάζεται "έλεγχος τύπου".
+
+Τύποι που μπορεί να συναντήσουμε στην PHP:
+
+1. **Βασικοί τύποι**: Αυτοί περιλαμβάνουν `int` (ακέραιοι αριθμοί), `float` (αριθμοί κινητής υποδιαστολής), `bool` (τιμές boolean), `string` (συμβολοσειρές), `array` (πίνακες) και `null`.
+2. **Κλάσεις**: Όταν θέλουμε μια τιμή να είναι περίπτωση μιας συγκεκριμένης κλάσης.
+3. **Διασυνδέσεις**: Ορίζει ένα σύνολο μεθόδων που πρέπει να υλοποιεί μια κλάση. Μια τιμή που ανταποκρίνεται σε μια διεπαφή πρέπει να έχει αυτές τις μεθόδους.
+4. **Μεικτοί τύποι**: Μπορούμε να καθορίσουμε ότι μια μεταβλητή μπορεί να έχει πολλούς επιτρεπόμενους τύπους.
+5. **Void**: Αυτός ο ειδικός τύπος δηλώνει ότι μια συνάρτηση ή μέθοδος δεν επιστρέφει καμία τιμή.
+
+Ας δούμε πώς μπορούμε να τροποποιήσουμε τον κώδικα για να συμπεριλάβουμε τύπους:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Με αυτόν τον τρόπο εξασφαλίζουμε ότι ο κώδικάς μας αναμένει και λειτουργεί με δεδομένα του σωστού τύπου, βοηθώντας μας να αποφύγουμε πιθανά σφάλματα.
+
+Ορισμένοι τύποι δεν μπορούν να γραφτούν απευθείας σε PHP. Σε αυτή την περίπτωση, αναφέρονται στο σχόλιο phpDoc, το οποίο είναι η τυπική μορφή για την τεκμηρίωση κώδικα PHP, ξεκινώντας με `/**` και τελειώνοντας με `*/`. Σας επιτρέπει να προσθέσετε περιγραφές κλάσεων, μεθόδων κ.λπ. Και επίσης να απαριθμήσετε σύνθετους τύπους χρησιμοποιώντας τις λεγόμενες επισημειώσεις `@var`, `@param` και `@return`. Αυτοί οι τύποι χρησιμοποιούνται στη συνέχεια από εργαλεία στατικής ανάλυσης κώδικα, αλλά δεν ελέγχονται από την ίδια την PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Σύγκριση και ταυτότητα .[#toc-comparison-and-identity]
+------------------------------------------------------
+
+Στην PHP, μπορείτε να συγκρίνετε αντικείμενα με δύο τρόπους:
+
+1. Σύγκριση τιμών `==`: Ελέγχει αν τα αντικείμενα ανήκουν στην ίδια κλάση και έχουν τις ίδιες τιμές στις ιδιότητές τους.
+2. Σύγκριση ταυτότητας `===`: Ελέγχει αν πρόκειται για την ίδια περίπτωση του αντικειμένου.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Ο χειριστής `instanceof` .[#toc-the-instanceof-operator]
+--------------------------------------------------------
+
+Ο τελεστής `instanceof` σας επιτρέπει να προσδιορίσετε αν ένα δεδομένο αντικείμενο είναι παράδειγμα μιας συγκεκριμένης κλάσης, απόγονος αυτής της κλάσης ή αν υλοποιεί μια συγκεκριμένη διασύνδεση.
+
+Φανταστείτε ότι έχουμε μια κλάση `Person` και μια άλλη κλάση `Student`, η οποία είναι απόγονος της `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Από τις εξόδους, είναι προφανές ότι το αντικείμενο `$student` θεωρείται παράδειγμα και των δύο κλάσεων `Student` και `Person`.
+
+
+Ρευστές διεπαφές .[#toc-fluent-interfaces]
+------------------------------------------
+
+Μια "ρευστή διεπαφή" είναι μια τεχνική στην OOP που επιτρέπει την αλυσιδωτή σύνδεση μεθόδων με μία μόνο κλήση. Αυτό συχνά απλοποιεί και αποσαφηνίζει τον κώδικα.
+
+Το βασικό στοιχείο μιας ρευστής διεπαφής είναι ότι κάθε μέθοδος στην αλυσίδα επιστρέφει μια αναφορά στο τρέχον αντικείμενο. Αυτό επιτυγχάνεται με τη χρήση του `return $this;` στο τέλος της μεθόδου. Αυτό το στυλ προγραμματισμού συνδέεται συχνά με μεθόδους που ονομάζονται "setters", οι οποίες ορίζουν τις τιμές των ιδιοτήτων ενός αντικειμένου.
+
+Ας δούμε πώς θα μπορούσε να μοιάζει μια ρευστή διεπαφή για την αποστολή μηνυμάτων ηλεκτρονικού ταχυδρομείου:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+Σε αυτό το παράδειγμα, οι μέθοδοι `setFrom()`, `setRecipient()` και `setMessage()` χρησιμοποιούνται για να ορίσουν τις αντίστοιχες τιμές (αποστολέας, παραλήπτης, περιεχόμενο μηνύματος). Μετά τον ορισμό καθεμιάς από αυτές τις τιμές, οι μέθοδοι επιστρέφουν το τρέχον αντικείμενο (`$email`), επιτρέποντάς μας να ακολουθήσουμε αλυσιδωτά μια άλλη μέθοδο. Τέλος, καλούμε τη μέθοδο `send()`, η οποία στην πραγματικότητα στέλνει το μήνυμα ηλεκτρονικού ταχυδρομείου.
+
+Χάρη στις ρευστές διεπαφές, μπορούμε να γράψουμε κώδικα που είναι διαισθητικός και εύκολα αναγνώσιμος.
+
+
+Αντιγραφή με `clone` .[#toc-copying-with-clone]
+-----------------------------------------------
+
+Στην PHP, μπορούμε να δημιουργήσουμε ένα αντίγραφο ενός αντικειμένου χρησιμοποιώντας τον τελεστή `clone`. Με αυτόν τον τρόπο, λαμβάνουμε μια νέα περίπτωση με πανομοιότυπο περιεχόμενο.
+
+Αν χρειάζεται να τροποποιήσουμε κάποιες από τις ιδιότητές του κατά την αντιγραφή ενός αντικειμένου, μπορούμε να ορίσουμε μια ειδική μέθοδο `__clone()` στην κλάση. Αυτή η μέθοδος καλείται αυτόματα όταν το αντικείμενο κλωνοποιείται.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+Σε αυτό το παράδειγμα, έχουμε μια κλάση `Sheep` με μια ιδιότητα `$name`. Όταν κλωνοποιούμε μια περίπτωση αυτής της κλάσης, η μέθοδος `__clone()` εξασφαλίζει ότι το όνομα του κλωνοποιημένου προβάτου παίρνει το πρόθεμα "Clone of".
+
+
+Χαρακτηριστικά .[#toc-traits]
+-----------------------------
+
+Τα γνωρίσματα στην PHP είναι ένα εργαλείο που επιτρέπει την κοινή χρήση μεθόδων, ιδιοτήτων και σταθερών μεταξύ κλάσεων και αποτρέπει την επανάληψη κώδικα. Μπορείτε να τα φανταστείτε ως ένα μηχανισμό "αντιγραφής και επικόλλησης" (Ctrl-C και Ctrl-V), όπου το περιεχόμενο ενός γνωρίσματος "επικολλάται" σε κλάσεις. Αυτό σας επιτρέπει να επαναχρησιμοποιείτε κώδικα χωρίς να χρειάζεται να δημιουργείτε περίπλοκες ιεραρχίες κλάσεων.
+
+Ας ρίξουμε μια ματιά σε ένα απλό παράδειγμα χρήσης των traits στην PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+Σε αυτό το παράδειγμα, έχουμε ένα trait με όνομα `Honking` που περιέχει μία μέθοδο `honk()`. Στη συνέχεια, έχουμε δύο κλάσεις: `Car` και `Truck`, οι οποίες χρησιμοποιούν το χαρακτηριστικό `Honking`. Ως αποτέλεσμα, και οι δύο κλάσεις "έχουν" τη μέθοδο `honk()` και μπορούμε να την καλέσουμε σε αντικείμενα και των δύο κλάσεων.
+
+Τα γνωρίσματα σας επιτρέπουν να μοιράζεστε εύκολα και αποτελεσματικά κώδικα μεταξύ κλάσεων. Δεν εισέρχονται στην ιεραρχία κληρονομικότητας, δηλαδή το `$car instanceof Honking` θα επιστρέψει το `false`.
+
+
+Εξαιρέσεις
+----------
+
+Οι εξαιρέσεις στην OOP μας επιτρέπουν να χειριζόμαστε με αξιοπρέπεια σφάλματα και απροσδόκητες καταστάσεις στον κώδικά μας. Πρόκειται για αντικείμενα που μεταφέρουν πληροφορίες σχετικά με ένα σφάλμα ή μια ασυνήθιστη κατάσταση.
+
+Στην PHP, έχουμε μια ενσωματωμένη κλάση `Exception`, η οποία χρησιμεύει ως βάση για όλες τις εξαιρέσεις. Αυτή διαθέτει διάφορες μεθόδους που μας επιτρέπουν να λάβουμε περισσότερες πληροφορίες σχετικά με την εξαίρεση, όπως το μήνυμα σφάλματος, το αρχείο και τη γραμμή όπου συνέβη το σφάλμα κ.λπ.
+
+Όταν εμφανίζεται ένα σφάλμα στον κώδικα, μπορούμε να "πετάξουμε" την εξαίρεση χρησιμοποιώντας τη λέξη-κλειδί `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Όταν η συνάρτηση `division()` λαμβάνει null ως δεύτερο όρισμά της, εκπέμπει μια εξαίρεση με το μήνυμα σφάλματος `'Division by zero!'`. Για να αποτρέψουμε τη συντριβή του προγράμματος όταν εκπέμπεται η εξαίρεση, την παγιδεύουμε στο μπλοκ `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Ο κώδικας που μπορεί να πετάξει μια εξαίρεση τυλίγεται σε ένα μπλοκ `try`. Αν η εξαίρεση εκτοξευτεί, η εκτέλεση του κώδικα μεταφέρεται σε ένα μπλοκ `catch`, όπου μπορούμε να χειριστούμε την εξαίρεση (π.χ. να γράψουμε ένα μήνυμα σφάλματος).
+
+Μετά τα μπλοκ `try` και `catch`, μπορούμε να προσθέσουμε ένα προαιρετικό μπλοκ `finally`, το οποίο εκτελείται πάντα, ανεξάρτητα από το αν η εξαίρεση προκλήθηκε ή όχι (ακόμη και αν χρησιμοποιήσουμε τα μπλοκ `return`, `break` ή `continue` στο μπλοκ `try` ή `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Μπορούμε επίσης να δημιουργήσουμε τις δικές μας κλάσεις εξαιρέσεων (ιεραρχία) που κληρονομούν από την κλάση Exception. Ως παράδειγμα, θεωρήστε μια απλή τραπεζική εφαρμογή που επιτρέπει καταθέσεις και αναλήψεις:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Μπορούν να καθοριστούν πολλαπλά μπλοκ `catch` για ένα μόνο μπλοκ `try`, εάν περιμένετε διαφορετικούς τύπους εξαιρέσεων.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+Σε αυτό το παράδειγμα, είναι σημαντικό να σημειωθεί η σειρά των μπλοκ `catch`. Δεδομένου ότι όλες οι εξαιρέσεις κληρονομούν από το `BankingException`, αν είχαμε αυτό το μπλοκ πρώτο, όλες οι εξαιρέσεις θα συλλαμβάνονταν σε αυτό χωρίς ο κώδικας να φτάσει στα επόμενα μπλοκ `catch`. Επομένως, είναι σημαντικό να έχουμε πιο συγκεκριμένες εξαιρέσεις (δηλαδή αυτές που κληρονομούν από άλλες) πιο ψηλά στη σειρά των μπλοκ `catch` από τις εξαιρέσεις των γονέων τους.
+
+
+Επαναλήψεις .[#toc-iterations]
+------------------------------
+
+Στην PHP, μπορείτε να διατρέχετε αντικείμενα με τη χρήση του βρόχου `foreach`, όπως ακριβώς κάνετε βρόχο σε έναν πίνακα. Για να λειτουργήσει αυτό, το αντικείμενο πρέπει να υλοποιεί μια ειδική διεπαφή.
+
+Η πρώτη επιλογή είναι να υλοποιήσετε τη διεπαφή `Iterator`, η οποία έχει τις μεθόδους `current()` που επιστρέφουν την τρέχουσα τιμή, `key()` που επιστρέφουν το κλειδί, `next()` που μεταβαίνουν στην επόμενη τιμή, `rewind()` που μεταβαίνουν στην αρχή και `valid()` που ελέγχουν αν έχουμε φτάσει στο τέλος.
+
+Η άλλη επιλογή είναι να υλοποιήσουμε μια διεπαφή `IteratorAggregate`, η οποία έχει μόνο μια μέθοδο `getIterator()`. Αυτή είτε επιστρέφει ένα αντικείμενο τοποθέτησης που θα παρέχει τη διάσχιση, είτε μπορεί να είναι μια γεννήτρια, η οποία είναι μια ειδική συνάρτηση που χρησιμοποιεί το `yield` για να επιστρέφει διαδοχικά τα κλειδιά και τις τιμές:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Βέλτιστες πρακτικές .[#toc-best-practices]
+------------------------------------------
+
+Μόλις μάθετε τις βασικές αρχές του αντικειμενοστραφούς προγραμματισμού, είναι ζωτικής σημασίας να εστιάσετε στις βέλτιστες πρακτικές του OOP. Αυτές θα σας βοηθήσουν να γράψετε κώδικα που δεν είναι μόνο λειτουργικός αλλά και ευανάγνωστος, κατανοητός και εύκολα συντηρήσιμος.
+
+1) **Διαχωρισμός των ανησυχιών**: Κάθε κλάση θα πρέπει να έχει σαφώς καθορισμένη ευθύνη και να ασχολείται μόνο με μία πρωταρχική εργασία. Αν μια κλάση κάνει πάρα πολλά πράγματα, ίσως είναι σκόπιμο να τη χωρίσετε σε μικρότερες, εξειδικευμένες κλάσεις.
+2) **Ενθυλάκωση**: Τα δεδομένα και οι μέθοδοι θα πρέπει να είναι όσο το δυνατόν πιο κρυφά και προσβάσιμα μόνο μέσω μιας καθορισμένης διεπαφής. Αυτό σας επιτρέπει να αλλάξετε την εσωτερική υλοποίηση μιας κλάσης χωρίς να επηρεάζεται ο υπόλοιπος κώδικας.
+3) **Έγχυση εξάρτησης**: Αντί να δημιουργείτε εξαρτήσεις απευθείας μέσα σε μια κλάση, θα πρέπει να τις "εγχέετε" από έξω. Για μια βαθύτερη κατανόηση αυτής της αρχής, σας συνιστούμε τα [κεφάλαια για το Dependency Injection |dependency-injection:introduction].
diff --git a/nette/el/troubleshooting.texy b/nette/el/troubleshooting.texy
index 1601a2e3fa..ffdd42680e 100644
--- a/nette/el/troubleshooting.texy
+++ b/nette/el/troubleshooting.texy
@@ -18,7 +18,7 @@
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // τη διεύθυνση IP σας
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ $configurator->enableTracy($appDir . '/log');
 Όταν όλες οι σελίδες (εκτός από την αρχική σελίδα) επιστρέφουν ένα σφάλμα 404, φαίνεται ότι υπάρχει πρόβλημα διαμόρφωσης του διακομιστή για τις [όμορφες διευθύνσεις URL |#How to Configure a Server for Nice URLs?].
 
 
+Πώς να απενεργοποιήσετε την προσωρινή μνήμη cache κατά τη διάρκεια της ανάπτυξης; .[#toc-how-to-disable-cache-during-development]
+---------------------------------------------------------------------------------------------------------------------------------
+Το Nette είναι έξυπνο και δεν χρειάζεται να απενεργοποιήσετε την προσωρινή αποθήκευση σε αυτό. Κατά τη διάρκεια της ανάπτυξης, ενημερώνει αυτόματα την κρυφή μνήμη κάθε φορά που υπάρχει μια αλλαγή στο πρότυπο ή στη διαμόρφωση του DI container. Επιπλέον, η λειτουργία ανάπτυξης ενεργοποιείται με αυτόματη ανίχνευση, οπότε συνήθως δεν χρειάζεται να ρυθμίσετε τίποτα [ή μόνο τη διεύθυνση IP |application:bootstrap#development-vs-production-mode].
+
+Κατά την αποσφαλμάτωση του δρομολογητή, συνιστούμε την απενεργοποίηση της προσωρινής μνήμης του προγράμματος περιήγησης, όπου, για παράδειγμα, ενδέχεται να αποθηκεύονται οι ανακατευθύνσεις: ανοίξτε τα Εργαλεία ανάπτυξης (Ctrl+Shift+I ή Cmd+Option+I) και στον πίνακα Δίκτυο, τσεκάρετε το πλαίσιο για την απενεργοποίηση της προσωρινής μνήμης.
+
+
 Σφάλμα `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Αυτό το σφάλμα εμφανίζεται αν έχετε αναβαθμίσει την PHP στην έκδοση 8.1 αλλά χρησιμοποιείτε τη Nette, η οποία δεν είναι συμβατή με αυτήν. Έτσι, η λύση είναι να ενημερώσετε τη Nette σε μια νεότερη έκδοση χρησιμοποιώντας το `composer update`. Η Nette υποστηρίζει την PHP 8.1 από την έκδοση 3.0. Αν χρησιμοποιείτε παλαιότερη έκδοση (μπορείτε να το διαπιστώσετε αναζητώντας στο `composer.json`), [αναβαθμίστε το Nette |migrations:en] ή μείνετε με την PHP 8.0.
@@ -67,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on
 
 Για να εκτελέσετε την εφαρμογή στη φιλοξενία, πρέπει να ορίσετε το document-root σε αυτόν τον κατάλογο στη διαμόρφωση της φιλοξενίας. Ή, αν η φιλοξενία έχει έναν προκαθορισμένο φάκελο για τον δημόσιο κατάλογο με διαφορετικό όνομα (για παράδειγμα `web`, `public_html` κ.λπ.), απλά μετονομάστε τον σε `www/`.
 
-Η λύση **δεν** είναι να "ξεφορτωθείτε" το φάκελο `www/` χρησιμοποιώντας κανόνες στο αρχείο `.htaccess` ή στο δρομολογητή. Αν η φιλοξενία δεν σας επιτρέπει να ορίσετε το document-root σε υποκατάλογο (δηλ. να δημιουργήσετε καταλόγους ένα επίπεδο πάνω από τον δημόσιο κατάλογο), αναζητήστε άλλον. Διαφορετικά, θα αναλάβετε ένα σημαντικό ρίσκο ασφάλειας. Θα ήταν σαν να ζείτε σε ένα διαμέρισμα όπου δεν μπορείτε να κλείσετε την εξώπορτα και είναι πάντα ορθάνοιχτη.
+Η λύση **δεν** είναι να αποτρέψετε την πρόσβαση σε όλους τους φακέλους εκτός από το `www/` χρησιμοποιώντας κανόνες στο αρχείο `.htaccess` ή στο δρομολογητή. Αν η φιλοξενία σας δεν επιτρέπει τον ορισμό της ρίζας του εγγράφου σε υποκατάλογο (δηλαδή τη δημιουργία καταλόγων ένα επίπεδο πάνω από τον δημόσιο κατάλογο), θα πρέπει να αναζητήσετε μια άλλη υπηρεσία φιλοξενίας. Διαφορετικά, θα εκτεθείτε σε σημαντικούς κινδύνους ασφαλείας. Θα ήταν σαν να ζείτε σε ένα διαμέρισμα όπου η μπροστινή πόρτα δεν μπορεί να κλείσει και είναι πάντα ορθάνοιχτη.
 
 
 Πώς να διαμορφώσετε έναν διακομιστή για ωραίες διευθύνσεις URL; .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/en/@home.texy b/nette/en/@home.texy
index 2fe80a3dab..b2d2e5c09a 100644
--- a/nette/en/@home.texy
+++ b/nette/en/@home.texy
@@ -84,11 +84,11 @@ Utilities
 - [utils:JSON]
 - [NEON|neon:]
 - [Password Hashing |security:passwords]
-- [utils:SmartObject]
 - [PHP Types |utils:type]
 - [utils:Strings]
 - [Validators |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...others |utils:]
 </div>
diff --git a/nette/en/installation.texy b/nette/en/installation.texy
index 016f177da7..0dfea8fadb 100644
--- a/nette/en/installation.texy
+++ b/nette/en/installation.texy
@@ -20,7 +20,7 @@ Nette offers a collection of useful and sophisticated packages (libraries) for P
 composer require nette/utils
 ```
 
-Do you prefer a graphical interface? Check out the [guide|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] on installing packages in the PhpStrom environment.
+Do you prefer a graphical interface? Check out the [guide|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] on installing packages in the PhpStorm environment.
 
 
 How to Start a New Project with Nette
diff --git a/nette/en/introduction-to-object-oriented-programming.texy b/nette/en/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..f8be46baf1
--- /dev/null
+++ b/nette/en/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Introduction to Object-Oriented Programming
+*******************************************
+
+.[perex]
+The term "OOP" stands for Object-Oriented Programming, which is a way to organize and structure code. OOP allows us to view a program as a collection of objects that communicate with each other, rather than a sequence of commands and functions.
+
+In OOP, an "object" is a unit that contains data and functions that operate on that data. Objects are created based on "classes", which can be understood as blueprints or templates for objects. Once we have a class, we can create its "instance", which is a specific object made from that class.
+
+Let's look at how we can create a simple class in PHP. When defining a class, we use the keyword "class", followed by the class name, and then curly braces that enclose the class's functions (called "methods") and class variables (called "properties" or "attributes"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+In this example, we've created a class named `Car` with one function (or "method") called `honk`.
+
+Each class should solve only one main task. If a class is doing too many things, it may be appropriate to divide it into smaller, specialized classes.
+
+Classes are typically stored in separate files to keep the code organized and easy to navigate. The file name should match the class name, so for the `Car` class, the file name would be `Car.php`.
+
+When naming classes, it's good to follow the "PascalCase" convention, meaning each word in the name starts with a capital letter, and there are no underscores or other separators. Methods and properties follow the "camelCase" convention, meaning they start with a lowercase letter.
+
+Some methods in PHP have special roles and are prefixed with `__` (two underscores). One of the most important special methods is the "constructor", labeled as `__construct`. The constructor is a method that's automatically called when creating a new instance of a class.
+
+We often use the constructor to set the initial state of an object. For example, when creating an object representing a person, you might use the constructor to set their age, name, or other attributes.
+
+Let's see how to use a constructor in PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+In this example, the `Person` class has a property (variable) `$age` and a constructor that sets this property. The `howOldAreYou()` method then provides access to the person's age.
+
+The `$this` pseudo-variable is used inside the class to access the properties and methods of the object.
+
+The `new` keyword is used to create a new instance of a class. In the example above, we created a new person aged 25.
+
+You can also set default values for constructor parameters if they aren't specified when creating an object. For instance:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+In this example, if you don't specify an age when creating a `Person` object, the default value of 20 will be used.
+
+The nice thing is that the property definition with its initialization via the constructor can be shortened and simplified like this:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+For completeness, in addition to constructors, objects can have destructors (method `__destruct`) that are called before the object is released from memory.
+
+
+Namespaces
+----------
+
+Namespaces allow us to organize and group related classes, functions, and constants while avoiding naming conflicts. You can think of them like folders on a computer, where each folder contains files related to a specific project or topic.
+
+Namespaces are especially useful in larger projects or when using third-party libraries where class naming conflicts might arise.
+
+Imagine you have a class named `Car` in your project, and you want to place it in a namespace called `Transport`. You would do it like this:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+If you want to use the `Car` class in another file, you need to specify from which namespace the class originates:
+
+```php
+$car = new Transport\Car;
+```
+
+For simplification, you can specify at the beginning of the file which class from a particular namespace you want to use, allowing you to create instances without mentioning the full path:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Inheritance
+-----------
+
+Inheritance is a tool of object-oriented programming that allows the creation of new classes based on existing ones, inheriting their properties and methods, and extending or redefining them as needed. Inheritance ensures code reusability and class hierarchy.
+
+Simply put, if we have one class and want to create another derived from it but with some modifications, we can "inherit" the new class from the original one.
+
+In PHP, inheritance is implemented using the `extends` keyword.
+
+Our `Person` class stores age information. We can have another class, `Student`, which extends `Person` and adds information about the field of study.
+
+Let's look at an example:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+How does this code work?
+
+- We used the `extends` keyword to extend the `Person` class, meaning the `Student` class inherits all methods and properties from `Person`.
+
+- The `parent::` keyword allows us to call methods from the parent class. In this case, we called the constructor from the `Person` class before adding our own functionality to the `Student` class. And similarly, the `printInformation()` ancestor method before listing the student information.
+
+Inheritance is meant for situations where there's an "is a" relationship between classes. For instance, a `Student` is a `Person`. A cat is an animal. It allows us in cases where we expect one object (e.g., "Person") in the code to use a derived object instead (e.g., "Student").
+
+It's essential to realize that the primary purpose of inheritance **is not** to prevent code duplication. On the contrary, misuse of inheritance can lead to complex and hard-to-maintain code. If there's no "is a" relationship between classes, we should consider composition instead of inheritance.
+
+Note that the `printInformation()` methods in the `Person` and `Student` classes output slightly different information. And we can add other classes (such as `Employee`) that will provide other implementations of this method. The ability of objects of different classes to respond to the same method in different ways is called polymorphism:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Composition
+-----------
+
+Composition is a technique where, instead of inheriting properties and methods from another class, we simply use its instance in our class. This allows us to combine functionalities and properties of multiple classes without creating complex inheritance structures.
+
+For example, we have a `Engine` class and a `Car` class. Instead of saying "A car is an engine", we say "A car has an engine", which is a typical composition relationship.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Here, the `Car` doesn't have all the properties and methods of the `Engine`, but it has access to it through the `$engine` property.
+
+The advantage of composition is greater design flexibility and better adaptability for future changes.
+
+
+Visibility
+----------
+
+In PHP, you can define "visibility" for class properties, methods, and constants. Visibility determines where you can access these elements.
+
+1. **Public:** If an element is marked as `public`, it means you can access it from anywhere, even outside the class.
+
+2. **Protected:** An element marked as `protected` is accessible only within the class and all its descendants (classes that inherit from it).
+
+3. **Private:** If an element is `private`, you can access it only from within the class where it was defined.
+
+If you don't specify visibility, PHP will automatically set it to `public`.
+
+Let's look at a sample code:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Continuing with class inheritance:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+In this case, the `printProperties()` method in the `ChildClass` can access the public and protected properties but cannot access the private properties of the parent class.
+
+Data and methods should be as hidden as possible and only accessible through a defined interface. This allows you to change the internal implementation of the class without affecting the rest of the code.
+
+
+Final Keyword
+-------------
+
+In PHP, we can use the `final` keyword if we want to prevent a class, method, or constant from being inherited or overridden. When a class is marked as `final`, it cannot be extended. When a method is marked as `final`, it cannot be overridden in a subclass.
+
+Being aware that a certain class or method will no longer be modified allows us to make changes more easily without worrying about potential conflicts. For example, we can add a new method without fear that a descendant might already have a method with the same name, leading to a collision. Or we can change the parameters of a method, again without the risk of causing inconsistency with an overridden method in a descendant.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+In this example, attempting to inherit from the final class `FinalClass` will result in an error.
+
+
+Static Properties and Methods
+-----------------------------
+
+When we talk about "static" elements of a class in PHP, we mean methods and properties that belong to the class itself, not to a specific instance of the class. This means that you don't have to create an instance of the class to access them. Instead, you call or access them directly through the class name.
+
+Keep in mind that since static elements belong to the class and not its instances, you cannot use the `$this` pseudo-variable inside static methods.
+
+Using static properties leads to [obfuscated code full of pitfalls|dependency-injection:global-state], so you should never use them, and we won't show an example here. On the other hand, static methods are useful. Here's an example:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+In this example, we created a `Calculator` class with two static methods. We can call these methods directly without creating an instance of the class using the `::` operator. Static methods are especially useful for operations that don't depend on the state of a specific class instance.
+
+
+Class Constants
+---------------
+
+Within classes, we have the option to define constants. Constants are values that never change during the program's execution. Unlike variables, the value of a constant remains the same.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+In this example, we have a `Car` class with the `NumberOfWheels` constant. When accessing the constant inside the class, we can use the `self` keyword instead of the class name.
+
+
+Object Interfaces
+-----------------
+
+Object interfaces act as "contracts" for classes. If a class is to implement an object interface, it must contain all the methods that the interface defines. It's a great way to ensure that certain classes adhere to the same "contract" or structure.
+
+In PHP, interfaces are defined using the `interface` keyword. All methods defined in an interface are public (`public`). When a class implements an interface, it uses the `implements` keyword.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+If a class implements an interface, but not all expected methods are defined, PHP will throw an error.
+
+A class can implement multiple interfaces at once, which is different from inheritance, where a class can only inherit from one class:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Abstract Classes
+----------------
+
+Abstract classes serve as base templates for other classes, but you cannot create their instances directly. They contain a mix of complete methods and abstract methods that don't have a defined content. Classes that inherit from abstract classes must provide definitions for all the abstract methods from the parent.
+
+We use the `abstract` keyword to define an abstract class.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+In this example, we have an abstract class with one regular and one abstract method. Then we have a `Child` class that inherits from `AbstractClass` and provides an implementation for the abstract method.
+
+How are interfaces and abstract classes different? Abstract classes can contain both abstract and concrete methods, while interfaces only define what methods the class must implement, but provide no implementation. A class can inherit from only one abstract class, but can implement any number of interfaces.
+
+
+Type Checking
+-------------
+
+In programming, it's crucial to ensure that the data we work with is of the correct type. In PHP, we have tools that provide this assurance. Verifying that data is of the correct type is called "type checking."
+
+Types we might encounter in PHP:
+
+1. **Basic types**: These include `int` (integers), `float` (floating-point numbers), `bool` (boolean values), `string` (strings), `array` (arrays), and `null`.
+2. **Classes**: When we want a value to be an instance of a specific class.
+3. **Interfaces**: Defines a set of methods that a class must implement. A value that meets an interface must have these methods.
+4. **Mixed types**: We can specify that a variable can have multiple allowed types.
+5. **Void**: This special type indicates that a function or method does not return any value.
+
+Let's see how to modify the code to include types:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+In this way, we ensure that our code expects and works with data of the correct type, helping us prevent potential errors.
+
+Some types cannot be written directly in PHP. In this case, they are listed in the phpDoc comment, which is the standard format for documenting PHP code, starting with `/**` and ending with `*/`. It allows you to add descriptions of classes, methods, and so on. And also to list complex types using so-called annotations `@var`, `@param` and `@return`. These types are then used by static code analysis tools, but are not checked by PHP itself.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Comparison and Identity
+-----------------------
+
+In PHP, you can compare objects in two ways:
+
+1. Value comparison `==`: Checks if the objects are of the same class and have the same values in their properties.
+2. Identity `===`: Checks if it's the same instance of the object.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+The `instanceof` Operator
+-------------------------
+
+The `instanceof` operator allows you to determine if a given object is an instance of a specific class, a descendant of that class, or if it implements a certain interface.
+
+Imagine we have a class `Person` and another class `Student`, which is a descendant of `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+From the outputs, it's evident that the `$student` object is considered an instance of both the `Student` and `Person` classes.
+
+
+Fluent Interfaces
+-----------------
+
+A "Fluent Interface" is a technique in OOP that allows chaining methods together in a single call. This often simplifies and clarifies the code.
+
+The key element of a fluent interface is that each method in the chain returns a reference to the current object. This is achieved by using `return $this;` at the end of the method. This programming style is often associated with methods called "setters", which set the values of an object's properties.
+
+Let's see what a fluent interface might look like for sending emails:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+In this example, the methods `setFrom()`, `setRecipient()`, and `setMessage()` are used to set the corresponding values (sender, recipient, message content). After setting each of these values, the methods return the current object (`$email`), allowing us to chain another method after it. Finally, we call the `send()` method, which actually sends the email.
+
+Thanks to fluent interfaces, we can write code that is intuitive and easily readable.
+
+
+Copying with `clone`
+--------------------
+
+In PHP, we can create a copy of an object using the `clone` operator. This way, we get a new instance with identical content.
+
+If we need to modify some of its properties when copying an object, we can define a special `__clone()` method in the class. This method is automatically called when the object is cloned.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+In this example, we have a `Sheep` class with one property `$name`. When we clone an instance of this class, the `__clone()` method ensures that the name of the cloned sheep gets the prefix "Clone of".
+
+
+Traits
+------
+
+Traits in PHP are a tool that allows sharing methods, properties and constants between classes and prevents code duplication. You can think of them as a "copy and paste" mechanism (Ctrl-C and Ctrl-V), where the content of a trait is "pasted" into classes. This allows you to reuse code without having to create complicated class hierarchies.
+
+Let's take a look at a simple example of how to use traits in PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+In this example, we have a trait named `Honking` that contains one method `honk()`. Then we have two classes: `Car` and `Truck`, both of which use the `Honking` trait. As a result, both classes "have" the `honk()` method, and we can call it on objects of both classes.
+
+Traits allow you to easily and efficiently share code between classes. They do not enter the inheritance hierarchy, i.e., `$car instanceof Honking` will return `false`.
+
+
+Exceptions
+----------
+
+Exceptions in OOP allow us to gracefully handle errors and unexpected situations in our code. They are objects that carry information about an error or unusual situation.
+
+In PHP, we have a built-in class `Exception`, which serves as the basis for all exceptions. This has several methods that allow us to get more information about the exception, such as the error message, the file and line where the error occurred, etc.
+
+When an error occurs in the code, we can "throw" the exception using the `throw` keyword.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+When the `division()` function receives null as its second argument, it throws an exception with the error message `'Division by zero!'`. To prevent the program from crashing when the exception is thrown, we trap it in the `try/catch` block:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Code that can throw an exception is wrapped in a block `try`. If the exception is thrown, the code execution moves to a block `catch`, where we can handle the exception (e.g., write an error message).
+
+After the `try` and `catch` blocks, we can add an optional block `finally`, which is always executed whether the exception was thrown or not (even if we use `return`, `break`, or `continue` in the `try` or `catch` block):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+We can also create our own exception classes (hierarchy) that inherit from the Exception class. As an example, consider a simple banking application that allows deposits and withdrawals:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Multiple `catch` blocks can be specified for a single `try` block if you expect different types of exceptions.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+In this example, it's important to note the order of the `catch` blocks. Since all exceptions inherit from `BankingException`, if we had this block first, all exceptions would be caught in it without the code reaching the subsequent `catch` blocks. Therefore, it's important to have more specific exceptions (i.e., those that inherit from others) higher in the `catch` block order than their parent exceptions.
+
+
+Iterations
+----------
+
+In PHP, you can loop through objects using the `foreach` loop, much like you loop through an array. For this to work, the object must implement a special interface.
+
+The first option is to implement the interface `Iterator`, which has methods `current()` returning the current value, `key()` returning the key, `next()` moving to the next value, `rewind()` moving to the beginning, and `valid()` checking to see if we're at the end yet.
+
+The other option is to implement an interface `IteratorAggregate`, which has only one method `getIterator()`. This either returns a placeholder object that will provide the traversal, or it can be a generator, which is a special function that uses `yield` to return keys and values sequentially:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Best Practices
+--------------
+
+Once you have the basic principles of object-oriented programming under your belt, it's crucial to focus on best practices in OOP. These will help you write code that is not only functional but also readable, understandable, and easily maintainable.
+
+1) **Separation of Concerns**: Each class should have a clearly defined responsibility and should address only one primary task. If a class does too many things, it might be appropriate to split it into smaller, specialized classes.
+2) **Encapsulation**: Data and methods should be as hidden as possible and accessible only through a defined interface. This allows you to change the internal implementation of a class without affecting the rest of the code.
+3) **Dependency Injection**: Instead of creating dependencies directly within a class, you should "inject" them from the outside. For a deeper understanding of this principle, we recommend the [chapters on Dependency Injection|dependency-injection:introduction].
diff --git a/nette/en/troubleshooting.texy b/nette/en/troubleshooting.texy
index da18381275..70b0b650bd 100644
--- a/nette/en/troubleshooting.texy
+++ b/nette/en/troubleshooting.texy
@@ -18,7 +18,7 @@ You can always find the reason for the error in the `log/` directory. However, i
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // your IP address
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Error 404, Routing Not Working
 When all pages (except the homepage) return a 404 error, it looks like a server configuration problem for [pretty URLs |#How to Configure a Server for Nice URLs?].
 
 
+How to Disable Cache During Development?
+----------------------------------------
+Nette is smart, and you don't need to disable caching in it. During development, it automatically updates the cache whenever there's a change in the template or the DI container configuration. Moreover, the development mode is activated by auto-detection, so there's usually no need to configure anything, [or just the IP address |application:bootstrap#development-vs-production-mode].
+
+When debugging the router, we recommend disabling the browser cache, where, for example, redirects might be stored: open Developer Tools (Ctrl+Shift+I or Cmd+Option+I) and in the Network panel, check the box to disable the cache.
+
+
 Error `#[\ReturnTypeWillChange] attribute should be used`
 ---------------------------------------------------------
 This error occurs if you have upgraded PHP to version 8.1 but are using Nette, which is not compatible with it. So the solution is to update Nette to a newer version using `composer update`. Nette has supported PHP 8.1 since version 3.0. If you are using an older version (you can find out by looking in `composer.json`), [upgrade Nette |migrations:] or stay with PHP 8.0.
@@ -67,7 +74,7 @@ The `www/` directory used in the sample projects in Nette is the so-called publi
 
 To run the application on the hosting, you need to set the document-root to this directory in the hosting configuration. Or, if the hosting has a pre-made folder for the public directory with a different name (for example `web`, `public_html` etc.), simply rename `www/`.
 
-The solution **isn't** to "get rid" of the `www/` folder using rules in the `.htaccess` file or in the router. If the hosting would not allow you to set document-root to a subdirectory (i.e. create directories one level above the public directory), look for another. You would otherwise be taking a significant security risk. It would be like living in an apartment where you can't close the front door and it's always wide open.
+The solution **is not** to prevent access to all folders except `www/` using rules in the `.htaccess` file or in the router. If your hosting does not allow setting the document root to a subdirectory (i.e., creating directories a level above the public directory), you should look for a different hosting service. Otherwise, you would be exposing yourself to significant security risks. It would be like living in an apartment where the front door cannot be closed and is always wide open.
 
 
 How to Configure a Server for Nice URLs?
diff --git a/nette/en/vulnerability-protection.texy b/nette/en/vulnerability-protection.texy
index 0eedf7cade..f5e8f5c88f 100644
--- a/nette/en/vulnerability-protection.texy
+++ b/nette/en/vulnerability-protection.texy
@@ -59,12 +59,12 @@ public function handleXyz()
 }
 ```
 
-In PHP 8, you can also use attributes:
+In Nette Application 3.2 you can also use attributes:
 
 ```php
-use Nette\Application\Attributes\CrossOrigin;
+use Nette\Application\Attributes\Requires;
 
-#[CrossOrigin]
+#[Requires(sameOrigin: false)]
 public function handleXyz()
 {
 }
diff --git a/nette/es/@home.texy b/nette/es/@home.texy
index c6644ab4c5..0a57b34965 100644
--- a/nette/es/@home.texy
+++ b/nette/es/@home.texy
@@ -84,11 +84,11 @@ Utilidades
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hashing de contraseñas |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Tipos de PHP |utils:type]
 - [Cadenas |utils:Strings]
 - [Validadores |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - ... [otros |utils:]
 </div>
diff --git a/nette/es/installation.texy b/nette/es/installation.texy
index 4690a5a0f3..4394de8f6a 100644
--- a/nette/es/installation.texy
+++ b/nette/es/installation.texy
@@ -20,7 +20,7 @@ Nette ofrece una colección de paquetes (librerías) útiles y sofisticados para
 composer require nette/utils
 ```
 
-¿Prefieres una interfaz gráfica? Consulta la [guía |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalación de paquetes en el entorno PhpStrom.
+¿Prefieres una interfaz gráfica? Consulta la [guía |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalación de paquetes en el entorno PhpStorm.
 
 
 Cómo iniciar un nuevo proyecto con Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/es/introduction-to-object-oriented-programming.texy b/nette/es/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..e60ec556b6
--- /dev/null
+++ b/nette/es/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Introducción a la programación orientada a objetos
+**************************************************
+
+.[perex]
+El término "POO" significa Programación Orientada a Objetos, que es una forma de organizar y estructurar el código. La POO nos permite ver un programa como una colección de objetos que se comunican entre sí, en lugar de como una secuencia de comandos y funciones.
+
+En la programación orientada a objetos, un "objeto" es una unidad que contiene datos y funciones que operan con esos datos. Los objetos se crean a partir de "clases", que pueden entenderse como planos o plantillas de objetos. Una vez que tenemos una clase, podemos crear su "instancia", que es un objeto específico hecho a partir de esa clase.
+
+Veamos cómo podemos crear una clase simple en PHP. Cuando definimos una clase, usamos la palabra clave "class", seguida del nombre de la clase, y luego llaves que encierran las funciones de la clase (llamadas "métodos") y las variables de la clase (llamadas "propiedades" o "atributos"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+En este ejemplo, hemos creado una clase llamada `Car` con una función (o "método") llamada `honk`.
+
+Cada clase debe resolver una sola tarea principal. Si una clase hace demasiadas cosas, puede ser conveniente dividirla en clases más pequeñas y especializadas.
+
+Las clases suelen almacenarse en archivos separados para mantener el código organizado y facilitar la navegación. El nombre del archivo debe coincidir con el nombre de la clase, por lo que para la clase `Car`, el nombre del archivo sería `Car.php`.
+
+Cuando se nombran las clases, es bueno seguir la convención "PascalCase", lo que significa que cada palabra en el nombre comienza con una letra mayúscula, y no hay guiones bajos u otros separadores. Los métodos y propiedades siguen la convención "camelCase", lo que significa que empiezan con minúscula.
+
+Algunos métodos en PHP tienen roles especiales y están prefijados con `__` (dos guiones bajos). Uno de los métodos especiales más importantes es el "constructor", etiquetado como `__construct`. El constructor es un método que es llamado automáticamente cuando se crea una nueva instancia de una clase.
+
+A menudo utilizamos el constructor para establecer el estado inicial de un objeto. Por ejemplo, al crear un objeto que representa a una persona, puedes utilizar el constructor para establecer su edad, nombre u otros atributos.
+
+Veamos como usar un constructor en PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+En este ejemplo, la clase `Person` tiene una propiedad (variable) `$age` y un constructor que establece esta propiedad. A continuación, el método `howOldAreYou()` proporciona acceso a la edad de la persona.
+
+La pseudo-variable `$this` se utiliza dentro de la clase para acceder a las propiedades y métodos del objeto.
+
+La palabra clave `new` se utiliza para crear una nueva instancia de una clase. En el ejemplo anterior, hemos creado una nueva persona de 25 años.
+
+También puedes establecer valores por defecto para los parámetros del constructor si no se especifican al crear un objeto. Por ejemplo:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+En este ejemplo, si no se especifica una edad al crear un objeto `Person`, se utilizará el valor por defecto de 20.
+
+Lo bueno es que la definición de la propiedad con su inicialización a través del constructor se puede acortar y simplificar así:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Para completar, además de constructores, los objetos pueden tener destructores (método `__destruct`) que son llamados antes de que el objeto sea liberado de la memoria.
+
+
+Espacios de nombres .[#toc-namespaces]
+--------------------------------------
+
+Los espacios de nombres nos permiten organizar y agrupar clases, funciones y constantes relacionadas evitando conflictos de nombres. Puedes pensar en ellos como carpetas en un ordenador, donde cada carpeta contiene archivos relacionados con un proyecto o tema específico.
+
+Los espacios de nombres son especialmente útiles en proyectos grandes o cuando se utilizan librerías de terceros donde pueden surgir conflictos de nombres de clases.
+
+Imagina que tienes una clase llamada `Car` en tu proyecto, y quieres colocarla en un espacio de nombres llamado `Transport`. Lo harías de la siguiente manera
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Si quieres utilizar la clase `Car` en otro archivo, tienes que especificar de qué espacio de nombres procede la clase:
+
+```php
+$car = new Transport\Car;
+```
+
+Para simplificar, puede especificar al principio del archivo qué clase de un espacio de nombres concreto desea utilizar, lo que le permitirá crear instancias sin mencionar la ruta completa:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Herencia .[#toc-inheritance]
+----------------------------
+
+La herencia es una herramienta de la programación orientada a objetos que permite crear nuevas clases a partir de otras ya existentes, heredando sus propiedades y métodos, y ampliándolas o redefiniéndolas según sea necesario. La herencia garantiza la reutilización del código y la jerarquía de las clases.
+
+En pocas palabras, si tenemos una clase y queremos crear otra derivada de ella pero con algunas modificaciones, podemos "heredar" la nueva clase de la original.
+
+En PHP, la herencia se implementa utilizando la palabra clave `extends`.
+
+Nuestra clase `Person` almacena información sobre la edad. Podemos tener otra clase, `Student`, que extienda `Person` y añada información sobre el campo de estudio.
+
+Veamos un ejemplo:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+¿Cómo funciona este código?
+
+- Utilizamos la palabra clave `extends` para extender la clase `Person`, lo que significa que la clase `Student` hereda todos los métodos y propiedades de `Person`.
+
+- La palabra clave `parent::` nos permite llamar a métodos de la clase padre. En este caso, llamamos al constructor de la clase `Person` antes de añadir nuestra propia funcionalidad a la clase `Student`. Y de forma similar, el método del ancestro `printInformation()` antes de listar la información del estudiante.
+
+La herencia está pensada para situaciones en las que existe una relación "es un" entre clases. Por ejemplo, un `Student` es un `Person`. Un gato es un animal. Nos permite, en casos en los que esperamos un objeto (por ejemplo, "Persona") en el código, utilizar un objeto derivado en su lugar (por ejemplo, "Estudiante").
+
+Es esencial darse cuenta de que el propósito principal de la herencia **no es** evitar la duplicación de código. Al contrario, un mal uso de la herencia puede llevar a un código complejo y difícil de mantener. Si no existe una relación "es un" entre clases, deberíamos considerar la composición en lugar de la herencia.
+
+Observe que los métodos `printInformation()` de las clases `Person` y `Student` proporcionan información ligeramente diferente. Y podemos añadir otras clases (como `Employee`) que proporcionarán otras implementaciones de este método. La capacidad de los objetos de diferentes clases para responder al mismo método de diferentes maneras se llama polimorfismo:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Composición .[#toc-composition]
+-------------------------------
+
+La composición es una técnica en la que, en lugar de heredar propiedades y métodos de otra clase, simplemente utilizamos su instancia en nuestra clase. Esto nos permite combinar funcionalidades y propiedades de múltiples clases sin crear complejas estructuras de herencia.
+
+Por ejemplo, tenemos una clase `Engine` y otra `Car`. En lugar de decir "Un coche es un motor", decimos "Un coche tiene un motor", que es una relación de composición típica.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Aquí, la `Car` no tiene todas las propiedades y métodos de la `Engine`, pero tiene acceso a ella a través de la propiedad `$engine`.
+
+La ventaja de la composición es una mayor flexibilidad de diseño y una mejor adaptabilidad a futuros cambios.
+
+
+Visibilidad .[#toc-visibility]
+------------------------------
+
+En PHP, usted puede definir "visibilidad" para propiedades de clases, métodos y constantes. La visibilidad determina dónde se puede acceder a estos elementos.
+
+1. **Público:** Si un elemento está marcado como `public`, significa que puede acceder a él desde cualquier lugar, incluso fuera de la clase.
+
+2. **Protegido:** Un elemento marcado como `protected` sólo es accesible dentro de la clase y todos sus descendientes (clases que heredan de ella).
+
+3. **Privado:** Si un elemento es `private`, sólo se puede acceder a él desde dentro de la clase en la que se definió.
+
+Si no especifica la visibilidad, PHP la establecerá automáticamente en `public`.
+
+Veamos un ejemplo de código:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Continuando con la herencia de clases:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+En este caso, el método `printProperties()` de `ChildClass` puede acceder a las propiedades públicas y protegidas pero no puede acceder a las propiedades privadas de la clase padre.
+
+Los datos y métodos deben estar lo más ocultos posible y sólo se puede acceder a ellos a través de una interfaz definida. Esto permite cambiar la implementación interna de la clase sin afectar al resto del código.
+
+
+Palabra clave final .[#toc-final-keyword]
+-----------------------------------------
+
+En PHP, podemos usar la palabra clave `final` si queremos evitar que una clase, método o constante sea heredada o sobrescrita. Cuando una clase es marcada como `final`, no puede ser extendida. Cuando un método es marcado como `final`, no puede ser sobrescrito en una subclase.
+
+Ser conscientes de que una determinada clase o método ya no se modificará nos permite realizar cambios más fácilmente sin preocuparnos por posibles conflictos. Por ejemplo, podemos añadir un nuevo método sin temor a que un descendiente pueda tener ya un método con el mismo nombre, provocando una colisión. O podemos cambiar los parámetros de un método, de nuevo sin el riesgo de causar inconsistencia con un método anulado en un descendiente.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+En este ejemplo, si se intenta heredar de la clase final `FinalClass` se producirá un error.
+
+
+Propiedades estáticas y métodos .[#toc-static-properties-and-methods]
+---------------------------------------------------------------------
+
+Cuando hablamos de elementos "estáticos" de una clase en PHP, nos referimos a métodos y propiedades que pertenecen a la clase misma, no a una instancia específica de la clase. Esto significa que no tiene que crear una instancia de la clase para acceder a ellos. En su lugar, se les llama o accede directamente a través del nombre de la clase.
+
+Ten en cuenta que como los elementos estáticos pertenecen a la clase y no a sus instancias, no puedes utilizar la pseudo-variable `$this` dentro de métodos estáticos.
+
+El uso de propiedades estáticas conduce a [código ofuscado lleno de trampas |dependency-injection:global-state], por lo que nunca deberías usarlas, y no mostraremos un ejemplo aquí. Por otro lado, los métodos estáticos son útiles. Aquí tienes un ejemplo:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+En este ejemplo, creamos una clase `Calculator` con dos métodos estáticos. Podemos llamar a estos métodos directamente sin crear una instancia de la clase utilizando el operador `::`. Los métodos estáticos son especialmente útiles para operaciones que no dependen del estado de una instancia específica de la clase.
+
+
+Constantes de clase .[#toc-class-constants]
+-------------------------------------------
+
+Dentro de las clases, tenemos la opción de definir constantes. Las constantes son valores que nunca cambian durante la ejecución del programa. A diferencia de las variables, el valor de una constante permanece igual.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+En este ejemplo, tenemos una clase `Car` con la constante `NumberOfWheels`. Al acceder a la constante dentro de la clase, podemos utilizar la palabra clave `self` en lugar del nombre de la clase.
+
+
+Interfaces de objetos .[#toc-object-interfaces]
+-----------------------------------------------
+
+Las interfaces de objetos actúan como "contratos" para las clases. Si una clase va a implementar una interfaz de objetos, debe contener todos los métodos que la interfaz define. Es una gran manera de asegurar que ciertas clases se adhieren al mismo "contrato" o estructura.
+
+En PHP, las interfaces se definen usando la palabra clave `interface`. Todos los métodos definidos en una interfaz son públicos (`public`). Cuando una clase implementa una interfaz, usa la palabra clave `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Si una clase implementa una interfaz, pero no todos los métodos esperados están definidos, PHP lanzará un error.
+
+Una clase puede implementar múltiples interfaces a la vez, que es diferente de la herencia, donde una clase sólo puede heredar de una clase:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Clases Abstractas .[#toc-abstract-classes]
+------------------------------------------
+
+Las clases abstractas sirven como plantillas base para otras clases, pero no se pueden crear instancias directamente. Contienen una mezcla de métodos completos y métodos abstractos que no tienen un contenido definido. Las clases que heredan de clases abstractas deben proporcionar definiciones para todos los métodos abstractos del padre.
+
+Utilizamos la palabra clave `abstract` para definir una clase abstracta.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+En este ejemplo, tenemos una clase abstracta con un método normal y otro abstracto. Luego tenemos una clase `Child` que hereda de `AbstractClass` y proporciona una implementación para el método abstracto.
+
+¿En qué se diferencian las interfaces de las clases abstractas? Las clases abstractas pueden contener métodos abstractos y concretos, mientras que las interfaces sólo definen qué métodos debe implementar la clase, pero no proporcionan ninguna implementación. Una clase sólo puede heredar de una clase abstracta, pero puede implementar cualquier número de interfaces.
+
+
+Comprobación de tipos .[#toc-type-checking]
+-------------------------------------------
+
+En programación, es crucial asegurarse de que los datos con los que trabajamos son del tipo correcto. En PHP, tenemos herramientas que proporcionan esta seguridad. Verificar que los datos son del tipo correcto se llama "comprobación de tipo".
+
+Tipos que podemos encontrar en PHP:
+
+1. **Tipos básicos**: Estos incluyen `int` (enteros), `float` (números de punto flotante), `bool` (valores booleanos), `string` (cadenas), `array` (matrices), y `null`.
+2. **Clases**: Cuando queremos que un valor sea una instancia de una clase concreta.
+3. **Interfaces**: Define un conjunto de métodos que una clase debe implementar. Un valor que cumpla una interfaz debe tener estos métodos.
+4. **Tipos mixtos**: Podemos especificar que una variable puede tener múltiples tipos permitidos.
+5. **Void**: Este tipo especial indica que una función o método no devuelve ningún valor.
+
+Veamos cómo modificar el código para incluir tipos:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+De esta forma, nos aseguramos de que nuestro código espera y trabaja con datos del tipo correcto, ayudándonos a prevenir posibles errores.
+
+Algunos tipos no pueden escribirse directamente en PHP. En este caso, se listan en el comentario phpDoc, que es el formato estándar para documentar código PHP, comenzando con `/**` y terminando con `*/`. Permite añadir descripciones de clases, métodos, etcétera. Y también listar tipos complejos usando las llamadas anotaciones `@var`, `@param` y `@return`. Estos tipos son luego utilizados por herramientas de análisis estático de código, pero no son comprobados por el propio PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Comparación e identidad .[#toc-comparison-and-identity]
+-------------------------------------------------------
+
+En PHP, puede comparar objetos de dos maneras:
+
+1. Comparación de valores `==`: Comprueba si los objetos son de la misma clase y tienen los mismos valores en sus propiedades.
+2. Identidad `===`: Comprueba si se trata de la misma instancia del objeto.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+El operador `instanceof` .[#toc-the-instanceof-operator]
+--------------------------------------------------------
+
+El operador `instanceof` permite determinar si un objeto dado es una instancia de una clase específica, un descendiente de esa clase o si implementa una determinada interfaz.
+
+Imaginemos que tenemos una clase `Person` y otra clase `Student`, que es descendiente de `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+A partir de las salidas, es evidente que el objeto `$student` se considera una instancia tanto de la clase `Student` como de la clase `Person`.
+
+
+Interfaces fluidas .[#toc-fluent-interfaces]
+--------------------------------------------
+
+Una "interfaz fluida" es una técnica de programación orientada a objetos que permite encadenar métodos en una sola llamada. Esto a menudo simplifica y clarifica el código.
+
+El elemento clave de una interfaz fluida es que cada método de la cadena devuelve una referencia al objeto actual. Esto se consigue utilizando `return $this;` al final del método. Este estilo de programación se asocia a menudo con métodos llamados "setters", que establecen los valores de las propiedades de un objeto.
+
+Veamos cómo sería una interfaz fluida para enviar correos electrónicos:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+En este ejemplo, los métodos `setFrom()`, `setRecipient()`, y `setMessage()` se utilizan para establecer los valores correspondientes (remitente, destinatario, contenido del mensaje). Después de establecer cada uno de estos valores, los métodos devuelven el objeto actual (`$email`), lo que nos permite encadenar otro método después de él. Finalmente, llamamos al método `send()`, que realmente envía el correo electrónico.
+
+Gracias a las interfaces fluidas, podemos escribir código intuitivo y fácilmente legible.
+
+
+Copiar con `clone` .[#toc-copying-with-clone]
+---------------------------------------------
+
+En PHP, podemos crear una copia de un objeto utilizando el operador `clone`. De esta forma, obtenemos una nueva instancia con idéntico contenido.
+
+Si necesitamos modificar algunas de sus propiedades al copiar un objeto, podemos definir un método especial `__clone()` en la clase. Este método se llama automáticamente cuando se clona el objeto.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+En este ejemplo, tenemos una clase `Sheep` con una propiedad `$name`. Cuando clonamos una instancia de esta clase, el método `__clone()` se asegura de que el nombre de la oveja clonada obtenga el prefijo "Clone of".
+
+
+Rasgos .[#toc-traits]
+---------------------
+
+Los traits en PHP son una herramienta que permite compartir métodos, propiedades y constantes entre clases y evita la duplicación de código. Puede pensar en ellos como un mecanismo de "copiar y pegar" (Ctrl-C y Ctrl-V), donde el contenido de un trait se "pega" en las clases. Esto permite reutilizar código sin tener que crear complicadas jerarquías de clases.
+
+Veamos un ejemplo sencillo de cómo usar traits en PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+En este ejemplo, tenemos un trait llamado `Honking` que contiene un método `honk()`. Luego tenemos dos clases: `Car` y `Truck`, las cuales usan el trait `Honking`. Como resultado, ambas clases "tienen" el método `honk()`, y podemos llamarlo en objetos de ambas clases.
+
+Los traits permiten compartir código entre clases de forma fácil y eficiente. No entran en la jerarquía de herencia, es decir, `$car instanceof Honking` devolverá `false`.
+
+
+Excepciones
+-----------
+
+Las excepciones en programación orientada a objetos nos permiten manejar con elegancia errores y situaciones inesperadas en nuestro código. Son objetos que contienen información sobre un error o una situación inusual.
+
+En PHP, tenemos una clase incorporada `Exception`, que sirve como base para todas las excepciones. Esta tiene varios métodos que nos permiten obtener más información sobre la excepción, como el mensaje de error, el archivo y la línea donde ocurrió el error, etc.
+
+Cuando se produce un error en el código, podemos "lanzar" la excepción utilizando la palabra clave `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Cuando la función `division()` recibe null como segundo argumento, lanza una excepción con el mensaje de error `'Division by zero!'`. Para evitar que el programa se bloquee cuando se lanza la excepción, la atrapamos en el bloque `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+El código que puede lanzar una excepción se envuelve en un bloque `try`. Si se lanza la excepción, la ejecución del código se mueve a un bloque `catch`, donde podemos manejar la excepción (por ejemplo, escribir un mensaje de error).
+
+Después de los bloques `try` y `catch`, podemos añadir un bloque opcional `finally`, que siempre se ejecuta, se haya lanzado o no la excepción (incluso si usamos `return`, `break`, o `continue` en el bloque `try` o `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+También podemos crear nuestras propias clases de excepción (jerarquía) que hereden de la clase Exception. Como ejemplo, consideremos una simple aplicación bancaria que permite depósitos y retiros:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Se pueden especificar varios bloques `catch` para un único bloque `try` si se esperan diferentes tipos de excepciones.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+En este ejemplo, es importante tener en cuenta el orden de los bloques `catch`. Dado que todas las excepciones heredan de `BankingException`, si tuviéramos este bloque en primer lugar, todas las excepciones se atraparían en él sin que el código llegara a los bloques `catch` posteriores. Por lo tanto, es importante tener las excepciones más específicas (es decir, aquellas que heredan de otras) más arriba en el orden del bloque `catch` que sus excepciones padre.
+
+
+Iteraciones .[#toc-iterations]
+------------------------------
+
+En PHP, puedes hacer un bucle a través de objetos usando el bucle `foreach`, de la misma manera que lo haces a través de un array. Para que esto funcione, el objeto debe implementar una interfaz especial.
+
+La primera opción es implementar la interfaz `Iterator`, que tiene métodos `current()` que devuelve el valor actual, `key()` que devuelve la clave, `next()` que se mueve al siguiente valor, `rewind()` que se mueve al principio, y `valid()` que comprueba si ya hemos llegado al final.
+
+La otra opción es implementar una interfaz `IteratorAggregate`, que sólo tiene un método `getIterator()`. Esto devuelve un objeto marcador de posición que proporcionará el recorrido, o puede ser un generador, que es una función especial que utiliza `yield` para devolver claves y valores secuencialmente:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Buenas prácticas .[#toc-best-practices]
+---------------------------------------
+
+Una vez que hayas aprendido los principios básicos de la programación orientada a objetos, es crucial centrarse en las mejores prácticas de la programación orientada a objetos. Éstas te ayudarán a escribir código que no sólo sea funcional, sino también legible, comprensible y fácil de mantener.
+
+1) **Separación de responsabilidades**: Cada clase debe tener una responsabilidad claramente definida y debe abordar sólo una tarea principal. Si una clase hace demasiadas cosas, puede ser conveniente dividirla en clases más pequeñas y especializadas.
+2) **Encapsulación**: Los datos y métodos deben estar lo más ocultos posible y ser accesibles únicamente a través de una interfaz definida. Esto permite cambiar la implementación interna de una clase sin afectar al resto del código.
+3) **Inyección de dependencias**: En lugar de crear dependencias directamente dentro de una clase, debes "inyectarlas" desde el exterior. Para una comprensión más profunda de este principio, recomendamos los [capítulos sobre In |dependency-injection:introduction]yección de Dependencias.
diff --git a/nette/es/troubleshooting.texy b/nette/es/troubleshooting.texy
index d0f9af49ff..963876307f 100644
--- a/nette/es/troubleshooting.texy
+++ b/nette/es/troubleshooting.texy
@@ -18,7 +18,7 @@ Siempre podrá encontrar el motivo del error en el directorio `log/`. Sin embarg
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // su dirección IP
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Error 404, enrutamiento no funciona .[#toc-error-404-routing-not-working]
 Cuando todas las páginas (excepto la página de inicio) devuelven un error 404, parece un problema de configuración del servidor para [URLs bonitas |#How to Configure a Server for Nice URLs?].
 
 
+¿Cómo desactivar la caché durante el desarrollo? .[#toc-how-to-disable-cache-during-development]
+------------------------------------------------------------------------------------------------
+Nette es inteligente, y no necesitas desactivar la caché en él. Durante el desarrollo, actualiza automáticamente la caché cada vez que hay un cambio en la plantilla o en la configuración del contenedor DI. Además, el modo de desarrollo se activa por auto-detección, por lo que normalmente no hay necesidad de configurar nada, [o sólo la dirección IP |application:bootstrap#development-vs-production-mode].
+
+A la hora de depurar el router, recomendamos desactivar la caché del navegador, donde, por ejemplo, podrían almacenarse las redirecciones: abre Herramientas de desarrollo (Ctrl+Mayús+I o Cmd+Opción+I) y, en el panel Red, marca la casilla para desactivar la caché.
+
+
 Error `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ---------------------------------------------------------------------------------------------------------------------
 Este error se produce si ha actualizado PHP a la versión 8.1 pero está utilizando Nette, que no es compatible con ella. Entonces la solución es actualizar Nette a una versión más reciente usando `composer update`. Nette es compatible con PHP 8.1 desde la versión 3.0. Si está usando una versión anterior (puede averiguarlo buscando en `composer.json`), [actualice |migrations:en] Nette o quédese con PHP 8.0.
@@ -67,7 +74,7 @@ El directorio `www/` utilizado en los proyectos de ejemplo de Nette es el denomi
 
 Para ejecutar la aplicación en el hosting, es necesario establecer el document-root a este directorio en la configuración del hosting. O, si el alojamiento tiene una carpeta pre-hecha para el directorio público con un nombre diferente (por ejemplo `web`, `public_html` etc.), simplemente renombre `www/`.
 
-La solución **no** es "deshacerse" de la carpeta `www/` utilizando reglas en el archivo `.htaccess` o en el router. Si el alojamiento no te permite establecer document-root en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), busca otro. De lo contrario, estarías asumiendo un riesgo de seguridad importante. Sería como vivir en un apartamento en el que no puedes cerrar la puerta principal y siempre está abierta de par en par.
+La solución **no es** impedir el acceso a todas las carpetas excepto `www/` mediante reglas en el archivo `.htaccess` o en el router. Si tu alojamiento no permite establecer la raíz del documento en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), deberías buscar otro servicio de alojamiento. De lo contrario, te estarías exponiendo a importantes riesgos de seguridad. Sería como vivir en un apartamento donde la puerta principal no se puede cerrar y está siempre abierta de par en par.
 
 
 ¿Cómo configurar un servidor para URLs agradables? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/fr/@home.texy b/nette/fr/@home.texy
index 76241bb9d3..23f87d0522 100644
--- a/nette/fr/@home.texy
+++ b/nette/fr/@home.texy
@@ -84,11 +84,11 @@ Utilitaires
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hachage de mot de passe |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Types PHP |utils:type]
 - [Strings |utils:Strings]
 - [Validateurs |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...autres |utils:]
 </div>
diff --git a/nette/fr/installation.texy b/nette/fr/installation.texy
index 76b5e3fdd8..64be253e09 100644
--- a/nette/fr/installation.texy
+++ b/nette/fr/installation.texy
@@ -20,7 +20,7 @@ Nette propose une collection de packages (bibliothèques) utiles et sophistiqué
 composer require nette/utils
 ```
 
-Vous préférez une interface graphique ? Consultez le [guide d' |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] installation des paquets dans l'environnement PhpStrom.
+Vous préférez une interface graphique ? Consultez le [guide d' |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] installation des paquets dans l'environnement PhpStorm.
 
 
 Comment démarrer un nouveau projet avec Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/fr/introduction-to-object-oriented-programming.texy b/nette/fr/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..d65c6026e3
--- /dev/null
+++ b/nette/fr/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Introduction à la programmation orientée objet
+**********************************************
+
+.[perex]
+Le terme "POO" signifie programmation orientée objet, c'est-à-dire une façon d'organiser et de structurer le code. La POO nous permet de considérer un programme comme une collection d'objets qui communiquent entre eux, plutôt que comme une séquence de commandes et de fonctions.
+
+Dans la POO, un "objet" est une unité qui contient des données et des fonctions qui opèrent sur ces données. Les objets sont créés sur la base de "classes", qui peuvent être considérées comme des plans ou des modèles d'objets. Une fois que nous disposons d'une classe, nous pouvons créer son "instance", qui est un objet spécifique fabriqué à partir de cette classe.
+
+Voyons comment créer une classe simple en PHP. Pour définir une classe, on utilise le mot-clé "class", suivi du nom de la classe, puis des accolades qui entourent les fonctions de la classe (appelées "méthodes") et les variables de la classe (appelées "propriétés" ou "attributs") :
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Dans cet exemple, nous avons créé une classe nommée `Car` avec une fonction (ou "méthode") appelée `honk`.
+
+Chaque classe ne doit résoudre qu'une seule tâche principale. Si une classe fait trop de choses, il peut être judicieux de la diviser en classes plus petites et spécialisées.
+
+Les classes sont généralement stockées dans des fichiers distincts afin que le code reste organisé et facile à parcourir. Le nom du fichier doit correspondre au nom de la classe. Ainsi, pour la classe `Car`, le nom du fichier sera `Car.php`.
+
+Pour nommer les classes, il est conseillé de suivre la convention "PascalCase", ce qui signifie que chaque mot du nom commence par une majuscule et qu'il n'y a pas de soulignement ou d'autres séparateurs. Les méthodes et les propriétés suivent la convention "camelCase", c'est-à-dire qu'elles commencent par une lettre minuscule.
+
+Certaines méthodes en PHP ont des rôles spéciaux et sont préfixées par `__` (deux underscores). L'une des méthodes spéciales les plus importantes est le "constructeur", désigné par `__construct`. Le constructeur est une méthode qui est automatiquement appelée lors de la création d'une nouvelle instance d'une classe.
+
+Nous utilisons souvent le constructeur pour définir l'état initial d'un objet. Par exemple, lors de la création d'un objet représentant une personne, vous pouvez utiliser le constructeur pour définir son âge, son nom ou d'autres attributs.
+
+Voyons comment utiliser un constructeur en PHP :
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+Dans cet exemple, la classe `Person` possède une propriété (variable) `$age` et un constructeur qui définit cette propriété. La méthode `howOldAreYou()` permet ensuite d'accéder à l'âge de la personne.
+
+La pseudo-variable `$this` est utilisée à l'intérieur de la classe pour accéder aux propriétés et aux méthodes de l'objet.
+
+Le mot-clé `new` est utilisé pour créer une nouvelle instance d'une classe. Dans l'exemple ci-dessus, nous avons créé une nouvelle personne âgée de 25 ans.
+
+Vous pouvez également définir des valeurs par défaut pour les paramètres du constructeur s'ils ne sont pas spécifiés lors de la création d'un objet. Par exemple :
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Dans cet exemple, si vous ne spécifiez pas d'âge lors de la création d'un objet `Person`, la valeur par défaut de 20 sera utilisée.
+
+L'avantage est que la définition de la propriété avec son initialisation via le constructeur peut être raccourcie et simplifiée comme suit :
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Pour être complet, outre les constructeurs, les objets peuvent avoir des destructeurs (méthode `__destruct`) qui sont appelés avant que l'objet ne soit libéré de la mémoire.
+
+
+Espaces nominatifs .[#toc-namespaces]
+-------------------------------------
+
+Les espaces de nommage nous permettent d'organiser et de regrouper des classes, des fonctions et des constantes apparentées tout en évitant les conflits de noms. Ils sont comparables aux dossiers d'un ordinateur, où chaque dossier contient des fichiers liés à un projet ou à un sujet spécifique.
+
+Les espaces de noms sont particulièrement utiles dans les grands projets ou lors de l'utilisation de bibliothèques tierces où des conflits de noms de classes peuvent survenir.
+
+Imaginez que vous ayez une classe nommée `Car` dans votre projet et que vous souhaitiez la placer dans un espace de noms appelé `Transport`. Voici comment procéder :
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Si vous souhaitez utiliser la classe `Car` dans un autre fichier, vous devez spécifier l'espace de noms d'où provient la classe :
+
+```php
+$car = new Transport\Car;
+```
+
+Pour simplifier, vous pouvez indiquer au début du fichier quelle classe d'un espace de noms particulier vous souhaitez utiliser, ce qui vous permet de créer des instances sans mentionner le chemin d'accès complet :
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Héritage .[#toc-inheritance]
+----------------------------
+
+L'héritage est un outil de la programmation orientée objet qui permet de créer de nouvelles classes basées sur des classes existantes, d'hériter de leurs propriétés et de leurs méthodes, et de les étendre ou de les redéfinir si nécessaire. L'héritage garantit la réutilisation du code et la hiérarchie des classes.
+
+En d'autres termes, si nous disposons d'une classe et que nous souhaitons en créer une autre dérivée, mais avec quelques modifications, nous pouvons "hériter" la nouvelle classe de la classe d'origine.
+
+En PHP, l'héritage est mis en œuvre à l'aide du mot-clé `extends`.
+
+Notre classe `Person` stocke des informations sur l'âge. Nous pouvons avoir une autre classe, `Student`, qui étend `Person` et ajoute des informations sur le domaine d'études.
+
+Prenons un exemple :
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Comment fonctionne ce code ?
+
+- Nous avons utilisé le mot-clé `extends` pour étendre la classe `Person`, ce qui signifie que la classe `Student` hérite de toutes les méthodes et propriétés de `Person`.
+
+- Le mot-clé `parent::` nous permet d'appeler les méthodes de la classe mère. Dans ce cas, nous avons appelé le constructeur de la classe `Person` avant d'ajouter notre propre fonctionnalité à la classe `Student`. De même, nous avons appelé la méthode de l'ancêtre `printInformation()` avant d'énumérer les informations sur les étudiants.
+
+L'héritage est destiné aux situations où il existe une relation "est un" entre les classes. Par exemple, un `Student` est un `Person`. Un chat est un animal. Il nous permet, dans les cas où nous attendons un objet (par exemple, "Personne") dans le code, d'utiliser un objet dérivé à la place (par exemple, "Étudiant").
+
+Il est essentiel de comprendre que l'objectif premier de l'héritage **n'est pas** d'empêcher la duplication du code. Au contraire, une mauvaise utilisation de l'héritage peut conduire à un code complexe et difficile à maintenir. S'il n'y a pas de relation "is a" entre les classes, nous devrions envisager la composition plutôt que l'héritage.
+
+Notez que les méthodes `printInformation()` des classes `Person` et `Student` produisent des informations légèrement différentes. Nous pouvons également ajouter d'autres classes (telles que `Employee`) qui fourniront d'autres implémentations de cette méthode. La capacité des objets de différentes classes à répondre à la même méthode de différentes manières est appelée polymorphisme :
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+La composition .[#toc-composition]
+----------------------------------
+
+La composition est une technique par laquelle, au lieu d'hériter des propriétés et des méthodes d'une autre classe, nous utilisons simplement son instance dans notre classe. Cela nous permet de combiner les fonctionnalités et les propriétés de plusieurs classes sans créer de structures d'héritage complexes.
+
+Par exemple, nous avons une classe `Engine` et une classe `Car`. Au lieu de dire "Une voiture est un moteur", nous disons "Une voiture a un moteur", ce qui est une relation de composition typique.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Ici, la classe `Car` ne possède pas toutes les propriétés et méthodes de la classe `Engine`, mais elle y a accès par l'intermédiaire de la propriété `$engine`.
+
+L'avantage de la composition est une plus grande souplesse de conception et une meilleure adaptabilité aux changements futurs.
+
+
+Visibilité .[#toc-visibility]
+-----------------------------
+
+En PHP, vous pouvez définir la "visibilité" des propriétés, méthodes et constantes des classes. La visibilité détermine l'endroit où vous pouvez accéder à ces éléments.
+
+1. **Public:** Si un élément est marqué comme `public`, cela signifie que vous pouvez y accéder de n'importe où, même en dehors de la classe.
+
+2. **Protégé:** Un élément marqué comme `protected` n'est accessible qu'au sein de la classe et de toutes ses descendantes (classes qui en héritent).
+
+3. **Privé:** Si un élément est marqué `private`, il n'est accessible qu'à l'intérieur de la classe dans laquelle il a été défini.
+
+Si vous ne spécifiez pas la visibilité, PHP la définira automatiquement à `public`.
+
+Voyons un exemple de code :
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Poursuite de l'héritage des classes :
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+Dans ce cas, la méthode `printProperties()` de la classe `ChildClass` peut accéder aux propriétés publiques et protégées, mais ne peut pas accéder aux propriétés privées de la classe mère.
+
+Les données et les méthodes doivent être aussi cachées que possible et accessibles uniquement par l'intermédiaire d'une interface définie. Cela permet de modifier l'implémentation interne de la classe sans affecter le reste du code.
+
+
+Mot-clé final .[#toc-final-keyword]
+-----------------------------------
+
+En PHP, nous pouvons utiliser le mot-clé `final` si nous voulons empêcher une classe, une méthode ou une constante d'être héritée ou surchargée. Lorsqu'une classe est marquée comme `final`, elle ne peut pas être étendue. Lorsqu'une méthode est marquée comme `final`, elle ne peut pas être remplacée dans une sous-classe.
+
+Le fait de savoir qu'une certaine classe ou méthode ne sera plus modifiée nous permet d'apporter des changements plus facilement sans nous soucier des conflits potentiels. Par exemple, nous pouvons ajouter une nouvelle méthode sans craindre qu'un descendant ait déjà une méthode portant le même nom, ce qui entraînerait une collision. Nous pouvons également modifier les paramètres d'une méthode, toujours sans risquer de provoquer une incohérence avec une méthode surchargée dans un descendant.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+Dans cet exemple, tenter d'hériter de la classe finale `FinalClass` entraînera une erreur.
+
+
+Propriétés et méthodes statiques .[#toc-static-properties-and-methods]
+----------------------------------------------------------------------
+
+Lorsque nous parlons d'éléments "statiques" d'une classe en PHP, nous parlons de méthodes et de propriétés qui appartiennent à la classe elle-même, et non à une instance spécifique de la classe. Cela signifie que vous n'avez pas besoin de créer une instance de la classe pour y accéder. Au lieu de cela, vous les appelez ou y accédez directement par l'intermédiaire du nom de la classe.
+
+N'oubliez pas qu'étant donné que les éléments statiques appartiennent à la classe et non à ses instances, vous ne pouvez pas utiliser la pseudo-variable `$this` à l'intérieur des méthodes statiques.
+
+L'utilisation de propriétés statiques conduit à un [code obscurci et plein d'embûches |dependency-injection:global-state], vous ne devriez donc jamais les utiliser, et nous ne montrerons pas d'exemple ici. En revanche, les méthodes statiques sont utiles. En voici un exemple :
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+Dans cet exemple, nous avons créé une classe `Calculator` avec deux méthodes statiques. Nous pouvons appeler ces méthodes directement sans créer une instance de la classe à l'aide de l'opérateur `::`. Les méthodes statiques sont particulièrement utiles pour les opérations qui ne dépendent pas de l'état d'une instance de classe spécifique.
+
+
+Constantes de classe .[#toc-class-constants]
+--------------------------------------------
+
+Au sein des classes, nous avons la possibilité de définir des constantes. Les constantes sont des valeurs qui ne changent jamais pendant l'exécution du programme. Contrairement aux variables, la valeur d'une constante reste inchangée.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+Dans cet exemple, nous avons une classe `Car` avec la constante `NumberOfWheels`. Lorsque nous accédons à la constante à l'intérieur de la classe, nous pouvons utiliser le mot-clé `self` au lieu du nom de la classe.
+
+
+Interfaces d'objets .[#toc-object-interfaces]
+---------------------------------------------
+
+Les interfaces d'objets agissent comme des "contrats" pour les classes. Si une classe doit implémenter une interface objet, elle doit contenir toutes les méthodes définies par l'interface. C'est un excellent moyen de s'assurer que certaines classes adhèrent au même "contrat" ou à la même structure.
+
+En PHP, les interfaces sont définies à l'aide du mot-clé `interface`. Toutes les méthodes définies dans une interface sont publiques (`public`). Lorsqu'une classe implémente une interface, elle utilise le mot-clé `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Si une classe implémente une interface, mais que toutes les méthodes attendues ne sont pas définies, PHP lèvera une erreur.
+
+Une classe peut implémenter plusieurs interfaces à la fois, ce qui est différent de l'héritage, où une classe ne peut hériter que d'une seule classe :
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Classes abstraites .[#toc-abstract-classes]
+-------------------------------------------
+
+Les classes abstraites servent de modèles de base pour d'autres classes, mais vous ne pouvez pas créer leurs instances directement. Elles contiennent un mélange de méthodes complètes et de méthodes abstraites dont le contenu n'est pas défini. Les classes qui héritent de classes abstraites doivent fournir des définitions pour toutes les méthodes abstraites du parent.
+
+Nous utilisons le mot-clé `abstract` pour définir une classe abstraite.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+Dans cet exemple, nous avons une classe abstraite avec une méthode ordinaire et une méthode abstraite. Nous avons ensuite une classe `Child` qui hérite de `AbstractClass` et fournit une implémentation pour la méthode abstraite.
+
+En quoi les interfaces et les classes abstraites sont-elles différentes ? Les classes abstraites peuvent contenir des méthodes abstraites et concrètes, tandis que les interfaces définissent uniquement les méthodes que la classe doit implémenter, mais ne fournissent aucune implémentation. Une classe ne peut hériter que d'une seule classe abstraite, mais peut implémenter un nombre quelconque d'interfaces.
+
+
+Vérification du type .[#toc-type-checking]
+------------------------------------------
+
+En programmation, il est crucial de s'assurer que les données avec lesquelles nous travaillons sont du bon type. En PHP, nous avons des outils qui fournissent cette assurance. Vérifier que les données sont du bon type est appelé "vérification de type".
+
+Les types que nous pouvons rencontrer en PHP :
+
+1. **Types de base** : Ils comprennent `int` (entiers), `float` (nombres à virgule flottante), `bool` (valeurs booléennes), `string` (chaînes de caractères), `array` (tableaux) et `null`.
+2. **Classes** : Lorsque nous voulons qu'une valeur soit une instance d'une classe spécifique.
+3. **Interfaces** : Définit un ensemble de méthodes qu'une classe doit implémenter. Une valeur qui répond à une interface doit posséder ces méthodes.
+4. **Types mixtes** : Nous pouvons spécifier qu'une variable peut avoir plusieurs types autorisés.
+5. **Void** : Ce type spécial indique qu'une fonction ou une méthode ne renvoie aucune valeur.
+
+Voyons comment modifier le code pour inclure les types :
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+De cette manière, nous nous assurons que notre code s'attend à ce que les données soient du bon type et qu'il fonctionne avec elles, ce qui nous permet d'éviter les erreurs potentielles.
+
+Certains types ne peuvent pas être écrits directement en PHP. Dans ce cas, ils sont listés dans le commentaire phpDoc, qui est le format standard de documentation du code PHP, commençant par `/**` et se terminant par `*/`. Il vous permet d'ajouter des descriptions de classes, de méthodes, etc. Il permet également d'énumérer des types complexes à l'aide des annotations `@var`, `@param` et `@return`. Ces types sont ensuite utilisés par les outils d'analyse statique du code, mais ne sont pas vérifiés par PHP lui-même.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Comparaison et identité .[#toc-comparison-and-identity]
+-------------------------------------------------------
+
+En PHP, vous pouvez comparer des objets de deux manières :
+
+1. Comparaison de valeurs `==`: Vérifie si les objets sont de la même classe et ont les mêmes valeurs dans leurs propriétés.
+2. Comparaison d'identité `===`: vérifie s'il s'agit de la même instance de l'objet.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+L'opérateur `instanceof` .[#toc-the-instanceof-operator]
+--------------------------------------------------------
+
+L'opérateur `instanceof` permet de déterminer si un objet donné est une instance d'une classe spécifique, un descendant de cette classe ou s'il implémente une certaine interface.
+
+Imaginons que nous ayons une classe `Person` et une autre classe `Student`, qui est un descendant de `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+D'après les résultats, il est évident que l'objet `$student` est considéré comme une instance des classes `Student` et `Person`.
+
+
+Interfaces fluides .[#toc-fluent-interfaces]
+--------------------------------------------
+
+Une "interface fluide" est une technique de la POO qui permet d'enchaîner des méthodes en un seul appel. Cela permet souvent de simplifier et de clarifier le code.
+
+L'élément clé d'une interface fluide est que chaque méthode de la chaîne renvoie une référence à l'objet actuel. Pour ce faire, on utilise `return $this;` à la fin de la méthode. Ce style de programmation est souvent associé à des méthodes appelées "setters", qui fixent les valeurs des propriétés d'un objet.
+
+Voyons à quoi pourrait ressembler une interface fluide pour l'envoi de courriers électroniques :
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+Dans cet exemple, les méthodes `setFrom()`, `setRecipient()`, et `setMessage()` sont utilisées pour définir les valeurs correspondantes (expéditeur, destinataire, contenu du message). Après avoir défini chacune de ces valeurs, les méthodes renvoient l'objet courant (`$email`), ce qui nous permet d'enchaîner une autre méthode après celle-ci. Enfin, nous appelons la méthode `send()`, qui envoie effectivement le courrier électronique.
+
+Grâce aux interfaces fluides, nous pouvons écrire un code intuitif et facilement lisible.
+
+
+Copier avec `clone` .[#toc-copying-with-clone]
+----------------------------------------------
+
+En PHP, nous pouvons créer une copie d'un objet en utilisant l'opérateur `clone`. De cette manière, nous obtenons une nouvelle instance avec un contenu identique.
+
+Si nous devons modifier certaines propriétés lors de la copie d'un objet, nous pouvons définir une méthode spéciale `__clone()` dans la classe. Cette méthode est automatiquement appelée lorsque l'objet est cloné.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+Dans cet exemple, nous avons une classe `Sheep` avec une propriété `$name`. Lorsque nous clonons une instance de cette classe, la méthode `__clone()` veille à ce que le nom du mouton cloné reçoive le préfixe "Clone de".
+
+
+Traits .[#toc-traits]
+---------------------
+
+Les traits en PHP sont un outil qui permet de partager des méthodes, des propriétés et des constantes entre les classes et d'éviter la duplication du code. Vous pouvez les considérer comme un mécanisme de "copier-coller" (Ctrl-C et Ctrl-V), où le contenu d'un trait est "collé" dans les classes. Cela vous permet de réutiliser le code sans avoir à créer des hiérarchies de classes compliquées.
+
+Voyons un exemple simple d'utilisation des traits en PHP :
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+Dans cet exemple, nous avons un trait nommé `Honking` qui contient une méthode `honk()`. Nous avons ensuite deux classes : `Car` et `Truck`, qui utilisent toutes deux le trait `Honking`. Par conséquent, les deux classes "possèdent" la méthode `honk()` et nous pouvons l'appeler sur des objets des deux classes.
+
+Les traits vous permettent de partager facilement et efficacement le code entre les classes. Ils n'entrent pas dans la hiérarchie de l'héritage, c'est-à-dire que `$car instanceof Honking` renverra `false`.
+
+
+Exceptions
+----------
+
+Les exceptions dans la POO nous permettent de gérer gracieusement les erreurs et les situations inattendues dans notre code. Il s'agit d'objets qui contiennent des informations sur une erreur ou une situation inhabituelle.
+
+En PHP, nous avons une classe intégrée `Exception`, qui sert de base à toutes les exceptions. Cette classe possède plusieurs méthodes qui nous permettent d'obtenir plus d'informations sur l'exception, comme le message d'erreur, le fichier et la ligne où l'erreur s'est produite, etc.
+
+Lorsqu'une erreur survient dans le code, nous pouvons "lancer" l'exception à l'aide du mot-clé `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Lorsque la fonction `division()` reçoit null comme deuxième argument, elle lance une exception avec le message d'erreur `'Division by zero!'`. Pour éviter que le programme ne se bloque lorsque l'exception est levée, nous la bloquons dans le bloc `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Le code qui peut lancer une exception est enveloppé dans un bloc `try`. Si l'exception est levée, l'exécution du code passe à un bloc `catch`, où nous pouvons gérer l'exception (par exemple, écrire un message d'erreur).
+
+Après les blocs `try` et `catch`, nous pouvons ajouter un bloc optionnel `finally`, qui est toujours exécuté, que l'exception ait été levée ou non (même si nous utilisons `return`, `break`, ou `continue` dans le bloc `try` ou `catch` ) :
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Nous pouvons également créer nos propres classes d'exception (hiérarchie) qui héritent de la classe Exception. Prenons l'exemple d'une application bancaire simple qui permet d'effectuer des dépôts et des retraits :
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Plusieurs blocs `catch` peuvent être spécifiés pour un seul bloc `try` si vous vous attendez à différents types d'exceptions.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+Dans cet exemple, il est important de noter l'ordre des blocs `catch`. Étant donné que toutes les exceptions héritent de `BankingException`, si nous avions ce bloc en premier, toutes les exceptions seraient capturées dans ce bloc sans que le code n'atteigne les blocs `catch` suivants. Par conséquent, il est important que les exceptions plus spécifiques (c'est-à-dire celles qui héritent d'autres exceptions) soient placées plus haut dans l'ordre du bloc `catch` que leurs exceptions parentales.
+
+
+Itérations .[#toc-iterations]
+-----------------------------
+
+En PHP, vous pouvez parcourir des objets en utilisant la boucle `foreach`, de la même manière que vous parcourez un tableau. Pour que cela fonctionne, l'objet doit implémenter une interface spéciale.
+
+La première option consiste à implémenter l'interface `Iterator`, qui possède des méthodes `current()` renvoyant la valeur courante, `key()` renvoyant la clé, `next()` passant à la valeur suivante, `rewind()` passant au début, et `valid()` vérifiant si nous sommes déjà à la fin.
+
+L'autre option consiste à mettre en œuvre une interface `IteratorAggregate`, qui ne comporte qu'une seule méthode `getIterator()`. Celle-ci renvoie un objet de remplacement qui assurera la traversée, ou peut être un générateur, c'est-à-dire une fonction spéciale qui utilise `yield` pour renvoyer les clés et les valeurs de manière séquentielle :
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Meilleures pratiques .[#toc-best-practices]
+-------------------------------------------
+
+Une fois que vous avez assimilé les principes de base de la programmation orientée objet, il est essentiel de vous concentrer sur les meilleures pratiques de la POO. Celles-ci vous aideront à écrire un code non seulement fonctionnel, mais aussi lisible, compréhensible et facile à maintenir.
+
+1) **Séparation des préoccupations** : Chaque classe doit avoir une responsabilité clairement définie et ne doit s'occuper que d'une seule tâche principale. Si une classe fait trop de choses, il peut être judicieux de la diviser en classes spécialisées plus petites.
+2) **Encapsulation** : Les données et les méthodes doivent être aussi cachées que possible et accessibles uniquement par l'intermédiaire d'une interface définie. Cela permet de modifier l'implémentation interne d'une classe sans affecter le reste du code.
+3) **Injection de dépendances** : Au lieu de créer des dépendances directement dans une classe, vous devriez les "injecter" depuis l'extérieur. Pour une compréhension plus approfondie de ce principe, nous recommandons les [chapitres sur l'injection de dépendances |dependency-injection:introduction].
diff --git a/nette/fr/troubleshooting.texy b/nette/fr/troubleshooting.texy
index fad903b6f2..a1b8cfcf69 100644
--- a/nette/fr/troubleshooting.texy
+++ b/nette/fr/troubleshooting.texy
@@ -18,7 +18,7 @@ Vous pouvez toujours trouver la raison de l'erreur dans le répertoire `log/`. C
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // votre adresse IP
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Erreur 404, le routage ne fonctionne pas .[#toc-error-404-routing-not-working]
 Lorsque toutes les pages (sauf la page d'accueil) renvoient une erreur 404, il semble qu'il y ait un problème de configuration du serveur pour les [jolies URL |#How to Configure a Server for Nice URLs?].
 
 
+Comment désactiver le cache pendant le développement ? .[#toc-how-to-disable-cache-during-development]
+------------------------------------------------------------------------------------------------------
+Nette est intelligent et il n'est pas nécessaire de désactiver la mise en cache. Pendant le développement, il met automatiquement à jour le cache chaque fois qu'il y a un changement dans le modèle ou la configuration du conteneur DI. De plus, le mode développement est activé par auto-détection, il n'y a donc généralement pas besoin de configurer quoi que ce soit, [ou juste l'adresse IP |application:bootstrap#development-vs-production-mode].
+
+Lorsque vous déboguez le routeur, nous vous recommandons de désactiver le cache du navigateur, où, par exemple, les redirections peuvent être stockées : ouvrez Developer Tools (Ctrl+Shift+I ou Cmd+Option+I) et dans le panneau Network, cochez la case pour désactiver le cache.
+
+
 Erreur `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Cette erreur se produit si vous avez mis à niveau PHP vers la version 8.1 mais que vous utilisez Nette, qui n'est pas compatible avec cette version. La solution est donc de mettre à jour Nette vers une version plus récente en utilisant `composer update`. Nette supporte PHP 8.1 depuis la version 3.0. Si vous utilisez une version plus ancienne (vous pouvez le savoir en consultant `composer.json`), [mettez à jour Nette |migrations:en] ou restez avec PHP 8.0.
@@ -67,7 +74,7 @@ Le répertoire `www/` utilisé dans les exemples de projets de Nette est le rép
 
 Pour exécuter l'application sur l'hébergement, vous devez définir le document-root sur ce répertoire dans la configuration de l'hébergement. Ou, si l'hébergement a un dossier prédéfini pour le répertoire public avec un nom différent (par exemple `web`, `public_html` etc.), renommez simplement `www/`.
 
-La solution **n'est pas** de se "débarrasser" du dossier `www/` en utilisant des règles dans le fichier `.htaccess` ou dans le routeur. Si l'hébergement ne vous permet pas de définir document-root sur un sous-répertoire (c'est-à-dire de créer des répertoires un niveau au-dessus du répertoire public), cherchez-en un autre. Sinon, vous prenez un risque important en matière de sécurité. Ce serait comme vivre dans un appartement où vous ne pouvez pas fermer la porte d'entrée et où elle est toujours grande ouverte.
+La solution **n'est pas** d'empêcher l'accès à tous les dossiers sauf `www/` en utilisant des règles dans le fichier `.htaccess` ou dans le routeur. Si votre hébergement ne permet pas de placer la racine du document dans un sous-répertoire (c'est-à-dire de créer des répertoires un niveau au-dessus du répertoire public), vous devriez chercher un autre service d'hébergement. Dans le cas contraire, vous vous exposeriez à des risques de sécurité importants. Ce serait comme vivre dans un appartement dont la porte d'entrée ne peut être fermée et reste toujours grande ouverte.
 
 
 Comment configurer un serveur pour de belles URL ? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/hu/@home.texy b/nette/hu/@home.texy
index 53d3959489..b3aa613dea 100644
--- a/nette/hu/@home.texy
+++ b/nette/hu/@home.texy
@@ -84,11 +84,11 @@ Segédprogramok
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Password Hashing |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [PHP típusok |utils:type]
 - [Strings |utils:Strings]
 - [Validátorok |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...mások |utils:]
 </div>
diff --git a/nette/hu/installation.texy b/nette/hu/installation.texy
index a390238849..cafa64d29c 100644
--- a/nette/hu/installation.texy
+++ b/nette/hu/installation.texy
@@ -20,7 +20,7 @@ A Nette hasznos és kifinomult csomagok (könyvtárak) gyűjteményét kínálja
 composer require nette/utils
 ```
 
-Grafikus felületet szeretne? Tekintse meg a csomagok telepítéséről szóló [útmutatót |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] a PhpStrom környezetben.
+Grafikus felületet szeretne? Tekintse meg a csomagok telepítéséről szóló [útmutatót |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] a PhpStorm környezetben.
 
 
 Új projekt indítása a Nette segítségével .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/hu/introduction-to-object-oriented-programming.texy b/nette/hu/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..92c8f98f91
--- /dev/null
+++ b/nette/hu/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Bevezetés az objektumorientált programozásba
+********************************************
+
+.[perex]
+Az "OOP" kifejezés az objektumorientált programozás rövidítése, amely a kód szervezésének és strukturálásának egy módja. Az OOP lehetővé teszi, hogy a programot egymással kommunikáló objektumok gyűjteményének tekintsük, nem pedig parancsok és függvények sorozatának.
+
+Az OOP-ban az "objektum" olyan egység, amely adatokat és az adatokkal operáló függvényeket tartalmaz. Az objektumok létrehozása "osztályok" alapján történik, amelyek az objektumok tervrajzaként vagy sablonjaként értelmezhetők. Ha már van egy osztályunk, létrehozhatjuk annak "példányát", amely egy konkrét, az osztályból készült objektum.
+
+Nézzük meg, hogyan hozhatunk létre egy egyszerű osztályt PHP-ben. Egy osztály definiálásakor az "class" kulcsszót használjuk, amelyet az osztály neve követ, majd a szögletes zárójelek az osztály függvényeit (az úgynevezett "metódusokat") és az osztály változóit (az úgynevezett "tulajdonságokat" vagy "attribútumokat") zárják körül:
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Ebben a példában egy `Car` nevű osztályt hoztunk létre egy `honk` nevű függvénnyel (vagy "módszerrel").
+
+Minden osztály csak egy fő feladatot oldhat meg. Ha egy osztály túl sok mindent csinál, akkor célszerű lehet kisebb, speciális osztályokra osztani.
+
+Az osztályokat általában külön fájlokban tároljuk, hogy a kódot rendszerezve tartsuk és könnyen áttekinthetővé tegyük. A fájlnévnek meg kell egyeznie az osztály nevével, így a `Car` osztály esetében a fájl neve `Car.php` lenne.
+
+Az osztályok elnevezésénél célszerű a "PascalCase" konvenciót követni, ami azt jelenti, hogy a névben minden szó nagybetűvel kezdődik, és nincsenek aláhúzások vagy egyéb elválasztójelek. A metódusok és tulajdonságok a "camelCase" konvenciót követik, azaz kisbetűvel kezdődnek.
+
+A PHP egyes metódusai speciális szerepkörrel rendelkeznek, és a `__` (két aláhúzás) előtaggal vannak ellátva. Az egyik legfontosabb speciális metódus a "konstruktor", amelyet a `__construct` jelöléssel látunk el. A konstruktor egy olyan metódus, amely automatikusan meghívásra kerül, amikor egy osztály új példányát létrehozzuk.
+
+A konstruktort gyakran használjuk egy objektum kezdeti állapotának beállítására. Például egy személyt reprezentáló objektum létrehozásakor a konstruktort használhatjuk a kor, a név vagy más attribútumok beállítására.
+
+Lássuk, hogyan használhatunk konstruktort a PHP-ban:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+Ebben a példában a `Person` osztály rendelkezik egy `$age` tulajdonsággal (változóval) és egy konstruktorral, amely beállítja ezt a tulajdonságot. A `howOldAreYou()` metódus ezután hozzáférést biztosít a személy életkorához.
+
+A `$this` álváltozót az osztályon belül az objektum tulajdonságainak és metódusainak elérésére használjuk.
+
+A `new` kulcsszó egy osztály új példányának létrehozására szolgál. A fenti példában egy új, 25 éves személyt hoztunk létre.
+
+A konstruktor paramétereihez alapértelmezett értékeket is megadhatunk, ha azok nincsenek megadva egy objektum létrehozásakor. Például:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Ebben a példában, ha a `Person` objektum létrehozásakor nem ad meg életkort, az alapértelmezett 20-as értéket fogja használni.
+
+A szép dolog az, hogy a tulajdonság definíciója a konstruktoron keresztül történő inicializálással lerövidíthető és leegyszerűsíthető így:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+A teljesség kedvéért a konstruktorok mellett az objektumok rendelkezhetnek destruktorokkal ( `__destruct`), amelyeket az objektum memóriából való kikerülése előtt hívunk meg.
+
+
+Névterek .[#toc-namespaces]
+---------------------------
+
+A névterek lehetővé teszik, hogy az egymással összefüggő osztályokat, függvényeket és konstansokat rendszerezzük és csoportosítsuk, miközben elkerüljük a névkonfliktusokat. Úgy gondolhat rájuk, mint a számítógép mappáira, ahol minden mappa egy adott projekthez vagy témához kapcsolódó fájlokat tartalmaz.
+
+A névterek különösen hasznosak nagyobb projekteknél vagy harmadik féltől származó könyvtárak használatakor, ahol osztályok elnevezési konfliktusok merülhetnek fel.
+
+Képzelje el, hogy van egy `Car` nevű osztálya a projektjében, és a `Transport` nevű névtérben szeretné elhelyezni. Ezt a következőképpen tenné:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Ha a `Car` osztályt egy másik fájlban szeretné használni, akkor meg kell adnia, hogy az osztály melyik névtérből származik:
+
+```php
+$car = new Transport\Car;
+```
+
+Az egyszerűsítés érdekében a fájl elején megadhatja, hogy melyik osztályt szeretné használni egy adott névtérből, így a teljes elérési út megadása nélkül hozhat létre példányokat:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Öröklés .[#toc-inheritance]
+---------------------------
+
+Az öröklés az objektumorientált programozás egyik eszköze, amely lehetővé teszi új osztályok létrehozását a már létező osztályok alapján, örökölve azok tulajdonságait és metódusait, és szükség szerint kibővítve vagy átdefiniálva azokat. Az öröklés biztosítja a kód újrafelhasználhatóságát és az osztályhierarchiát.
+
+Egyszerűen fogalmazva, ha van egy osztályunk, és szeretnénk létrehozni egy másik, abból származtatott, de némi módosítással rendelkező osztályt, akkor az új osztályt "örökölhetjük" az eredetiből.
+
+A PHP-ben az öröklés a `extends` kulcsszóval valósul meg.
+
+A mi `Person` osztályunk az életkori információkat tárolja. Létrehozhatunk egy másik osztályt, a `Student`, amely a `Person` kiterjesztése, és hozzáadhatja a tanulmányi területre vonatkozó információkat.
+
+Nézzünk egy példát:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Hogyan működik ez a kód?
+
+- A `extends` kulcsszóval bővítettük a `Person` osztályt, ami azt jelenti, hogy a `Student` osztály minden metódust és tulajdonságot a `Person` osztályból örököl.
+
+- A `parent::` kulcsszó lehetővé teszi számunkra, hogy a szülő osztály metódusait hívjuk. Ebben az esetben a `Person` osztály konstruktorát hívtuk meg, mielőtt a `Student` osztályhoz hozzáadtuk volna a saját funkcionalitásunkat. És hasonlóképpen a `printInformation()` felmenő osztály metódusát, mielőtt a tanulói adatokat listáznánk.
+
+Az öröklés olyan helyzetekre való, amikor az osztályok között "is a" kapcsolat van. Például egy `Student` egy `Person`. A macska egy állat. Lehetővé teszi számunkra, hogy olyan esetekben, amikor egy objektumot (pl. "Person") várunk a kódban, egy származtatott objektumot használjunk helyette (pl. "Student").
+
+Lényeges felismerni, hogy az öröklés elsődleges célja **nem** a kódduplikáció megakadályozása. Éppen ellenkezőleg, az öröklés helytelen használata összetett és nehezen karbantartható kódhoz vezethet. Ha nincs "is a" kapcsolat az osztályok között, akkor az öröklés helyett a kompozíciót kell fontolóra vennünk.
+
+Vegyük észre, hogy a `Person` és a `Student` osztályok `printInformation()` metódusai kissé eltérő információkat adnak ki. És hozzáadhatunk más osztályokat is (például `Employee`), amelyek ennek a metódusnak más megvalósításait biztosítják. A különböző osztályok objektumainak azt a képességét, hogy ugyanarra a metódusra különböző módon reagáljanak, polimorfizmusnak nevezzük:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Kompozíció .[#toc-composition]
+------------------------------
+
+A kompozíció egy olyan technika, ahol ahelyett, hogy egy másik osztály tulajdonságait és metódusait örökölnénk, egyszerűen csak használjuk annak példányát a saját osztályunkban. Ez lehetővé teszi, hogy több osztály funkcionalitását és tulajdonságait kombináljuk anélkül, hogy bonyolult öröklési struktúrákat hoznánk létre.
+
+Például van egy `Engine` és egy `Car` osztályunk. Ahelyett, hogy azt mondanánk, hogy "Egy autó egy motor", azt mondjuk, hogy "Egy autónak van egy motorja", ami egy tipikus kompozíciós kapcsolat.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Itt a `Car` nem rendelkezik a `Engine` osztály összes tulajdonságával és metódusával, de a `$engine` tulajdonságon keresztül hozzáférhet azokhoz.
+
+A kompozíció előnye a nagyobb tervezési rugalmasság és a jobb alkalmazkodóképesség a jövőbeli változásokhoz.
+
+
+Láthatóság .[#toc-visibility]
+-----------------------------
+
+A PHP-ben az osztályok tulajdonságai, metódusai és konstansai számára meghatározható a "láthatóság". A láthatóság határozza meg, hogy hol lehet hozzáférni ezekhez az elemekhez.
+
+1. **Public:** Ha egy elemet `public`-ként jelölünk, az azt jelenti, hogy bárhonnan, akár az osztályon kívülről is elérhetjük.
+
+2. **Védett:** Egy `protected` jelű elem csak az osztályon belül és annak összes leszármazottján (az osztályból öröklődő osztályok) belül érhető el.
+
+3. **Privát:** Ha egy elem `private`, akkor csak azon az osztályon belül érhető el, ahol definiálták.
+
+Ha nem adja meg a láthatóságot, a PHP automatikusan `public` értékre állítja.
+
+Nézzünk meg egy példakódot:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Folytatva az osztályöröklést:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+Ebben az esetben a `printProperties()` metódus a `ChildClass` osztályban hozzáférhet a nyilvános és védett tulajdonságokhoz, de nem férhet hozzá a szülőosztály privát tulajdonságaihoz.
+
+Az adatoknak és a metódusoknak a lehető legrejtettebbnek kell lenniük, és csak egy meghatározott interfészen keresztül lehet őket elérni. Ez lehetővé teszi, hogy az osztály belső implementációját megváltoztassa anélkül, hogy a kód többi részét befolyásolná.
+
+
+Végleges kulcsszó .[#toc-final-keyword]
+---------------------------------------
+
+A PHP-ben a `final` kulcsszót használhatjuk, ha meg akarjuk akadályozni, hogy egy osztály, metódus vagy konstans öröklődjön vagy felülíródjon. Ha egy osztályt `final` jelöli, akkor nem bővíthető. Ha egy metódus `final`-ként van megjelölve, akkor nem lehet felülírni egy alosztályban.
+
+Ha tudatában vagyunk annak, hogy egy bizonyos osztály vagy metódus nem lesz többé módosítható, könnyebben tudunk változtatásokat végrehajtani anélkül, hogy aggódnánk a lehetséges konfliktusok miatt. Például hozzáadhatunk egy új metódust anélkül, hogy attól kellene tartanunk, hogy egy leszármazottnak már van egy ugyanilyen nevű metódusa, ami ütközéshez vezethet. Vagy megváltoztathatjuk egy metódus paramétereit, szintén anélkül, hogy azt kockáztatnánk, hogy következetlenséget okozunk egy leszármazottban lévő felülhajtott metódussal.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+Ebben a példában a `FinalClass` végleges osztályból való öröklés megkísérlése hibát eredményez.
+
+
+Statikus tulajdonságok és metódusok .[#toc-static-properties-and-methods]
+-------------------------------------------------------------------------
+
+Amikor egy osztály "statikus" elemeiről beszélünk a PHP-ben, akkor olyan metódusokra és tulajdonságokra gondolunk, amelyek magához az osztályhoz tartoznak, nem pedig az osztály egy adott példányához. Ez azt jelenti, hogy nem kell létrehozni az osztály egy példányát ahhoz, hogy hozzáférjünk hozzájuk. Ehelyett közvetlenül az osztály nevén keresztül hívja meg vagy éri el őket.
+
+Ne feledje, hogy mivel a statikus elemek az osztályhoz tartoznak, nem pedig annak példányaihoz, nem használhatja a `$this` pszeudováltozót statikus metódusokon belül.
+
+A statikus tulajdonságok használata [buktatókkal teli homályos kódhoz |dependency-injection:global-state] vezet, ezért soha ne használd őket, és itt nem is mutatunk példát. A statikus metódusok viszont hasznosak. Íme egy példa:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+Ebben a példában létrehoztunk egy `Calculator` osztályt két statikus metódussal. Ezeket a metódusokat közvetlenül meg tudjuk hívni anélkül, hogy az osztály példányát létrehoznánk a `::` operátor segítségével. A statikus metódusok különösen hasznosak olyan műveleteknél, amelyek nem függnek egy adott osztálypéldány állapotától.
+
+
+Osztálykonstansok .[#toc-class-constants]
+-----------------------------------------
+
+Az osztályokon belül lehetőségünk van konstansok definiálására. A konstansok olyan értékek, amelyek a program végrehajtása során soha nem változnak. A változókkal ellentétben a konstansok értéke változatlan marad.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+Ebben a példában van egy `Car` osztályunk a `NumberOfWheels` konstanssal. Az osztályon belüli konstans elérésekor az osztály neve helyett a `self` kulcsszót használhatjuk.
+
+
+Objektum interfészek .[#toc-object-interfaces]
+----------------------------------------------
+
+Az objektum interfészek az osztályok "szerződéseiként" működnek. Ha egy osztálynak egy objektum interfészt kell implementálnia, akkor tartalmaznia kell az összes metódust, amelyet az interfész definiál. Ez egy nagyszerű módja annak, hogy bizonyos osztályok azonos "szerződést" vagy struktúrát tartsanak be.
+
+A PHP-ben az interfészeket a `interface` kulcsszóval definiáljuk. Az interfészben definiált összes metódus nyilvános (`public`). Amikor egy osztály megvalósít egy interfészt, akkor a `implements` kulcsszót használja.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Ha egy osztály megvalósít egy interfészt, de nem minden elvárt metódus van definiálva, a PHP hibát fog dobni.
+
+Egy osztály egyszerre több interfészt is megvalósíthat, ami eltér az örökléstől, ahol egy osztály csak egy osztálytól örökölhet:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Absztrakt osztályok .[#toc-abstract-classes]
+--------------------------------------------
+
+Az absztrakt osztályok más osztályok alapsablonjaiként szolgálnak, de közvetlenül nem hozhatók létre példányaik. Teljes metódusok és olyan absztrakt metódusok keverékét tartalmazzák, amelyeknek nincs meghatározott tartalma. Az absztrakt osztályokból öröklődő osztályoknak meg kell adniuk a szülőktől származó összes absztrakt metódus definícióját.
+
+Az absztrakt osztályok definiálására a `abstract` kulcsszót használjuk.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+Ebben a példában egy absztrakt osztályunk van egy reguláris és egy absztrakt metódussal. Ezután van egy `Child` osztályunk, amely a `AbstractClass` osztályból örököl, és implementációt biztosít az absztrakt metódushoz.
+
+Miben különböznek az interfészek és az absztrakt osztályok? Az absztrakt osztályok absztrakt és konkrét metódusokat is tartalmazhatnak, míg az interfészek csak azt határozzák meg, hogy az osztálynak milyen metódusokat kell implementálnia, de implementációt nem biztosítanak. Egy osztály csak egy absztrakt osztálytól örökölhet, de tetszőleges számú interfészt implementálhat.
+
+
+Típusellenőrzés .[#toc-type-checking]
+-------------------------------------
+
+A programozásban alapvető fontosságú annak biztosítása, hogy az adatok, amelyekkel dolgozunk, megfelelő típusúak legyenek. A PHP-ben vannak olyan eszközeink, amelyek ezt a biztosítékot nyújtják. Az adatok megfelelő típusának ellenőrzését "típusellenőrzésnek" nevezzük.
+
+Típusok, amelyekkel a PHP-ben találkozhatunk:
+
+1. **Bázis típusok**: Ezek közé tartozik a `int` (egész számok), `float` (lebegőpontos számok), `bool` (boolék), `string` (karakterláncok), `array` (tömbök) és `null`.
+2. **osztályok**: Amikor azt akarjuk, hogy egy érték egy adott osztály példánya legyen.
+3. **Interfészek**: Meghatározza azon metódusok halmazát, amelyeket egy osztálynak implementálnia kell. Egy interfésznek megfelelő értéknek rendelkeznie kell ezekkel a metódusokkal.
+4. **Keverék típusok**: Megadhatjuk, hogy egy változónak több megengedett típusa is lehet.
+5. **Void**: Ez a speciális típus azt jelzi, hogy egy függvény vagy metódus nem ad vissza értéket.
+
+Lássuk, hogyan módosíthatjuk a kódot a típusok felvételére:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Így biztosítjuk, hogy a kódunk a megfelelő típusú adatokat várja el és a megfelelő típusú adatokkal dolgozik, ami segít megelőzni a lehetséges hibákat.
+
+Néhány típus nem írható közvetlenül PHP-ben. Ebben az esetben a phpDoc kommentben szerepelnek, ami a PHP kód dokumentálásának szabványos formátuma, a `/**` kezdődik és a `*/` végződik. Lehetővé teszi, hogy osztályok, metódusok stb. leírását adjuk hozzá. Valamint az összetett típusok felsorolását az úgynevezett annotációk segítségével `@var`, `@param` és `@return`. Ezeket a típusokat aztán a statikus kódelemző eszközök használják, de maga a PHP nem ellenőrzi őket.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Összehasonlítás és azonosság .[#toc-comparison-and-identity]
+------------------------------------------------------------
+
+A PHP-ben kétféleképpen lehet objektumokat összehasonlítani:
+
+1. Érték-összehasonlítás `==`: Ellenőrzi, hogy az objektumok ugyanabba az osztályba tartoznak-e, és tulajdonságaikban ugyanazok az értékek szerepelnek-e.
+2. Azonosság `===`: Ellenőrzi, hogy az objektum azonos példányáról van-e szó.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+A `instanceof` Üzemeltető .[#toc-the-instanceof-operator]
+---------------------------------------------------------
+
+A `instanceof` operátor lehetővé teszi annak meghatározását, hogy egy adott objektum egy adott osztály példánya, leszármazottja, vagy egy bizonyos interfész megvalósítója-e.
+
+Képzeljük el, hogy van egy `Person` osztályunk és egy másik osztályunk, a `Student`, amely a `Person` leszármazottja:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+A kimenetekből látható, hogy a `$student` objektumot a `Student` és a `Person` osztályok példányának tekintjük.
+
+
+Folyékony interfészek .[#toc-fluent-interfaces]
+-----------------------------------------------
+
+A "folyékony interfész" egy olyan technika az OOP-ban, amely lehetővé teszi a metódusok egyetlen hívással történő láncolását. Ez gyakran egyszerűsíti és egyértelművé teszi a kódot.
+
+A folyékony interfész kulcseleme, hogy a lánc minden egyes metódusa az aktuális objektumra való hivatkozást adja vissza. Ezt a `return $this;` használatával érjük el a metódus végén. Ez a programozási stílus gyakran társul a "setters" nevű metódusokkal, amelyek az objektum tulajdonságainak értékeit állítják be.
+
+Nézzük meg, hogyan nézhet ki egy folyékony interfész az e-mailek küldéséhez:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+Ebben a példában a `setFrom()`, `setRecipient()` és `setMessage()` metódusok a megfelelő értékek (feladó, címzett, üzenet tartalma) beállítására szolgálnak. Az egyes értékek beállítása után a metódusok visszaadják az aktuális objektumot (`$email`), ami lehetővé teszi számunkra, hogy egy másik metódust láncoljunk utána. Végül meghívjuk a `send()` metódust, amely ténylegesen elküldi az e-mailt.
+
+A folyékony interfészeknek köszönhetően olyan kódot írhatunk, amely intuitív és könnyen olvasható.
+
+
+Másolás a `clone` címen .[#toc-copying-with-clone]
+--------------------------------------------------
+
+A PHP-ben a `clone` operátor segítségével létrehozhatjuk egy objektum másolatát. Így egy új, azonos tartalmú példányt kapunk.
+
+Ha egy objektum másolásakor szükségünk van néhány tulajdonságának módosítására, akkor az osztályban definiálhatunk egy speciális `__clone()` metódust. Ez a metódus automatikusan meghívódik, amikor az objektumot klónozzuk.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+Ebben a példában van egy `Sheep` osztályunk, amelynek egy tulajdonsága a `$name`. Amikor klónozzuk ennek az osztálynak egy példányát, a `__clone()` metódus biztosítja, hogy a klónozott bárány neve a "Clone of" előtagot kapja.
+
+
+A  tulajdonságok. .[#toc-traits]
+--------------------------------
+
+A PHP-ban a Traits egy olyan eszköz, amely lehetővé teszi a metódusok, tulajdonságok és konstansok megosztását az osztályok között, és megakadályozza a kód duplikálását. Úgy gondolhatsz rájuk, mint egy "másolás és beillesztés" mechanizmusra (Ctrl-C és Ctrl-V), ahol egy tulajdonság tartalma "beillesztésre" kerül az osztályokba. Ez lehetővé teszi a kód újrafelhasználását anélkül, hogy bonyolult osztályhierarchiákat kellene létrehozni.
+
+Nézzünk meg egy egyszerű példát a vonások PHP-ban való használatára:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+Ebben a példában van egy `Honking` nevű tulajdonságunk, amely egy metódust tartalmaz: `honk()`. Ezután van két osztályunk: `Car` és `Truck`, amelyek mindkettő a `Honking` tulajdonságot használja. Ennek eredményeképpen mindkét osztály "rendelkezik" a `honk()` metódussal, és mindkét osztály objektumain meg tudjuk hívni azt.
+
+A tulajdonságok lehetővé teszik az osztályok közötti egyszerű és hatékony kódmegosztást. Nem lépnek be az öröklési hierarchiába, azaz a `$car instanceof Honking` a `false`-t fogja visszaadni.
+
+
+Kivételek .[#toc-exceptions]
+----------------------------
+
+A kivételek az OOP-ban lehetővé teszik számunkra a hibák és váratlan helyzetek méltóságteljes kezelését a kódunkban. Ezek olyan objektumok, amelyek információt hordoznak egy hibáról vagy szokatlan helyzetről.
+
+A PHP-ben van egy beépített osztályunk, a `Exception`, amely az összes kivétel alapjául szolgál. Ez több olyan metódussal rendelkezik, amelyek lehetővé teszik számunkra, hogy több információt kapjunk a kivételről, például a hibaüzenetet, a fájlt és a sort, ahol a hiba történt, stb.
+
+Ha hiba lép fel a kódban, a `throw` kulcsszóval "dobhatjuk" a kivételt.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Ha a `division()` függvény második argumentumként null értéket kap, akkor a `'Division by zero!'` hibaüzenetű kivételt dob. Annak érdekében, hogy a program ne essen össze a kivétel dobásakor, a `try/catch` blokkban csapdába ejtjük azt:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Az olyan kódot, amely kivételt dobhat, egy blokkba csomagoljuk `try`. Ha a kivételt dobjuk, a kód végrehajtása átkerül a `catch` blokkba, ahol a kivételt kezelhetjük (pl. hibaüzenetet írhatunk).
+
+A `try` és a `catch` blokkok után hozzáadhatunk egy opcionális `finally` blokkot, amely mindig végrehajtásra kerül, függetlenül attól, hogy a kivételt dobta-e vagy sem (még akkor is, ha a `return`, `break` vagy `continue` blokkot használjuk a `try` vagy `catch` blokkban):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Saját kivételosztályokat (hierarchiát) is létrehozhatunk, amelyek az Exception osztályból öröklődnek. Példaként tekintsünk egy egyszerű banki alkalmazást, amely lehetővé teszi a befizetéseket és a kifizetéseket:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Egyetlen `try` blokkhoz több `catch` blokk is megadható, ha különböző típusú kivételekre számít.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+Ebben a példában fontos megjegyezni a `catch` blokkok sorrendjét. Mivel minden kivétel a `BankingException`-tól öröklődik, ha ez a blokk lenne az első, akkor minden kivételt elkapnánk benne anélkül, hogy a kód elérné a következő `catch` blokkokat. Ezért fontos, hogy a specifikusabb (azaz másoktól öröklődő) kivételek a `catch` blokkok sorrendjében előrébb legyenek, mint a szülő kivételek.
+
+
+Iterációk .[#toc-iterations]
+----------------------------
+
+A PHP-ben a `foreach` ciklus segítségével végighaladhat az objektumokon, hasonlóan a tömbökön való végighaladáshoz. Ahhoz, hogy ez működjön, az objektumnak egy speciális interfészt kell megvalósítania.
+
+Az első lehetőség a `Iterator` interfész implementálása, amely a `current()` metódusokkal rendelkezik, amelyek visszaadják az aktuális értéket, a `key()` metódus visszaadja a kulcsot, a `next()` metódus a következő értékre lép, a `rewind()` metódus az elejére lép, és a `valid()` metódus ellenőrzi, hogy a végén vagyunk-e már.
+
+A másik lehetőség a `IteratorAggregate` interfész implementálása, amelynek csak egy metódusa van: `getIterator()`. Ez vagy egy helyőrző objektumot ad vissza, amely a traverzálást biztosítja, vagy lehet egy generátor, ami egy speciális függvény, amely a `yield` segítségével adja vissza a kulcsokat és az értékeket egymás után:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Legjobb gyakorlatok .[#toc-best-practices]
+------------------------------------------
+
+Ha már az objektumorientált programozás alapelveivel megismerkedtél, elengedhetetlen, hogy az OOP legjobb gyakorlataira koncentrálj. Ezek segítenek olyan kódot írni, amely nemcsak funkcionális, hanem olvasható, érthető és könnyen karbantartható is.
+
+1) **Separation of Concerns**: Minden osztálynak egyértelműen meghatározott felelősségi körrel kell rendelkeznie, és csak egy elsődleges feladattal kell foglalkoznia. Ha egy osztály túl sok mindent csinál, célszerű lehet kisebb, specializált osztályokra bontani.
+2) **Kapszulázás**: Az adatoknak és a metódusoknak a lehető legrejtettebbnek kell lenniük, és csak egy meghatározott interfészen keresztül lehet hozzájuk hozzáférni. Ez lehetővé teszi, hogy egy osztály belső megvalósítását megváltoztassuk anélkül, hogy a kód többi részét befolyásolná.
+3) **Függőségi injektálás**: Ahelyett, hogy közvetlenül egy osztályon belül hoznánk létre függőségeket, inkább kívülről "injektáljuk" azokat. Ennek az elvnek a mélyebb megértéséhez ajánljuk a [Dependency Injection fejezeteket |dependency-injection:introduction].
diff --git a/nette/hu/troubleshooting.texy b/nette/hu/troubleshooting.texy
index 4b9b567e85..765855a096 100644
--- a/nette/hu/troubleshooting.texy
+++ b/nette/hu/troubleshooting.texy
@@ -18,7 +18,7 @@ A hiba okát mindig megtalálhatja a `log/` könyvtárban. Ha azonban a hibaüze
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // az Ön IP-címe
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Az 500-as hiba egyik leggyakoribb oka az elavult gyorsítótár. Míg a Nette ok
 Amikor minden oldal (a kezdőlap kivételével) 404-es hibát ad vissza, úgy tűnik, hogy a szerver konfigurációs problémája van a [szép URL-eknél |#How to Configure a Server for Nice URLs?].
 
 
+Hogyan lehet letiltani a gyorsítótárat a fejlesztés során? .[#toc-how-to-disable-cache-during-development]
+----------------------------------------------------------------------------------------------------------
+A Nette okos, és nem kell kikapcsolni benne a gyorsítótárazást. A fejlesztés során automatikusan frissíti a gyorsítótárat, ha változás történik a sablonban vagy a DI konténer konfigurációjában. Ráadásul a fejlesztési mód automatikus felismeréssel aktiválódik, így általában nem kell semmit, [vagy csak az IP-címet |application:bootstrap#development-vs-production-mode] konfigurálni.
+
+A router hibakeresése során javasoljuk a böngésző gyorsítótárának letiltását, ahol például az átirányítások tárolódhatnak: nyissa meg a Developer Tools-t (Ctrl+Shift+I vagy Cmd+Option+I), és a Hálózat panelen jelölje be a gyorsítótár letiltására szolgáló négyzetet.
+
+
 Hiba `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 --------------------------------------------------------------------------------------------------------------------
 Ez a hiba akkor jelentkezik, ha a PHP-t a 8.1-es verzióra frissítette, de a Nette-et használja, amely nem kompatibilis vele. A megoldás tehát a Nette újabb verzióra való frissítése a `composer update` segítségével. A Nette a 3.0-s verzió óta támogatja a PHP 8.1-es verzióját. Ha régebbi verziót használ (ezt a `composer.json` oldalon találja meg), [frissítse a Nette-et |migrations:en], vagy maradjon a PHP 8.0-nál.
@@ -67,7 +74,7 @@ A Nette mintaprojektekben használt `www/` könyvtár a projekt úgynevezett nyi
 
 Ahhoz, hogy az alkalmazás a tárhelyen fusson, a tárhely konfigurációjában a document-root-ot erre a könyvtárra kell állítani. Vagy, ha a tárhelyen van egy előre elkészített mappa a nyilvános könyvtár számára más névvel (például `web`, `public_html` stb.), egyszerűen nevezze át `www/`.
 
-A megoldás **nem** a `www/` mappától való "megszabadulás" a `.htaccess` fájlban vagy a routerben található szabályok segítségével. Ha a tárhely nem engedné meg, hogy a document-root-ot egy alkönyvtárra állítsa (azaz a nyilvános könyvtár felett egy szinttel magasabb könyvtárakat hozzon létre), keressen másikat. Ellenkező esetben jelentős biztonsági kockázatot vállalna. Olyan lenne, mintha olyan lakásban élnél, ahol nem tudod becsukni a bejárati ajtót, és az mindig nyitva van.
+A megoldás **nem** az, hogy a `www/` kivételével minden mappához való hozzáférést megakadályozzuk a `.htaccess` fájlban vagy az útválasztóban található szabályok segítségével. Ha a tárhelye nem teszi lehetővé a dokumentum gyökerének alkönyvtárba helyezését (azaz a nyilvános könyvtár feletti könyvtárak létrehozását), akkor más tárhelyszolgáltatást kell keresnie. Ellenkező esetben jelentős biztonsági kockázatoknak teszi ki magát. Ez olyan lenne, mintha olyan lakásban élne, ahol a bejárati ajtót nem lehet bezárni, és mindig nyitva van.
 
 
 Hogyan konfiguráljunk egy kiszolgálót a szép URL-ekhez? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/it/@home.texy b/nette/it/@home.texy
index 73dfd0447c..758fd70193 100644
--- a/nette/it/@home.texy
+++ b/nette/it/@home.texy
@@ -84,11 +84,11 @@ Utilità
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hashing della password |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Tipi PHP |utils:type]
 - [Stringhe |utils:Strings]
 - [Validatori |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...altri |utils:]
 </div>
diff --git a/nette/it/installation.texy b/nette/it/installation.texy
index 48fbf452d1..cfdcbe8aef 100644
--- a/nette/it/installation.texy
+++ b/nette/it/installation.texy
@@ -20,7 +20,7 @@ Nette offre una raccolta di pacchetti (librerie) utili e sofisticati per PHP. Pe
 composer require nette/utils
 ```
 
-Preferite un'interfaccia grafica? Consultate la [guida |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] all'installazione dei pacchetti nell'ambiente PhpStrom.
+Preferite un'interfaccia grafica? Consultate la [guida |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] all'installazione dei pacchetti nell'ambiente PhpStorm.
 
 
 Come avviare un nuovo progetto con Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/it/introduction-to-object-oriented-programming.texy b/nette/it/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..415dcf0c7b
--- /dev/null
+++ b/nette/it/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Introduzione alla programmazione orientata agli oggetti
+*******************************************************
+
+.[perex]
+Il termine "OOP" sta per Object-Oriented Programming (programmazione orientata agli oggetti), un modo per organizzare e strutturare il codice. L'OOP ci permette di vedere un programma come un insieme di oggetti che comunicano tra loro, piuttosto che come una sequenza di comandi e funzioni.
+
+Nell'OOP, un "oggetto" è un'unità che contiene dati e funzioni che operano su tali dati. Gli oggetti vengono creati sulla base di "classi", che possono essere intese come progetti o modelli di oggetti. Una volta che abbiamo una classe, possiamo creare la sua "istanza", che è un oggetto specifico creato a partire da quella classe.
+
+Vediamo come creare una semplice classe in PHP. Quando si definisce una classe, si usa la parola chiave "class", seguita dal nome della classe e poi dalle parentesi graffe che racchiudono le funzioni della classe (chiamate "metodi") e le variabili della classe (chiamate "proprietà" o "attributi"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+In questo esempio, abbiamo creato una classe chiamata `Car` con una funzione (o "metodo") chiamata `honk`.
+
+Ogni classe dovrebbe risolvere un solo compito principale. Se una classe fa troppe cose, può essere opportuno dividerla in classi più piccole e specializzate.
+
+Le classi sono in genere memorizzate in file separati per mantenere il codice organizzato e facile da navigare. Il nome del file deve corrispondere al nome della classe, quindi per la classe `Car` il nome del file sarà `Car.php`.
+
+Quando si nominano le classi, è bene seguire la convenzione "PascalCase", cioè ogni parola del nome inizia con una lettera maiuscola e non ci sono sottolineature o altri separatori. I metodi e le proprietà seguono la convenzione "camelCase", cioè iniziano con una lettera minuscola.
+
+Alcuni metodi in PHP hanno ruoli speciali e sono preceduti da `__` (due trattini bassi). Uno dei metodi speciali più importanti è il "costruttore", contrassegnato con `__construct`. Il costruttore è un metodo che viene chiamato automaticamente quando si crea una nuova istanza di una classe.
+
+Spesso si usa il costruttore per impostare lo stato iniziale di un oggetto. Per esempio, quando si crea un oggetto che rappresenta una persona, si può usare il costruttore per impostarne l'età, il nome o altri attributi.
+
+Vediamo come utilizzare un costruttore in PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+In questo esempio, la classe `Person` ha una proprietà (variabile) `$age` e un costruttore che imposta questa proprietà. Il metodo `howOldAreYou()` consente di accedere all'età della persona.
+
+La pseudo-variabile `$this` viene utilizzata all'interno della classe per accedere alle proprietà e ai metodi dell'oggetto.
+
+La parola chiave `new` viene utilizzata per creare una nuova istanza di una classe. Nell'esempio precedente, abbiamo creato una nuova persona di 25 anni.
+
+È anche possibile impostare valori predefiniti per i parametri del costruttore, se non sono specificati durante la creazione di un oggetto. Per esempio:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+In questo esempio, se non si specifica l'età quando si crea un oggetto `Person`, verrà usato il valore predefinito di 20.
+
+La cosa bella è che la definizione della proprietà con la sua inizializzazione tramite il costruttore può essere accorciata e semplificata in questo modo:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Per completezza, oltre ai costruttori, gli oggetti possono avere dei distruttori (metodo `__destruct`) che vengono chiamati prima che l'oggetto venga rilasciato dalla memoria.
+
+
+Spazi dei nomi .[#toc-namespaces]
+---------------------------------
+
+Gli spazi dei nomi consentono di organizzare e raggruppare classi, funzioni e costanti correlate, evitando conflitti di denominazione. Si possono considerare come le cartelle di un computer, dove ogni cartella contiene file relativi a un progetto o a un argomento specifico.
+
+Gli spazi dei nomi sono particolarmente utili in progetti di grandi dimensioni o quando si utilizzano librerie di terze parti in cui potrebbero sorgere conflitti di denominazione delle classi.
+
+Immaginate di avere una classe chiamata `Car` nel vostro progetto e di volerla inserire in uno spazio dei nomi chiamato `Transport`. Si procederà in questo modo:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Se si vuole utilizzare la classe `Car` in un altro file, occorre specificare da quale spazio dei nomi proviene la classe:
+
+```php
+$car = new Transport\Car;
+```
+
+Per semplificare, si può specificare all'inizio del file quale classe di un particolare spazio dei nomi si vuole utilizzare, consentendo di creare istanze senza citare il percorso completo:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Eredità .[#toc-inheritance]
+---------------------------
+
+L'ereditarietà è uno strumento della programmazione orientata agli oggetti che consente di creare nuove classi basate su quelle esistenti, ereditandone proprietà e metodi ed estendendole o ridefinendole a seconda delle necessità. L'ereditarietà garantisce la riusabilità del codice e la gerarchia delle classi.
+
+In parole povere, se abbiamo una classe e vogliamo crearne un'altra derivata da essa ma con alcune modifiche, possiamo "ereditare" la nuova classe da quella originale.
+
+In PHP, l'ereditarietà viene implementata utilizzando la parola chiave `extends`.
+
+La nostra classe `Person` memorizza informazioni sull'età. Possiamo avere un'altra classe, `Student`, che estende `Person` e aggiunge informazioni sul campo di studi.
+
+Vediamo un esempio:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Come funziona questo codice?
+
+- Abbiamo usato la parola chiave `extends` per estendere la classe `Person`, il che significa che la classe `Student` eredita tutti i metodi e le proprietà da `Person`.
+
+- La parola chiave `parent::` consente di richiamare i metodi della classe padre. In questo caso, abbiamo richiamato il costruttore della classe `Person` prima di aggiungere la nostra funzionalità alla classe `Student`. E allo stesso modo, il metodo dell'antenato `printInformation()` prima di elencare le informazioni sugli studenti.
+
+L'ereditarietà è pensata per le situazioni in cui esiste una relazione "is a" tra le classi. Per esempio, un `Student` è un `Person`. Un gatto è un animale. Ci consente, nei casi in cui ci aspettiamo un oggetto (ad esempio, "Persona") nel codice, di utilizzare invece un oggetto derivato (ad esempio, "Studente").
+
+È essenziale rendersi conto che lo scopo principale dell'ereditarietà **non** è quello di prevenire la duplicazione del codice. Al contrario, un uso improprio dell'ereditarietà può portare a codice complesso e difficile da mantenere. Se non c'è una relazione "è un" tra le classi, dovremmo considerare la composizione invece dell'ereditarietà.
+
+Si noti che i metodi `printInformation()` delle classi `Person` e `Student` forniscono informazioni leggermente diverse. È possibile aggiungere altre classi (come `Employee`) che forniranno altre implementazioni di questo metodo. La capacità di oggetti di classi diverse di rispondere allo stesso metodo in modi diversi si chiama polimorfismo:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Composizione .[#toc-composition]
+--------------------------------
+
+La composizione è una tecnica in cui, invece di ereditare proprietà e metodi da un'altra classe, si usa semplicemente la sua istanza nella propria classe. Questo ci permette di combinare funzionalità e proprietà di più classi senza creare complesse strutture di ereditarietà.
+
+Ad esempio, abbiamo una classe `Engine` e una classe `Car`. Invece di dire "Un'auto è un motore", diciamo "Un'auto ha un motore", che è una tipica relazione di composizione.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+In questo caso, la classe `Car` non possiede tutte le proprietà e i metodi della classe `Engine`, ma vi ha accesso attraverso la proprietà `$engine`.
+
+Il vantaggio della composizione è una maggiore flessibilità di progettazione e una migliore adattabilità ai cambiamenti futuri.
+
+
+Visibilità .[#toc-visibility]
+-----------------------------
+
+In PHP, è possibile definire la "visibilità" per le proprietà, i metodi e le costanti delle classi. La visibilità determina dove è possibile accedere a questi elementi.
+
+1. Se un elemento è contrassegnato come `public`, significa che è possibile accedervi da qualsiasi punto, anche al di fuori della classe.
+
+2. Un elemento contrassegnato come `protected` è accessibile solo all'interno della classe e di tutti i suoi discendenti (classi che ereditano da essa).
+
+3. Se un elemento è `private`, è possibile accedervi solo dalla classe in cui è stato definito.
+
+Se non si specifica la visibilità, PHP la imposterà automaticamente a `public`.
+
+Vediamo un esempio di codice:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Continuare con l'ereditarietà delle classi:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+In questo caso, il metodo `printProperties()` della classe `ChildClass` può accedere alle proprietà pubbliche e protette, ma non alle proprietà private della classe padre.
+
+I dati e i metodi devono essere il più possibile nascosti e accessibili solo attraverso un'interfaccia definita. Ciò consente di modificare l'implementazione interna della classe senza influenzare il resto del codice.
+
+
+Parola chiave finale .[#toc-final-keyword]
+------------------------------------------
+
+In PHP, si può usare la parola chiave `final` se si vuole impedire che una classe, un metodo o una costante vengano ereditati o sovrascritti. Quando una classe è contrassegnata come `final`, non può essere estesa. Quando un metodo è contrassegnato come `final`, non può essere sovrascritto in una sottoclasse.
+
+Essere consapevoli che una certa classe o un certo metodo non saranno più modificati ci permette di apportare modifiche più facilmente senza preoccuparci di potenziali conflitti. Ad esempio, possiamo aggiungere un nuovo metodo senza temere che un discendente abbia già un metodo con lo stesso nome, causando una collisione. Oppure possiamo cambiare i parametri di un metodo, sempre senza il rischio di causare incoerenze con un metodo sovrascritto in un discendente.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+In questo esempio, il tentativo di ereditare dalla classe finale `FinalClass` produrrà un errore.
+
+
+Proprietà e metodi statici .[#toc-static-properties-and-methods]
+----------------------------------------------------------------
+
+Quando si parla di elementi "statici" di una classe in PHP, si intendono metodi e proprietà che appartengono alla classe stessa, non a un'istanza specifica della classe. Ciò significa che non è necessario creare un'istanza della classe per accedervi. Al contrario, è possibile chiamarli o accedervi direttamente attraverso il nome della classe.
+
+Tenere presente che, poiché gli elementi statici appartengono alla classe e non alle sue istanze, non è possibile utilizzare la pseudo-variabile `$this` all'interno dei metodi statici.
+
+L'uso di proprietà statiche porta a un [codice offuscato e pieno di insidie |dependency-injection:global-state], quindi non si dovrebbe mai usarle e non ne mostreremo un esempio qui. D'altra parte, i metodi statici sono utili. Ecco un esempio:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+In questo esempio, abbiamo creato una classe `Calculator` con due metodi statici. Possiamo chiamare questi metodi direttamente, senza creare un'istanza della classe, utilizzando l'operatore `::`. I metodi statici sono particolarmente utili per le operazioni che non dipendono dallo stato di una specifica istanza della classe.
+
+
+Costanti di classe .[#toc-class-constants]
+------------------------------------------
+
+All'interno delle classi è possibile definire delle costanti. Le costanti sono valori che non cambiano mai durante l'esecuzione del programma. A differenza delle variabili, il valore di una costante rimane invariato.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+In questo esempio, abbiamo una classe `Car` con la costante `NumberOfWheels`. Quando si accede alla costante all'interno della classe, si può usare la parola chiave `self` invece del nome della classe.
+
+
+Interfacce di oggetti .[#toc-object-interfaces]
+-----------------------------------------------
+
+Le interfacce di oggetti agiscono come "contratti" per le classi. Se una classe deve implementare un'interfaccia di oggetti, deve contenere tutti i metodi definiti dall'interfaccia. È un ottimo modo per garantire che alcune classi aderiscano allo stesso "contratto" o struttura.
+
+In PHP, le interfacce sono definite utilizzando la parola chiave `interface`. Tutti i metodi definiti in un'interfaccia sono pubblici (`public`). Quando una classe implementa un'interfaccia, utilizza la parola chiave `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Se una classe implementa un'interfaccia, ma non tutti i metodi previsti sono definiti, PHP lancia un errore.
+
+Una classe può implementare più interfacce contemporaneamente, a differenza dell'ereditarietà, dove una classe può ereditare solo da una classe:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Classi astratte .[#toc-abstract-classes]
+----------------------------------------
+
+Le classi astratte servono come modelli di base per altre classi, ma non è possibile creare direttamente le loro istanze. Contengono un mix di metodi completi e metodi astratti che non hanno un contenuto definito. Le classi che ereditano da classi astratte devono fornire le definizioni di tutti i metodi astratti del genitore.
+
+Per definire una classe astratta si usa la parola chiave `abstract`.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+In questo esempio, abbiamo una classe astratta con un metodo regolare e uno astratto. Poi abbiamo una classe `Child` che eredita da `AbstractClass` e fornisce un'implementazione per il metodo astratto.
+
+In cosa differiscono le interfacce e le classi astratte? Le classi astratte possono contenere sia metodi astratti che concreti, mentre le interfacce definiscono solo quali metodi la classe deve implementare, ma non forniscono alcuna implementazione. Una classe può ereditare da una sola classe astratta, ma può implementare un numero qualsiasi di interfacce.
+
+
+Verifica del tipo .[#toc-type-checking]
+---------------------------------------
+
+Nella programmazione è fondamentale assicurarsi che i dati con cui si lavora siano del tipo corretto. In PHP, disponiamo di strumenti che forniscono questa garanzia. Verificare che i dati siano del tipo corretto si chiama "controllo del tipo".
+
+Tipi che possiamo incontrare in PHP:
+
+1. **Tipi di base**: Questi includono `int` (numeri interi), `float` (numeri in virgola mobile), `bool` (valori booleani), `string` (stringhe), `array` (array) e `null`.
+2. **Classi**: Quando si vuole che un valore sia un'istanza di una classe specifica.
+3. **Interfacce**: Definisce un insieme di metodi che una classe deve implementare. Un valore che soddisfa un'interfaccia deve avere questi metodi.
+4. **Tipi misti**: Si può specificare che una variabile può avere più tipi consentiti.
+5. **Voide**: Questo tipo speciale indica che una funzione o un metodo non restituisce alcun valore.
+
+Vediamo come modificare il codice per includere i tipi:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+In questo modo, ci assicuriamo che il nostro codice si aspetti e lavori con dati del tipo corretto, aiutandoci a prevenire potenziali errori.
+
+Alcuni tipi non possono essere scritti direttamente in PHP. In questo caso, vengono elencati nel commento phpDoc, che è il formato standard per la documentazione del codice PHP, che inizia con `/**` e termina con `*/`. Esso consente di aggiungere descrizioni di classi, metodi e così via. E anche di elencare tipi complessi usando le cosiddette annotazioni `@var`, `@param` e `@return`. Questi tipi vengono poi utilizzati dagli strumenti di analisi statica del codice, ma non vengono controllati da PHP stesso.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Confronto e identità .[#toc-comparison-and-identity]
+----------------------------------------------------
+
+In PHP, è possibile confrontare gli oggetti in due modi:
+
+1. Confronto tra valori `==`: verifica se gli oggetti appartengono alla stessa classe e hanno gli stessi valori nelle loro proprietà.
+2. Identità `===`: verifica se si tratta della stessa istanza dell'oggetto.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+L'operatore di `instanceof` .[#toc-the-instanceof-operator]
+-----------------------------------------------------------
+
+L'operatore `instanceof` consente di determinare se un dato oggetto è un'istanza di una classe specifica, un discendente di quella classe o se implementa una certa interfaccia.
+
+Immaginiamo di avere una classe `Person` e un'altra classe `Student`, che è un discendente di `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Dai risultati, è evidente che l'oggetto `$student` è considerato un'istanza di entrambe le classi `Student` e `Person`.
+
+
+Interfacce fluenti .[#toc-fluent-interfaces]
+--------------------------------------------
+
+Una "interfaccia fluida" è una tecnica dell'OOP che consente di concatenare i metodi in un'unica chiamata. Questo spesso semplifica e chiarisce il codice.
+
+L'elemento chiave di un'interfaccia fluente è che ogni metodo della catena restituisce un riferimento all'oggetto corrente. Questo si ottiene utilizzando `return $this;` alla fine del metodo. Questo stile di programmazione è spesso associato ai metodi chiamati "setter", che impostano i valori delle proprietà di un oggetto.
+
+Vediamo come potrebbe essere un'interfaccia fluente per l'invio di e-mail:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+In questo esempio, i metodi `setFrom()`, `setRecipient()` e `setMessage()` sono usati per impostare i valori corrispondenti (mittente, destinatario, contenuto del messaggio). Dopo aver impostato ciascuno di questi valori, i metodi restituiscono l'oggetto corrente (`$email`), consentendoci di concatenare un altro metodo dopo di esso. Infine, chiamiamo il metodo `send()`, che invia effettivamente l'e-mail.
+
+Grazie alle interfacce fluide, possiamo scrivere codice intuitivo e facilmente leggibile.
+
+
+Copiare con `clone` .[#toc-copying-with-clone]
+----------------------------------------------
+
+In PHP, possiamo creare una copia di un oggetto usando l'operatore `clone`. In questo modo, si ottiene una nuova istanza con contenuti identici.
+
+Se durante la copia di un oggetto è necessario modificarne alcune proprietà, è possibile definire un metodo speciale `__clone()` nella classe. Questo metodo viene richiamato automaticamente quando l'oggetto viene clonato.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+In questo esempio, abbiamo una classe `Sheep` con una proprietà `$name`. Quando si clona un'istanza di questa classe, il metodo `__clone()` assicura che il nome della pecora clonata ottenga il prefisso "Clone di".
+
+
+Tratti .[#toc-traits]
+---------------------
+
+I tratti in PHP sono uno strumento che consente di condividere metodi, proprietà e costanti tra le classi, evitando la duplicazione del codice. Si può pensare a loro come a un meccanismo di "copia e incolla" (Ctrl-C e Ctrl-V), in cui il contenuto di un tratto viene "incollato" nelle classi. Ciò consente di riutilizzare il codice senza dover creare complicate gerarchie di classi.
+
+Vediamo un semplice esempio di utilizzo dei tratti in PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+In questo esempio, abbiamo un tratto chiamato `Honking` che contiene un metodo `honk()`. Abbiamo poi due classi: `Car` e `Truck`, che utilizzano entrambe il tratto `Honking`. Di conseguenza, entrambe le classi "possiedono" il metodo `honk()` e possiamo chiamarlo su oggetti di entrambe le classi.
+
+I tratti consentono di condividere facilmente ed efficacemente il codice tra le classi. Non entrano nella gerarchia ereditaria, cioè `$car instanceof Honking` restituirà `false`.
+
+
+Eccezioni
+---------
+
+Le eccezioni nell'OOP ci permettono di gestire con grazia gli errori e le situazioni inaspettate nel nostro codice. Sono oggetti che contengono informazioni su un errore o una situazione insolita.
+
+In PHP, abbiamo una classe incorporata `Exception`, che serve come base per tutte le eccezioni. Questa classe ha diversi metodi che ci permettono di ottenere ulteriori informazioni sull'eccezione, come il messaggio di errore, il file e la riga in cui si è verificato l'errore, ecc.
+
+Quando si verifica un errore nel codice, si può "lanciare" l'eccezione usando la parola chiave `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Quando la funzione `division()` riceve null come secondo argomento, lancia un'eccezione con il messaggio di errore `'Division by zero!'`. Per evitare che il programma si blocchi quando viene lanciata l'eccezione, la intrappoliamo nel blocco `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Il codice che può lanciare un'eccezione viene avvolto in un blocco `try`. Se l'eccezione viene lanciata, l'esecuzione del codice passa a un blocco `catch`, dove è possibile gestire l'eccezione (ad esempio, scrivere un messaggio di errore).
+
+Dopo i blocchi `try` e `catch`, si può aggiungere un blocco opzionale `finally`, che viene sempre eseguito, indipendentemente dal fatto che l'eccezione sia stata lanciata o meno (anche se si utilizzano `return`, `break`, o `continue` nel blocco `try` o `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Possiamo anche creare le nostre classi di eccezioni (gerarchia) che ereditano dalla classe Exception. A titolo di esempio, si consideri una semplice applicazione bancaria che consente depositi e prelievi:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+È possibile specificare più blocchi `catch` per un singolo blocco `try` se si prevedono diversi tipi di eccezioni.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+In questo esempio, è importante notare l'ordine dei blocchi `catch`. Poiché tutte le eccezioni ereditano da `BankingException`, se avessimo questo blocco per primo, tutte le eccezioni verrebbero catturate in esso, senza che il codice raggiunga i successivi blocchi `catch`. Pertanto, è importante che le eccezioni più specifiche (cioè quelle che ereditano da altre) si trovino più in alto nell'ordine dei blocchi `catch` rispetto alle loro eccezioni padre.
+
+
+Iterazioni .[#toc-iterations]
+-----------------------------
+
+In PHP, è possibile eseguire un ciclo di oggetti utilizzando il ciclo `foreach`, proprio come si fa con un array. Perché funzioni, l'oggetto deve implementare un'interfaccia speciale.
+
+La prima opzione è implementare l'interfaccia `Iterator`, che ha i metodi `current()` che restituisce il valore corrente, `key()` che restituisce la chiave, `next()` che passa al valore successivo, `rewind()` che passa all'inizio e `valid()` che controlla se siamo già alla fine.
+
+L'altra opzione è implementare un'interfaccia `IteratorAggregate`, che ha un solo metodo `getIterator()`. Questo metodo può restituire un oggetto segnaposto che fornirà l'attraversamento, oppure può essere un generatore, cioè una funzione speciale che utilizza `yield` per restituire chiavi e valori in sequenza:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Migliori pratiche .[#toc-best-practices]
+----------------------------------------
+
+Una volta acquisiti i principi di base della programmazione orientata agli oggetti, è fondamentale concentrarsi sulle best practice dell'OOP. Queste vi aiuteranno a scrivere codice non solo funzionale, ma anche leggibile, comprensibile e facilmente manutenibile.
+
+1) **Separazione delle preoccupazioni**: Ogni classe dovrebbe avere una responsabilità chiaramente definita e dovrebbe occuparsi di un solo compito primario. Se una classe fa troppe cose, potrebbe essere opportuno dividerla in classi più piccole e specializzate.
+2) **Incapsulamento**: I dati e i metodi devono essere il più possibile nascosti e accessibili solo attraverso un'interfaccia definita. Ciò consente di modificare l'implementazione interna di una classe senza influenzare il resto del codice.
+3) **Iniezione di dipendenze**: Invece di creare dipendenze direttamente all'interno di una classe, è opportuno "iniettarle" dall'esterno. Per una comprensione più approfondita di questo principio, si consiglia di leggere i [capitoli sulla Dependency Injection |dependency-injection:introduction].
diff --git a/nette/it/troubleshooting.texy b/nette/it/troubleshooting.texy
index 38016d0bfb..cbf29ca1f3 100644
--- a/nette/it/troubleshooting.texy
+++ b/nette/it/troubleshooting.texy
@@ -18,7 +18,7 @@ Questa pagina di errore viene visualizzata da Nette in modalità di produzione.
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // il vostro indirizzo IP
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Errore 404, il routing non funziona .[#toc-error-404-routing-not-working]
 Quando tutte le pagine (tranne la homepage) restituiscono un errore 404, sembra che ci sia un problema di configurazione del server per gli [URL più belli |#How to Configure a Server for Nice URLs?].
 
 
+Come disattivare la cache durante lo sviluppo? .[#toc-how-to-disable-cache-during-development]
+----------------------------------------------------------------------------------------------
+Nette è intelligente e non è necessario disabilitare la cache. Durante lo sviluppo, aggiorna automaticamente la cache ogni volta che c'è un cambiamento nel template o nella configurazione del contenitore DI. Inoltre, la modalità di sviluppo è attivata dal rilevamento automatico, quindi di solito non è necessario configurare nulla, [o solo l'indirizzo IP |application:bootstrap#development-vs-production-mode].
+
+Quando si esegue il debug del router, si consiglia di disabilitare la cache del browser, dove, ad esempio, potrebbero essere memorizzati i reindirizzamenti: aprire gli Strumenti per gli sviluppatori (Ctrl+Maiusc+I o Cmd+Option+I) e, nel pannello Rete, selezionare la casella per disabilitare la cache.
+
+
 Errore `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Questo errore si verifica se si è aggiornato PHP alla versione 8.1 ma si sta utilizzando Nette, che non è compatibile con essa. La soluzione è aggiornare Nette a una versione più recente utilizzando `composer update`. Nette supporta PHP 8.1 dalla versione 3.0. Se si sta utilizzando una versione più vecchia (lo si può scoprire consultando `composer.json`), [aggiornare Nette |migrations:en] o rimanere con PHP 8.0.
@@ -67,7 +74,7 @@ La directory `www/` utilizzata nei progetti di esempio di Nette è la cosiddetta
 
 Per eseguire l'applicazione sull'hosting, è necessario impostare la document-root su questa directory nella configurazione dell'hosting. Oppure, se l'hosting ha una cartella preconfezionata per la directory pubblica con un nome diverso (ad esempio `web`, `public_html` ecc.), è sufficiente rinominare `www/`.
 
-La soluzione **non** è quella di "sbarazzarsi" della cartella `www/` usando regole nel file `.htaccess` o nel router. Se l'hosting non vi permette di impostare document-root su una sottodirectory (cioè di creare directory un livello sopra la directory pubblica), cercatene un'altra. In caso contrario, si correrebbe un rischio significativo per la sicurezza. Sarebbe come vivere in un appartamento in cui non si può chiudere la porta d'ingresso, che rimane sempre aperta.
+La soluzione non è impedire l'accesso a tutte le cartelle tranne `www/` utilizzando regole nel file `.htaccess` o nel router. Se il vostro hosting non consente di impostare la radice del documento in una sottodirectory (cioè di creare directory un livello sopra la directory pubblica), dovreste cercare un altro servizio di hosting. In caso contrario, ci si esporrebbe a rischi significativi per la sicurezza. Sarebbe come vivere in un appartamento dove la porta d'ingresso non può essere chiusa ed è sempre spalancata.
 
 
 Come configurare un server per avere URL gradevoli? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/pl/@home.texy b/nette/pl/@home.texy
index 9868af29e3..6429bb7295 100644
--- a/nette/pl/@home.texy
+++ b/nette/pl/@home.texy
@@ -84,11 +84,11 @@ Narzędzia
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hashing hasła |security:passwords]
-- [SmartObject |utils:smartobject]
 - [Rodzaje PHP |utils:type]
 - [Struny |utils:strings]
 - [Walidatory |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...więcej |utils:]
 </div>
diff --git a/nette/pl/installation.texy b/nette/pl/installation.texy
index 6655f61a7f..8e2c2e70f7 100644
--- a/nette/pl/installation.texy
+++ b/nette/pl/installation.texy
@@ -20,7 +20,7 @@ Nette oferuje kolekcję przydatnych i zaawansowanych pakietów (bibliotek) dla P
 composer require nette/utils
 ```
 
-Wolisz interfejs graficzny? Zapoznaj się z [przewodnikiem |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] dotyczącym instalacji pakietów w środowisku PhpStrom.
+Wolisz interfejs graficzny? Zapoznaj się z [przewodnikiem |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] dotyczącym instalacji pakietów w środowisku PhpStorm.
 
 
 Jak rozpocząć nowy projekt z Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/pl/introduction-to-object-oriented-programming.texy b/nette/pl/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..2862ba8895
--- /dev/null
+++ b/nette/pl/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Wprowadzenie do programowania obiektowego
+*****************************************
+
+.[perex]
+Termin "OOP" oznacza programowanie obiektowe (Object-Oriented Programming), które jest sposobem organizacji i strukturyzacji kodu. OOP pozwala nam postrzegać program jako zbiór obiektów, które komunikują się ze sobą, a nie jako sekwencję poleceń i funkcji.
+
+W OOP "obiekt" to jednostka zawierająca dane i funkcje, które działają na tych danych. Obiekty są tworzone w oparciu o "klasy", które można rozumieć jako plany lub szablony obiektów. Gdy mamy już klasę, możemy utworzyć jej "instancję", która jest konkretnym obiektem utworzonym z tej klasy.
+
+Przyjrzyjmy się jak możemy stworzyć prostą klasę w PHP. Podczas definiowania klasy używamy słowa kluczowego "class", po którym następuje nazwa klasy, a następnie nawiasy klamrowe, które otaczają funkcje klasy (zwane "metodami") i zmienne klasy (zwane "właściwościami" lub "atrybutami"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+W tym przykładzie utworzyliśmy klasę o nazwie `Car` z jedną funkcją (lub "metodą") o nazwie `honk`.
+
+Każda klasa powinna rozwiązywać tylko jedno główne zadanie. Jeśli klasa wykonuje zbyt wiele zadań, może być wskazane podzielenie jej na mniejsze, wyspecjalizowane klasy.
+
+Klasy są zwykle przechowywane w oddzielnych plikach, aby kod był uporządkowany i łatwy w nawigacji. Nazwa pliku powinna być zgodna z nazwą klasy, więc dla klasy `Car` nazwa pliku brzmiałaby `Car.php`.
+
+Podczas nazywania klas dobrze jest przestrzegać konwencji "PascalCase", co oznacza, że każde słowo w nazwie zaczyna się wielką literą i nie ma podkreśleń ani innych separatorów. Metody i właściwości są zgodne z konwencją "camelCase", co oznacza, że zaczynają się od małej litery.
+
+Niektóre metody w PHP mają specjalne role i są poprzedzone `__` (dwa podkreślenia). Jedną z najważniejszych metod specjalnych jest "konstruktor", oznaczony jako `__construct`. Konstruktor jest metodą, która jest automatycznie wywoływana podczas tworzenia nowej instancji klasy.
+
+Często używamy konstruktora do ustawienia początkowego stanu obiektu. Na przykład, podczas tworzenia obiektu reprezentującego osobę, można użyć konstruktora, aby ustawić jej wiek, imię lub inne atrybuty.
+
+Zobaczmy jak używać konstruktora w PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+W tym przykładzie klasa `Person` ma właściwość (zmienną) `$age` i konstruktor, który ustawia tę właściwość. Metoda `howOldAreYou()` zapewnia następnie dostęp do wieku osoby.
+
+Pseudo-zmienna `$this` jest używana wewnątrz klasy w celu uzyskania dostępu do właściwości i metod obiektu.
+
+Słowo kluczowe `new` służy do tworzenia nowej instancji klasy. W powyższym przykładzie utworzyliśmy nową osobę w wieku 25 lat.
+
+Można również ustawić wartości domyślne dla parametrów konstruktora, jeśli nie zostały one określone podczas tworzenia obiektu. Na przykład:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+W tym przykładzie, jeśli nie określisz wieku podczas tworzenia obiektu `Person`, zostanie użyta domyślna wartość 20.
+
+Fajną rzeczą jest to, że definicję właściwości z jej inicjalizacją za pomocą konstruktora można skrócić i uprościć w następujący sposób:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Dla kompletności, oprócz konstruktorów, obiekty mogą mieć destruktory (metoda `__destruct`), które są wywoływane przed zwolnieniem obiektu z pamięci.
+
+
+Przestrzenie nazw .[#toc-namespaces]
+------------------------------------
+
+Przestrzenie nazw pozwalają nam organizować i grupować powiązane klasy, funkcje i stałe, unikając jednocześnie konfliktów nazewnictwa. Można o nich myśleć jak o folderach na komputerze, gdzie każdy folder zawiera pliki związane z konkretnym projektem lub tematem.
+
+Przestrzenie nazw są szczególnie przydatne w większych projektach lub podczas korzystania z bibliotek innych firm, gdzie mogą wystąpić konflikty nazewnictwa klas.
+
+Wyobraź sobie, że masz w projekcie klasę o nazwie `Car` i chcesz umieścić ją w przestrzeni nazw o nazwie `Transport`. Można to zrobić w następujący sposób:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Jeśli chcesz użyć klasy `Car` w innym pliku, musisz określić, z której przestrzeni nazw pochodzi ta klasa:
+
+```php
+$car = new Transport\Car;
+```
+
+Dla uproszczenia można określić na początku pliku, której klasy z danej przestrzeni nazw chcemy użyć, co pozwala na tworzenie instancji bez podawania pełnej ścieżki:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Dziedziczenie .[#toc-inheritance]
+---------------------------------
+
+Dziedziczenie jest narzędziem programowania obiektowego, które umożliwia tworzenie nowych klas na podstawie istniejących, dziedziczenie ich właściwości i metod oraz rozszerzanie lub redefiniowanie ich w razie potrzeby. Dziedziczenie zapewnia możliwość ponownego wykorzystania kodu i hierarchię klas.
+
+Mówiąc prościej, jeśli mamy jedną klasę i chcemy utworzyć inną, pochodną od niej, ale z pewnymi modyfikacjami, możemy "odziedziczyć" nową klasę z oryginalnej.
+
+W PHP dziedziczenie jest implementowane za pomocą słowa kluczowego `extends`.
+
+Nasza klasa `Person` przechowuje informacje o wieku. Możemy mieć inną klasę, `Student`, która rozszerza `Person` i dodaje informacje o kierunku studiów.
+
+Spójrzmy na przykład:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Jak działa ten kod?
+
+- Użyliśmy słowa kluczowego `extends`, aby rozszerzyć klasę `Person`, co oznacza, że klasa `Student` dziedziczy wszystkie metody i właściwości z `Person`.
+
+- Słowo kluczowe `parent::` pozwala nam wywoływać metody z klasy nadrzędnej. W tym przypadku wywołaliśmy konstruktor z klasy `Person` przed dodaniem naszej własnej funkcjonalności do klasy `Student`. I podobnie, metodę przodka `printInformation()` przed wyświetleniem informacji o uczniu.
+
+Dziedziczenie jest przeznaczone dla sytuacji, w których istnieje relacja "is a" między klasami. Na przykład, klasa `Student` jest klasą `Person`. Kot jest zwierzęciem. Pozwala nam to w przypadkach, w których oczekujemy jednego obiektu (np. "Osoba") w kodzie na użycie obiektu pochodnego (np. "Student").
+
+Ważne jest, aby zdać sobie sprawę, że głównym celem dziedziczenia **nie jest** zapobieganie powielaniu kodu. Wręcz przeciwnie, niewłaściwe wykorzystanie dziedziczenia może prowadzić do skomplikowanego i trudnego w utrzymaniu kodu. Jeśli między klasami nie ma relacji "is a", powinniśmy rozważyć kompozycję zamiast dziedziczenia.
+
+Należy zauważyć, że metody `printInformation()` w klasach `Person` i `Student` wyświetlają nieco inne informacje. Możemy też dodać inne klasy (takie jak `Employee`), które zapewnią inne implementacje tej metody. Zdolność obiektów różnych klas do reagowania na tę samą metodę na różne sposoby nazywana jest polimorfizmem:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Kompozycja .[#toc-composition]
+------------------------------
+
+Kompozycja to technika, w której zamiast dziedziczyć właściwości i metody z innej klasy, po prostu używamy jej instancji w naszej klasie. Pozwala nam to łączyć funkcjonalności i właściwości wielu klas bez tworzenia złożonych struktur dziedziczenia.
+
+Na przykład, mamy klasę `Engine` i klasę `Car`. Zamiast mówić "Samochód jest silnikiem", mówimy "Samochód ma silnik", co jest typową relacją kompozycji.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+W tym przypadku klasa `Car` nie ma wszystkich właściwości i metod klasy `Engine`, ale ma do nich dostęp poprzez właściwość `$engine`.
+
+Zaletą kompozycji jest większa elastyczność projektu i lepsza zdolność adaptacji do przyszłych zmian.
+
+
+Widoczność .[#toc-visibility]
+-----------------------------
+
+W PHP można zdefiniować "widoczność" dla właściwości, metod i stałych klasy. Widoczność określa, gdzie można uzyskać dostęp do tych elementów.
+
+1. Jeśli element jest oznaczony jako `public`, oznacza to, że można uzyskać do niego dostęp z dowolnego miejsca, nawet spoza klasy.
+
+2. Element oznaczony jako `protected` jest dostępny tylko w obrębie klasy i wszystkich jej klas potomnych (klas, które po niej dziedziczą).
+
+3. Jeśli element jest `private`, można uzyskać do niego dostęp tylko w obrębie klasy, w której został zdefiniowany.
+
+Jeśli nie określisz widoczności, PHP automatycznie ustawi ją na `public`.
+
+Spójrzmy na przykładowy kod:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Kontynuacja dziedziczenia klas:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+W tym przypadku metoda `printProperties()` w klasie `ChildClass` może uzyskać dostęp do właściwości publicznych i chronionych, ale nie może uzyskać dostępu do właściwości prywatnych klasy nadrzędnej.
+
+Dane i metody powinny być jak najbardziej ukryte i dostępne tylko poprzez zdefiniowany interfejs. Pozwala to na zmianę wewnętrznej implementacji klasy bez wpływu na resztę kodu.
+
+
+Końcowe słowo kluczowe .[#toc-final-keyword]
+--------------------------------------------
+
+W PHP możemy użyć słowa kluczowego `final`, jeśli chcemy zapobiec dziedziczeniu lub nadpisywaniu klasy, metody lub stałej. Gdy klasa jest oznaczona jako `final`, nie może zostać rozszerzona. Gdy metoda jest oznaczona jako `final`, nie może zostać nadpisana w podklasie.
+
+Świadomość, że dana klasa lub metoda nie będzie już modyfikowana, pozwala nam łatwiej wprowadzać zmiany bez obawy o potencjalne konflikty. Na przykład, możemy dodać nową metodę bez obawy, że potomek może już mieć metodę o tej samej nazwie, co doprowadzi do kolizji. Możemy też zmienić parametry metody, ponownie bez ryzyka spowodowania niespójności z nadpisaną metodą w metodzie potomnej.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+W tym przykładzie próba dziedziczenia z klasy finalnej `FinalClass` spowoduje błąd.
+
+
+Statyczne właściwości i metody .[#toc-static-properties-and-methods]
+--------------------------------------------------------------------
+
+Kiedy mówimy o "statycznych" elementach klasy w PHP, mamy na myśli metody i właściwości, które należą do samej klasy, a nie do konkretnej instancji klasy. Oznacza to, że nie musisz tworzyć instancji klasy, aby uzyskać do nich dostęp. Zamiast tego, wywołujesz je lub uzyskujesz do nich dostęp bezpośrednio poprzez nazwę klasy.
+
+Należy pamiętać, że ponieważ elementy statyczne należą do klasy, a nie do jej instancji, nie można używać pseudo-zmiennej `$this` wewnątrz metod statycznych.
+
+Używanie właściwości statycznych prowadzi do [zaciemniania kodu pełnego pułapek |dependency-injection:global-state], więc nigdy nie powinieneś ich używać, a my nie pokażemy tutaj przykładu. Z drugiej strony, metody statyczne są użyteczne. Oto przykład:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+W tym przykładzie utworzyliśmy klasę `Calculator` z dwiema metodami statycznymi. Możemy wywołać te metody bezpośrednio bez tworzenia instancji klasy za pomocą operatora `::`. Metody statyczne są szczególnie przydatne w przypadku operacji, które nie zależą od stanu konkretnej instancji klasy.
+
+
+Stałe klasowe .[#toc-class-constants]
+-------------------------------------
+
+W ramach klas mamy możliwość definiowania stałych. Stałe to wartości, które nigdy nie zmieniają się podczas wykonywania programu. W przeciwieństwie do zmiennych, wartość stałej pozostaje taka sama.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+W tym przykładzie mamy klasę `Car` ze stałą `NumberOfWheels`. Podczas uzyskiwania dostępu do stałej wewnątrz klasy możemy użyć słowa kluczowego `self` zamiast nazwy klasy.
+
+
+Interfejsy obiektów .[#toc-object-interfaces]
+---------------------------------------------
+
+Interfejsy obiektowe działają jak "kontrakty" dla klas. Jeśli klasa ma zaimplementować interfejs obiektowy, musi zawierać wszystkie metody zdefiniowane przez interfejs. Jest to świetny sposób na zapewnienie, że niektóre klasy przestrzegają tego samego "kontraktu" lub struktury.
+
+W PHP interfejsy definiowane są za pomocą słowa kluczowego `interface`. Wszystkie metody zdefiniowane w interfejsie są publiczne (`public`). Gdy klasa implementuje interfejs, używa słowa kluczowego `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Jeśli klasa implementuje interfejs, ale nie wszystkie oczekiwane metody są zdefiniowane, PHP zgłosi błąd.
+
+Klasa może implementować wiele interfejsów jednocześnie, co różni się od dziedziczenia, gdzie klasa może dziedziczyć tylko z jednej klasy:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Klasy abstrakcyjne .[#toc-abstract-classes]
+-------------------------------------------
+
+Klasy abstrakcyjne służą jako szablony bazowe dla innych klas, ale nie można bezpośrednio tworzyć ich instancji. Zawierają one mieszankę kompletnych metod i metod abstrakcyjnych, które nie mają zdefiniowanej zawartości. Klasy dziedziczące po klasach abstrakcyjnych muszą zawierać definicje wszystkich metod abstrakcyjnych z klasy nadrzędnej.
+
+Do zdefiniowania klasy abstrakcyjnej używamy słowa kluczowego `abstract`.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+W tym przykładzie mamy klasę abstrakcyjną z jedną zwykłą i jedną abstrakcyjną metodą. Następnie mamy klasę `Child`, która dziedziczy po `AbstractClass` i zapewnia implementację metody abstrakcyjnej.
+
+Czym różnią się interfejsy od klas abstrakcyjnych? Klasy abstrakcyjne mogą zawierać zarówno metody abstrakcyjne, jak i konkretne, podczas gdy interfejsy definiują tylko metody, które klasa musi zaimplementować, ale nie zapewniają implementacji. Klasa może dziedziczyć tylko z jednej klasy abstrakcyjnej, ale może implementować dowolną liczbę interfejsów.
+
+
+Sprawdzanie typu .[#toc-type-checking]
+--------------------------------------
+
+W programowaniu kluczowe jest upewnienie się, że dane, z którymi pracujemy, są poprawnego typu. W PHP mamy narzędzia, które to zapewniają. Weryfikacja poprawności typu danych nazywana jest "sprawdzaniem typu".
+
+Typy, które możemy napotkać w PHP:
+
+1. **Podstawowe typy**: Należą do nich `int` (liczby całkowite), `float` (liczby zmiennoprzecinkowe), `bool` (wartości logiczne), `string` (ciągi znaków), `array` (tablice) i `null`.
+2. **Klasy**: Gdy chcemy, aby wartość była instancją określonej klasy.
+3. **Interfaces**: Definiuje zestaw metod, które klasa musi zaimplementować. Wartość, która spełnia interfejs, musi mieć te metody.
+4. **Typ mieszany**: Możemy określić, że zmienna może mieć wiele dozwolonych typów.
+5. **Void**: Ten specjalny typ wskazuje, że funkcja lub metoda nie zwraca żadnej wartości.
+
+Zobaczmy, jak zmodyfikować kod, aby uwzględnić typy:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+W ten sposób upewniamy się, że nasz kod oczekuje i działa z danymi odpowiedniego typu, pomagając nam zapobiegać potencjalnym błędom.
+
+Niektóre typy nie mogą być zapisane bezpośrednio w PHP. W takim przypadku są one wymienione w komentarzu phpDoc, który jest standardowym formatem dokumentowania kodu PHP, zaczynając od `/**` i kończąc na `*/`. Pozwala on na dodawanie opisów klas, metod itp. A także wylistować złożone typy za pomocą tak zwanych adnotacji `@var`, `@param` i `@return`. Typy te są następnie wykorzystywane przez narzędzia do statycznej analizy kodu, ale nie są sprawdzane przez sam PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Porównanie i tożsamość .[#toc-comparison-and-identity]
+------------------------------------------------------
+
+W PHP można porównywać obiekty na dwa sposoby:
+
+1. Porównanie wartości `==`: Sprawdza, czy obiekty są tej samej klasy i mają te same wartości we właściwościach.
+2. Tożsamość `===`: Sprawdza, czy jest to ta sama instancja obiektu.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Operator `instanceof` .[#toc-the-instanceof-operator]
+-----------------------------------------------------
+
+Operator `instanceof` pozwala określić, czy dany obiekt jest instancją określonej klasy, potomkiem tej klasy lub czy implementuje określony interfejs.
+
+Wyobraźmy sobie, że mamy klasę `Person` i inną klasę `Student`, która jest potomkiem klasy `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Z danych wyjściowych wynika, że obiekt `$student` jest uważany za instancję zarówno klasy `Student`, jak i `Person`.
+
+
+Płynne interfejsy .[#toc-fluent-interfaces]
+-------------------------------------------
+
+"Fluent Interface" to technika w OOP, która pozwala na łączenie metod w jednym wywołaniu. Często upraszcza to i wyjaśnia kod.
+
+Kluczowym elementem płynnego interfejsu jest to, że każda metoda w łańcuchu zwraca odniesienie do bieżącego obiektu. Osiąga się to za pomocą `return $this;` na końcu metody. Ten styl programowania jest często kojarzony z metodami zwanymi "setterami", które ustawiają wartości właściwości obiektu.
+
+Zobaczmy, jak mógłby wyglądać płynny interfejs do wysyłania wiadomości e-mail:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+W tym przykładzie metody `setFrom()`, `setRecipient()` i `setMessage()` są używane do ustawiania odpowiednich wartości (nadawca, odbiorca, treść wiadomości). Po ustawieniu każdej z tych wartości, metody zwracają bieżący obiekt (`$email`), pozwalając nam na łańcuchowanie kolejnej metody po nim. Na koniec wywołujemy metodę `send()`, która faktycznie wysyła wiadomość e-mail.
+
+Dzięki płynnym interfejsom możemy pisać kod, który jest intuicyjny i czytelny.
+
+
+Kopiowanie z `clone` .[#toc-copying-with-clone]
+-----------------------------------------------
+
+W PHP możemy utworzyć kopię obiektu za pomocą operatora `clone`. W ten sposób otrzymujemy nową instancję o identycznej zawartości.
+
+Jeśli podczas kopiowania obiektu musimy zmodyfikować niektóre z jego właściwości, możemy zdefiniować specjalną metodę `__clone()` w klasie. Metoda ta jest automatycznie wywoływana, gdy obiekt jest klonowany.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+W tym przykładzie mamy klasę `Sheep` z jedną właściwością `$name`. Kiedy klonujemy instancję tej klasy, metoda `__clone()` zapewnia, że nazwa sklonowanej owcy otrzyma przedrostek "Clone of".
+
+
+Cechy .[#toc-traits]
+--------------------
+
+Traity w PHP są narzędziem, które pozwala na współdzielenie metod, właściwości i stałych pomiędzy klasami i zapobiega duplikacji kodu. Można o nich myśleć jak o mechanizmie "kopiuj-wklej" (Ctrl-C i Ctrl-V), w którym zawartość cechy jest "wklejana" do klas. Pozwala to na ponowne wykorzystanie kodu bez konieczności tworzenia skomplikowanych hierarchii klas.
+
+Przyjrzyjmy się prostemu przykładowi wykorzystania cech w PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+W tym przykładzie mamy cechę o nazwie `Honking`, która zawiera jedną metodę `honk()`. Następnie mamy dwie klasy: `Car` i `Truck`, z których obie używają cechy `Honking`. W rezultacie obie klasy "mają" metodę `honk()` i możemy ją wywołać na obiektach obu klas.
+
+Cechy pozwalają na łatwe i efektywne współdzielenie kodu pomiędzy klasami. Nie wchodzą one w hierarchię dziedziczenia, tzn. `$car instanceof Honking` zwróci `false`.
+
+
+Wyjątki
+-------
+
+Wyjątki w OOP pozwalają nam z wdziękiem obsługiwać błędy i nieoczekiwane sytuacje w naszym kodzie. Są to obiekty, które przenoszą informacje o błędzie lub nietypowej sytuacji.
+
+W PHP mamy wbudowaną klasę `Exception`, która służy jako podstawa dla wszystkich wyjątków. Ma ona kilka metod, które pozwalają nam uzyskać więcej informacji o wyjątku, takich jak komunikat o błędzie, plik i linia, w której wystąpił błąd itp.
+
+Gdy w kodzie wystąpi błąd, możemy "rzucić" wyjątek za pomocą słowa kluczowego `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Gdy funkcja `division()` otrzyma null jako drugi argument, rzuca wyjątek z komunikatem o błędzie `'Division by zero!'`. Aby zapobiec awarii programu, gdy wyjątek zostanie rzucony, uwięzimy go w bloku `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Kod, który może rzucić wyjątek, jest zawijany w blok `try`. Jeśli wyjątek zostanie rzucony, wykonanie kodu przenosi się do bloku `catch`, gdzie możemy obsłużyć wyjątek (np. napisać komunikat o błędzie).
+
+Po blokach `try` i `catch` możemy dodać opcjonalny blok `finally`, który jest zawsze wykonywany niezależnie od tego, czy wyjątek został rzucony, czy nie (nawet jeśli użyjemy `return`, `break` lub `continue` w bloku `try` lub `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Możemy również tworzyć własne klasy wyjątków (hierarchie), które dziedziczą po klasie Exception. Jako przykład rozważmy prostą aplikację bankową, która umożliwia wpłaty i wypłaty:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Można określić wiele bloków `catch` dla pojedynczego bloku `try`, jeśli spodziewane są różne typy wyjątków.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+W tym przykładzie ważne jest, aby zwrócić uwagę na kolejność bloków `catch`. Ponieważ wszystkie wyjątki dziedziczą z `BankingException`, gdybyśmy mieli ten blok jako pierwszy, wszystkie wyjątki zostałyby w nim przechwycone, a kod nie dotarłby do kolejnych bloków `catch`. Dlatego ważne jest, aby bardziej specyficzne wyjątki (tj. te, które dziedziczą po innych) znajdowały się wyżej w kolejności bloków `catch` niż ich wyjątki nadrzędne.
+
+
+Iteracje .[#toc-iterations]
+---------------------------
+
+W PHP można przechodzić przez obiekty za pomocą pętli `foreach`, podobnie jak przez tablice. Aby to działało, obiekt musi implementować specjalny interfejs.
+
+Pierwszą opcją jest zaimplementowanie interfejsu `Iterator`, który ma metody `current()` zwracające bieżącą wartość, `key()` zwracające klucz, `next()` przechodzące do następnej wartości, `rewind()` przechodzące do początku i `valid()` sprawdzające, czy jesteśmy już na końcu.
+
+Inną opcją jest zaimplementowanie interfejsu `IteratorAggregate`, który ma tylko jedną metodę `getIterator()`. Zwraca ona albo obiekt zastępczy, który zapewni przechodzenie, albo może być generatorem, który jest specjalną funkcją, która używa `yield` do sekwencyjnego zwracania kluczy i wartości:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Najlepsze praktyki .[#toc-best-practices]
+-----------------------------------------
+
+Po opanowaniu podstawowych zasad programowania obiektowego ważne jest, aby skupić się na najlepszych praktykach OOP. Pomogą ci one pisać kod, który jest nie tylko funkcjonalny, ale także czytelny, zrozumiały i łatwy w utrzymaniu.
+
+1) **Separation of Concerns**: Każda klasa powinna mieć jasno określoną odpowiedzialność i powinna zajmować się tylko jednym podstawowym zadaniem. Jeśli klasa robi zbyt wiele rzeczy, może być właściwe podzielenie jej na mniejsze, wyspecjalizowane klasy.
+2) **Ekapsułkowanie**: Dane i metody powinny być jak najbardziej ukryte i dostępne tylko poprzez zdefiniowany interfejs. Pozwala to na zmianę wewnętrznej implementacji klasy bez wpływu na resztę kodu.
+3) **Wstrzykiwanie zależności**: Zamiast tworzyć zależności bezpośrednio w klasie, należy "wstrzykiwać" je z zewnątrz. Aby lepiej zrozumieć tę zasadę, zalecamy zapoznanie się z [rozdziałami dotyczącymi wst |dependency-injection:introduction]rzykiwania zależności.
diff --git a/nette/pl/troubleshooting.texy b/nette/pl/troubleshooting.texy
index f51c01be14..b2af3ea4db 100644
--- a/nette/pl/troubleshooting.texy
+++ b/nette/pl/troubleshooting.texy
@@ -18,7 +18,7 @@ Przyczynę błędu można zawsze znaleźć w katalogu `log/`. Jeśli jednak komu
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // Twój adres IP
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Błąd 404, routing nie działa .[#toc-error-404-routing-not-working]
 Kiedy wszystkie strony (oprócz strony głównej) zwracają błąd 404, wygląda to na problem z konfiguracją serwera dla [ładnych adresów URL |#How to Configure a Server for Nice URLs?].
 
 
+Jak wyłączyć pamięć podręczną podczas programowania? .[#toc-how-to-disable-cache-during-development]
+----------------------------------------------------------------------------------------------------
+Nette jest inteligentny i nie trzeba w nim wyłączać buforowania. Podczas programowania automatycznie aktualizuje pamięć podręczną za każdym razem, gdy nastąpi zmiana w szablonie lub konfiguracji kontenera DI. Co więcej, tryb deweloperski jest aktywowany przez automatyczne wykrywanie, więc zwykle nie ma potrzeby konfigurowania czegokolwiek [lub tylko adresu IP |application:bootstrap#development-vs-production-mode].
+
+Podczas debugowania routera zalecamy wyłączenie pamięci podręcznej przeglądarki, w której mogą być przechowywane na przykład przekierowania: otwórz Narzędzia deweloperskie (Ctrl+Shift+I lub Cmd+Option+I) i w panelu Sieć zaznacz pole, aby wyłączyć pamięć podręczną.
+
+
 Błąd `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 --------------------------------------------------------------------------------------------------------------------
 Ten błąd pojawia się, jeśli zaktualizowałeś PHP do wersji 8.1, ale używasz Nette, która nie jest z nim kompatybilna. Rozwiązaniem jest więc aktualizacja Nette do nowszej wersji za pomocą `composer update`. Nette wspiera PHP 8.1 od wersji 3.0. Jeśli używasz starszej wersji (możesz to sprawdzić zaglądając na stronę `composer.json`), [zaktualizuj Nette |migrations:en] lub pozostań przy PHP 8.0.
@@ -67,7 +74,7 @@ Katalog `www/` używany w przykładowych projektach Nette jest katalogiem public
 
 Aby aplikacja działała na hostingu, należy w konfiguracji hostingu ustawić document-root na ten katalog. Lub, jeśli hosting ma przygotowany folder o innej nazwie dla katalogu publicznego (na przykład `web`, `public_html`, itp.), po prostu zmień nazwę `www/`.
 
-Rozwiązaniem **nie jest** "pozbycie się" folderu `www/` za pomocą reguł w pliku `.htaccess` lub w routerze. Jeśli hosting nie pozwoliłby Ci ustawić document-root na podkatalog (czyli tworzyć katalogi jeden poziom powyżej katalogu publicznego), poszukaj innego. W przeciwnym razie podejmowałbyś znaczne ryzyko związane z bezpieczeństwem. Byłoby to jak mieszkanie, w którym nie można zamknąć drzwi wejściowych i są one zawsze szeroko otwarte.
+Rozwiązaniem **nie jest** uniemożliwienie dostępu do wszystkich folderów z wyjątkiem `www/` za pomocą reguł w pliku `.htaccess` lub w routerze. Jeśli twój hosting nie pozwala na ustawienie katalogu głównego dokumentu w podkatalogu (tj. tworzenie katalogów na poziomie wyższym niż katalog publiczny), powinieneś poszukać innej usługi hostingowej. W przeciwnym razie narazisz się na poważne zagrożenia bezpieczeństwa. Byłoby to jak mieszkanie w mieszkaniu, w którym drzwi wejściowe nie mogą być zamknięte i są zawsze szeroko otwarte.
 
 
 Jak założyć serwer dla ładnych adresów URL? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/pt/@home.texy b/nette/pt/@home.texy
index 6b35915287..e2fdbdc4ec 100644
--- a/nette/pt/@home.texy
+++ b/nette/pt/@home.texy
@@ -84,11 +84,11 @@ Utilidades
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hashing de senha |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Tipos de PHP |utils:type]
 - [Cordas |utils:Strings]
 - [Validadores |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...outros |utils:]
 </div>
diff --git a/nette/pt/installation.texy b/nette/pt/installation.texy
index 66d80dec1f..958f96c331 100644
--- a/nette/pt/installation.texy
+++ b/nette/pt/installation.texy
@@ -20,7 +20,7 @@ O Nette oferece uma coleção de pacotes (bibliotecas) úteis e sofisticados par
 composer require nette/utils
 ```
 
-Você prefere uma interface gráfica? Confira o [guia |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] sobre a instalação de pacotes no ambiente PhpStrom.
+Você prefere uma interface gráfica? Confira o [guia |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] sobre a instalação de pacotes no ambiente PhpStorm.
 
 
 Como iniciar um novo projeto com o Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/pt/introduction-to-object-oriented-programming.texy b/nette/pt/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..f5a70b6a5f
--- /dev/null
+++ b/nette/pt/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Introdução à programação orientada a objetos
+********************************************
+
+.[perex]
+O termo "OOP" significa Object-Oriented Programming (Programação orientada a objetos), que é uma forma de organizar e estruturar o código. A OOP nos permite ver um programa como uma coleção de objetos que se comunicam entre si, em vez de uma sequência de comandos e funções.
+
+Na OOP, um "objeto" é uma unidade que contém dados e funções que operam com esses dados. Os objetos são criados com base em "classes", que podem ser entendidas como planos ou modelos para objetos. Quando temos uma classe, podemos criar sua "instância", que é um objeto específico criado a partir dessa classe.
+
+Vamos ver como podemos criar uma classe simples no PHP. Quando definimos uma classe, usamos a palavra-chave "class" (classe), seguida pelo nome da classe e, em seguida, chaves que envolvem as funções da classe (chamadas de "métodos") e as variáveis da classe (chamadas de "propriedades" ou "atributos"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Neste exemplo, criamos uma classe chamada `Car` com uma função (ou "método") chamada `honk`.
+
+Cada classe deve resolver apenas uma tarefa principal. Se uma classe estiver fazendo muitas coisas, pode ser apropriado dividi-la em classes menores e especializadas.
+
+Normalmente, as classes são armazenadas em arquivos separados para manter o código organizado e fácil de navegar. O nome do arquivo deve corresponder ao nome da classe, portanto, para a classe `Car`, o nome do arquivo seria `Car.php`.
+
+Ao nomear as classes, é bom seguir a convenção "PascalCase", o que significa que cada palavra do nome começa com uma letra maiúscula e não há sublinhados ou outros separadores. Os métodos e as propriedades seguem a convenção "camelCase", ou seja, começam com uma letra minúscula.
+
+Alguns métodos no PHP têm funções especiais e são prefixados com `__` (dois sublinhados). Um dos métodos especiais mais importantes é o "construtor", rotulado como `__construct`. O construtor é um método que é chamado automaticamente ao criar uma nova instância de uma classe.
+
+Geralmente usamos o construtor para definir o estado inicial de um objeto. Por exemplo, ao criar um objeto que representa uma pessoa, você pode usar o construtor para definir sua idade, nome ou outros atributos.
+
+Vamos ver como usar um construtor no PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+Neste exemplo, a classe `Person` tem uma propriedade (variável) `$age` e um construtor que define essa propriedade. O método `howOldAreYou()` fornece acesso à idade da pessoa.
+
+A pseudovariável `$this` é usada dentro da classe para acessar as propriedades e os métodos do objeto.
+
+A palavra-chave `new` é usada para criar uma nova instância de uma classe. No exemplo acima, criamos uma nova pessoa com 25 anos.
+
+Você também pode definir valores padrão para os parâmetros do construtor se eles não forem especificados ao criar um objeto. Por exemplo:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Neste exemplo, se você não especificar uma idade ao criar um objeto `Person`, o valor padrão de 20 será usado.
+
+O bom é que a definição da propriedade com sua inicialização por meio do construtor pode ser encurtada e simplificada da seguinte forma:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Para ser mais completo, além dos construtores, os objetos podem ter destrutores (método `__destruct`) que são chamados antes de o objeto ser liberado da memória.
+
+
+Namespaces .[#toc-namespaces]
+-----------------------------
+
+Os namespaces nos permitem organizar e agrupar classes, funções e constantes relacionadas, evitando conflitos de nomes. Você pode pensar neles como pastas em um computador, onde cada pasta contém arquivos relacionados a um projeto ou tópico específico.
+
+Os namespaces são especialmente úteis em projetos maiores ou ao usar bibliotecas de terceiros, onde podem surgir conflitos de nomes de classes.
+
+Imagine que você tenha uma classe chamada `Car` em seu projeto e queira colocá-la em um namespace chamado `Transport`. Você faria isso da seguinte forma:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Se quiser usar a classe `Car` em outro arquivo, precisará especificar de qual namespace a classe se origina:
+
+```php
+$car = new Transport\Car;
+```
+
+Para simplificar, você pode especificar no início do arquivo qual classe de um determinado namespace deseja usar, o que lhe permite criar instâncias sem mencionar o caminho completo:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Herança .[#toc-inheritance]
+---------------------------
+
+A herança é uma ferramenta de programação orientada a objetos que permite a criação de novas classes com base nas existentes, herdando suas propriedades e métodos e estendendo-os ou redefinindo-os conforme necessário. A herança garante a reutilização do código e a hierarquia de classes.
+
+Em termos simples, se tivermos uma classe e quisermos criar outra derivada dela, mas com algumas modificações, podemos "herdar" a nova classe da original.
+
+No PHP, a herança é implementada usando a palavra-chave `extends`.
+
+Nossa classe `Person` armazena informações de idade. Podemos ter outra classe, `Student`, que estende a `Person` e acrescenta informações sobre o campo de estudo.
+
+Vamos dar uma olhada em um exemplo:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Como esse código funciona?
+
+- Usamos a palavra-chave `extends` para estender a classe `Person`, o que significa que a classe `Student` herda todos os métodos e propriedades de `Person`.
+
+- A palavra-chave `parent::` nos permite chamar métodos da classe principal. Nesse caso, chamamos o construtor da classe `Person` antes de adicionar nossa própria funcionalidade à classe `Student`. E, da mesma forma, o método ancestral `printInformation()` antes de listar as informações do aluno.
+
+A herança é destinada a situações em que há um relacionamento "é um" entre as classes. Por exemplo, um `Student` é um `Person`. Um gato é um animal. Ela nos permite, nos casos em que esperamos um objeto (por exemplo, "Person") no código, usar um objeto derivado (por exemplo, "Student").
+
+É essencial perceber que o objetivo principal da herança **não** é evitar a duplicação de código. Pelo contrário, o uso incorreto da herança pode levar a um código complexo e de difícil manutenção. Se não houver uma relação "é um" entre as classes, devemos considerar a composição em vez da herança.
+
+Observe que os métodos `printInformation()` nas classes `Person` e `Student` produzem informações ligeiramente diferentes. E podemos adicionar outras classes (como `Employee`) que fornecerão outras implementações desse método. A capacidade de objetos de classes diferentes responderem ao mesmo método de maneiras diferentes é chamada de polimorfismo:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Composição .[#toc-composition]
+------------------------------
+
+A composição é uma técnica em que, em vez de herdar propriedades e métodos de outra classe, simplesmente usamos sua instância em nossa classe. Isso nos permite combinar funcionalidades e propriedades de várias classes sem criar estruturas de herança complexas.
+
+Por exemplo, temos uma classe `Engine` e uma classe `Car`. Em vez de dizer "Um carro é um motor", dizemos "Um carro tem um motor", que é uma relação de composição típica.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Aqui, o `Car` não tem todas as propriedades e métodos do `Engine`, mas tem acesso a eles por meio da propriedade `$engine`.
+
+A vantagem da composição é a maior flexibilidade de design e a melhor adaptabilidade a mudanças futuras.
+
+
+Visibilidade .[#toc-visibility]
+-------------------------------
+
+No PHP, você pode definir "visibilidade" para propriedades de classe, métodos e constantes. A visibilidade determina onde você pode acessar esses elementos.
+
+1. **Public:** Se um elemento estiver marcado como `public`, isso significa que você pode acessá-lo de qualquer lugar, mesmo fora da classe.
+
+2. **Protegido:** Um elemento marcado como `protected` é acessível somente dentro da classe e de todos os seus descendentes (classes que herdam dela).
+
+3. **Private:** Se um elemento for `private`, você poderá acessá-lo somente na classe em que ele foi definido.
+
+Se você não especificar a visibilidade, o PHP a definirá automaticamente como `public`.
+
+Vamos dar uma olhada em um exemplo de código:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Continuando com a herança de classes:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+Nesse caso, o método `printProperties()` no `ChildClass` pode acessar as propriedades públicas e protegidas, mas não pode acessar as propriedades privadas da classe principal.
+
+Os dados e os métodos devem ser tão ocultos quanto possível e acessíveis somente por meio de uma interface definida. Isso permite que você altere a implementação interna da classe sem afetar o restante do código.
+
+
+Palavra-chave final .[#toc-final-keyword]
+-----------------------------------------
+
+No PHP, podemos usar a palavra-chave `final` se quisermos impedir que uma classe, um método ou uma constante seja herdado ou substituído. Quando uma classe é marcada como `final`, ela não pode ser estendida. Quando um método é marcado como `final`, ele não pode ser substituído em uma subclasse.
+
+O fato de saber que uma determinada classe ou método não será mais modificado nos permite fazer alterações com mais facilidade sem nos preocuparmos com possíveis conflitos. Por exemplo, podemos adicionar um novo método sem medo de que um descendente já tenha um método com o mesmo nome, levando a uma colisão. Ou podemos alterar os parâmetros de um método, novamente sem o risco de causar inconsistência com um método substituído em um descendente.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+Neste exemplo, a tentativa de herdar da classe final `FinalClass` resultará em um erro.
+
+
+Propriedades e métodos estáticos .[#toc-static-properties-and-methods]
+----------------------------------------------------------------------
+
+Quando falamos de elementos "estáticos" de uma classe no PHP, queremos dizer métodos e propriedades que pertencem à própria classe, não a uma instância específica da classe. Isso significa que não é necessário criar uma instância da classe para acessá-los. Em vez disso, você os chama ou acessa diretamente por meio do nome da classe.
+
+Lembre-se de que, como os elementos estáticos pertencem à classe e não às suas instâncias, você não pode usar a pseudovariável `$this` dentro dos métodos estáticos.
+
+O uso de propriedades estáticas leva a um [código ofuscado e cheio de armadilhas |dependency-injection:global-state], portanto, você nunca deve usá-las, e não mostraremos um exemplo aqui. Por outro lado, os métodos estáticos são úteis. Aqui está um exemplo:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+Neste exemplo, criamos uma classe `Calculator` com dois métodos estáticos. Podemos chamar esses métodos diretamente sem criar uma instância da classe usando o operador `::`. Os métodos estáticos são especialmente úteis para operações que não dependem do estado de uma instância específica da classe.
+
+
+Constantes de classe .[#toc-class-constants]
+--------------------------------------------
+
+Nas classes, temos a opção de definir constantes. Constantes são valores que nunca mudam durante a execução do programa. Ao contrário das variáveis, o valor de uma constante permanece o mesmo.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+Neste exemplo, temos uma classe `Car` com a constante `NumberOfWheels`. Ao acessar a constante dentro da classe, podemos usar a palavra-chave `self` em vez do nome da classe.
+
+
+Interfaces de objeto .[#toc-object-interfaces]
+----------------------------------------------
+
+As interfaces de objetos funcionam como "contratos" para as classes. Se uma classe tiver que implementar uma interface de objeto, ela deverá conter todos os métodos que a interface define. Essa é uma ótima maneira de garantir que determinadas classes sigam o mesmo "contrato" ou estrutura.
+
+No PHP, as interfaces são definidas usando a palavra-chave `interface`. Todos os métodos definidos em uma interface são públicos (`public`). Quando uma classe implementa uma interface, ela usa a palavra-chave `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Se uma classe implementar uma interface, mas nem todos os métodos esperados estiverem definidos, o PHP lançará um erro.
+
+Uma classe pode implementar várias interfaces de uma vez, o que é diferente da herança, em que uma classe só pode herdar de uma classe:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Classes abstratas .[#toc-abstract-classes]
+------------------------------------------
+
+As classes abstratas servem como modelos de base para outras classes, mas você não pode criar suas instâncias diretamente. Elas contêm uma mistura de métodos completos e métodos abstratos que não têm um conteúdo definido. As classes que herdam de classes abstratas devem fornecer definições para todos os métodos abstratos da classe pai.
+
+Usamos a palavra-chave `abstract` para definir uma classe abstrata.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+Neste exemplo, temos uma classe abstrata com um método regular e um método abstrato. Em seguida, temos uma classe `Child` que herda de `AbstractClass` e fornece uma implementação para o método abstrato.
+
+Qual é a diferença entre interfaces e classes abstratas? As classes abstratas podem conter métodos abstratos e concretos, enquanto as interfaces definem apenas os métodos que a classe deve implementar, mas não fornecem nenhuma implementação. Uma classe pode herdar de apenas uma classe abstrata, mas pode implementar qualquer número de interfaces.
+
+
+Verificação de tipo .[#toc-type-checking]
+-----------------------------------------
+
+Na programação, é fundamental garantir que os dados com os quais trabalhamos sejam do tipo correto. No PHP, temos ferramentas que oferecem essa garantia. A verificação de que os dados são do tipo correto é chamada de "verificação de tipo".
+
+Tipos que podemos encontrar no PHP:
+
+1. **Tipos básicos**: Incluem `int` (inteiros), `float` (números de ponto flutuante), `bool` (valores booleanos), `string` (strings), `array` (arrays) e `null`.
+2. **Classes**: Quando queremos que um valor seja uma instância de uma classe específica.
+3. **Interfaces**: Define um conjunto de métodos que uma classe deve implementar. Um valor que atende a uma interface deve ter esses métodos.
+4. **Tipos mistos**: Podemos especificar que uma variável pode ter vários tipos permitidos.
+5. **Void**: Esse tipo especial indica que uma função ou método não retorna nenhum valor.
+
+Vamos ver como modificar o código para incluir tipos:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Dessa forma, garantimos que nosso código espera e trabalha com dados do tipo correto, o que nos ajuda a evitar possíveis erros.
+
+Alguns tipos não podem ser escritos diretamente no PHP. Nesse caso, eles são listados no comentário phpDoc, que é o formato padrão para documentar o código PHP, começando com `/**` e terminando com `*/`. Ele permite que você adicione descrições de classes, métodos e assim por diante. E também para listar tipos complexos usando as chamadas anotações `@var`, `@param` e `@return`. Esses tipos são usados por ferramentas de análise de código estático, mas não são verificados pelo próprio PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Comparação e identidade .[#toc-comparison-and-identity]
+-------------------------------------------------------
+
+No PHP, você pode comparar objetos de duas maneiras:
+
+1. Comparação de valores `==`: Verifica se os objetos são da mesma classe e têm os mesmos valores em suas propriedades.
+2. Identidade `===`: Verifica se é a mesma instância do objeto.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+O operador do `instanceof` .[#toc-the-instanceof-operator]
+----------------------------------------------------------
+
+O operador `instanceof` permite que você determine se um determinado objeto é uma instância de uma classe específica, um descendente dessa classe ou se implementa uma determinada interface.
+
+Imagine que temos uma classe `Person` e outra classe `Student`, que é descendente de `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+A partir dos resultados, fica evidente que o objeto `$student` é considerado uma instância das classes `Student` e `Person`.
+
+
+Interfaces fluentes .[#toc-fluent-interfaces]
+---------------------------------------------
+
+Uma "Interface Fluente" é uma técnica em OOP que permite encadear métodos em uma única chamada. Isso geralmente simplifica e esclarece o código.
+
+O principal elemento de uma interface fluente é que cada método na cadeia retorna uma referência ao objeto atual. Isso é obtido com o uso do endereço `return $this;` no final do método. Esse estilo de programação é frequentemente associado a métodos chamados "setters", que definem os valores das propriedades de um objeto.
+
+Vamos ver como seria uma interface fluente para o envio de e-mails:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+Neste exemplo, os métodos `setFrom()`, `setRecipient()` e `setMessage()` são usados para definir os valores correspondentes (remetente, destinatário, conteúdo da mensagem). Depois de definir cada um desses valores, os métodos retornam o objeto atual (`$email`), o que nos permite encadear outro método depois dele. Por fim, chamamos o método `send()`, que de fato envia o e-mail.
+
+Graças às interfaces fluentes, podemos escrever códigos intuitivos e de fácil leitura.
+
+
+Copiando com `clone` .[#toc-copying-with-clone]
+-----------------------------------------------
+
+No PHP, podemos criar uma cópia de um objeto usando o operador `clone`. Dessa forma, obtemos uma nova instância com conteúdo idêntico.
+
+Se precisarmos modificar algumas de suas propriedades ao copiar um objeto, podemos definir um método `__clone()` especial na classe. Esse método é chamado automaticamente quando o objeto é clonado.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+Neste exemplo, temos uma classe `Sheep` com uma propriedade `$name`. Quando clonamos uma instância dessa classe, o método `__clone()` garante que o nome da ovelha clonada receba o prefixo "Clone of".
+
+
+Características .[#toc-traits]
+------------------------------
+
+As características no PHP são uma ferramenta que permite o compartilhamento de métodos, propriedades e constantes entre classes e evita a duplicação de código. Você pode pensar nelas como um mecanismo de "copiar e colar" (Ctrl-C e Ctrl-V), em que o conteúdo de uma característica é "colado" nas classes. Isso permite que você reutilize o código sem precisar criar hierarquias de classe complicadas.
+
+Vamos dar uma olhada em um exemplo simples de como usar características no PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+Neste exemplo, temos uma característica chamada `Honking` que contém um método `honk()`. Em seguida, temos duas classes: `Car` e `Truck`, ambas as quais usam a característica `Honking`. Como resultado, ambas as classes "têm" o método `honk()` e podemos chamá-lo em objetos de ambas as classes.
+
+As características permitem o compartilhamento fácil e eficiente de código entre classes. Elas não entram na hierarquia de herança, ou seja, `$car instanceof Honking` retornará `false`.
+
+
+Exceções
+--------
+
+As exceções na OOP nos permitem lidar com erros e situações inesperadas em nosso código. Elas são objetos que contêm informações sobre um erro ou uma situação incomum.
+
+No PHP, temos uma classe interna `Exception`, que serve de base para todas as exceções. Ela tem vários métodos que nos permitem obter mais informações sobre a exceção, como a mensagem de erro, o arquivo e a linha em que o erro ocorreu etc.
+
+Quando ocorre um erro no código, podemos "lançar" a exceção usando a palavra-chave `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Quando a função `division()` recebe null como seu segundo argumento, ela lança uma exceção com a mensagem de erro `'Division by zero!'`. Para evitar que o programa seja interrompido quando a exceção for lançada, nós a capturamos no bloco `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+O código que pode lançar uma exceção é envolvido em um bloco `try`. Se a exceção for lançada, a execução do código será movida para um bloco `catch`, onde poderemos tratar a exceção (por exemplo, escrever uma mensagem de erro).
+
+Após os blocos `try` e `catch`, podemos adicionar um bloco opcional `finally`, que é sempre executado, independentemente de a exceção ter sido lançada ou não (mesmo se usarmos `return`, `break` ou `continue` no bloco `try` ou `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Também podemos criar nossas próprias classes de exceção (hierarquia) que herdam da classe Exception. Como exemplo, considere um aplicativo bancário simples que permite depósitos e saques:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Vários blocos `catch` podem ser especificados para um único bloco `try` se você espera diferentes tipos de exceções.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+Nesse exemplo, é importante observar a ordem dos blocos `catch`. Como todas as exceções são herdadas de `BankingException`, se tivéssemos esse bloco primeiro, todas as exceções seriam capturadas nele sem que o código chegasse aos blocos `catch` subsequentes. Portanto, é importante que as exceções mais específicas (ou seja, aquelas que herdam de outras) estejam em uma posição mais alta na ordem do bloco `catch` do que suas exceções pai.
+
+
+Iterações .[#toc-iterations]
+----------------------------
+
+No PHP, você pode percorrer objetos usando o loop `foreach`, da mesma forma que percorre uma matriz. Para que isso funcione, o objeto deve implementar uma interface especial.
+
+A primeira opção é implementar a interface `Iterator`, que tem os métodos `current()` que retorna o valor atual, `key()` que retorna a chave, `next()` que passa para o próximo valor, `rewind()` que passa para o início e `valid()` que verifica se já estamos no final.
+
+A outra opção é implementar uma interface `IteratorAggregate`, que tem apenas um método `getIterator()`. Ele retorna um objeto de espaço reservado que fornecerá a passagem ou pode ser um gerador, que é uma função especial que usa `yield` para retornar chaves e valores sequencialmente:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Melhores práticas .[#toc-best-practices]
+----------------------------------------
+
+Depois de aprender os princípios básicos da programação orientada a objetos, é fundamental concentrar-se nas práticas recomendadas de OOP. Elas o ajudarão a escrever códigos que não sejam apenas funcionais, mas também legíveis, compreensíveis e de fácil manutenção.
+
+1) **Separação de preocupações**: Cada classe deve ter uma responsabilidade claramente definida e deve tratar apenas de uma tarefa principal. Se uma classe fizer muitas coisas, pode ser apropriado dividi-la em classes menores e especializadas.
+2) **Encapsulamento**: Os dados e métodos devem ser tão ocultos quanto possível e acessíveis somente por meio de uma interface definida. Isso permite que você altere a implementação interna de uma classe sem afetar o restante do código.
+3) **Injeção de dependência**: Em vez de criar dependências diretamente em uma classe, você deve "injetá-las" do lado de fora. Para entender melhor esse princípio, recomendamos os [capítulos sobre Injeção de Dependência |dependency-injection:introduction].
diff --git a/nette/pt/troubleshooting.texy b/nette/pt/troubleshooting.texy
index 37f15320ca..9614da9a54 100644
--- a/nette/pt/troubleshooting.texy
+++ b/nette/pt/troubleshooting.texy
@@ -18,7 +18,7 @@ Você sempre pode encontrar o motivo do erro no diretório `log/`. Entretanto, s
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // seu endereço IP
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Erro 404, roteamento não funciona .[#toc-error-404-routing-not-working]
 Quando todas as páginas (exceto a página inicial) retornam um erro 404, parece um problema de configuração do servidor para [URLs bonitas |#How to Configure a Server for Nice URLs?].
 
 
+Como desativar o cache durante o desenvolvimento? .[#toc-how-to-disable-cache-during-development]
+-------------------------------------------------------------------------------------------------
+O Nette é inteligente, e você não precisa desativar o cache nele. Durante o desenvolvimento, ele atualiza automaticamente o cache sempre que há uma alteração no modelo ou na configuração do contêiner DI. Além disso, o modo de desenvolvimento é ativado por detecção automática, portanto, normalmente não há necessidade de configurar nada, [ou apenas o endereço IP |application:bootstrap#development-vs-production-mode].
+
+Ao depurar o roteador, recomendamos desativar o cache do navegador, onde, por exemplo, os redirecionamentos podem ser armazenados: abra o Developer Tools (Ctrl+Shift+I ou Cmd+Option+I) e, no painel Network, marque a caixa para desativar o cache.
+
+
 Erro `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 --------------------------------------------------------------------------------------------------------------------
 Este erro ocorre se você tiver atualizado o PHP para a versão 8.1, mas estiver usando Nette, que não é compatível com ele. Portanto, a solução é atualizar o Nette para uma versão mais recente usando `composer update`. Nette suporta o PHP 8.1 desde a versão 3.0. Se você estiver usando uma versão mais antiga (você pode descobrir procurando em `composer.json`), [atualize Nette |migrations:en] ou fique com o PHP 8.0.
@@ -67,7 +74,7 @@ O diretório `www/` usado nos projetos modelo em Nette é o chamado diretório p
 
 Para executar o aplicativo na hospedagem, é necessário definir a raiz do documento para este diretório na configuração de hospedagem. Ou, se a hospedagem tiver uma pasta pré-fabricada para o diretório público com um nome diferente (por exemplo `web`, `public_html` etc.), simplesmente renomeie `www/`.
 
-A solução ** não é*** para "se livrar" da pasta `www/` usando regras no arquivo `.htaccess` ou no roteador. Se a hospedagem não permitir que você coloque a raiz do documento em um subdiretório (ou seja, criar diretórios um nível acima do diretório público), procure por outro. Caso contrário, você estaria correndo um risco significativo de segurança. Seria como viver em um apartamento onde não se pode fechar a porta da frente e ela está sempre aberta.
+A solução **não é** impedir o acesso a todas as pastas, exceto `www/`, usando regras no arquivo `.htaccess` ou no roteador. Se a sua hospedagem não permitir a configuração da raiz do documento em um subdiretório (ou seja, a criação de diretórios um nível acima do diretório público), você deverá procurar outro serviço de hospedagem. Caso contrário, você estará se expondo a riscos de segurança significativos. Seria como morar em um apartamento em que a porta da frente não pode ser fechada e está sempre aberta.
 
 
 Como configurar um servidor para URLs legais? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/ro/@home.texy b/nette/ro/@home.texy
index 93cb581542..44631364c9 100644
--- a/nette/ro/@home.texy
+++ b/nette/ro/@home.texy
@@ -84,11 +84,11 @@ Utilități
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hașurarea parolei |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Tipuri PHP |utils:type]
 - [Șiruri de caractere |utils:Strings]
 - [Validatori |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...altele |utils:]
 </div>
diff --git a/nette/ro/installation.texy b/nette/ro/installation.texy
index a21291725e..370bcd62ca 100644
--- a/nette/ro/installation.texy
+++ b/nette/ro/installation.texy
@@ -20,7 +20,7 @@ Nette oferă o colecție de pachete (biblioteci) utile și sofisticate pentru PH
 composer require nette/utils
 ```
 
-Preferați o interfață grafică? Consultați [ghidul |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalare a pachetelor în mediul PhpStrom.
+Preferați o interfață grafică? Consultați [ghidul |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalare a pachetelor în mediul PhpStorm.
 
 
 Cum să începeți un proiect nou cu Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/ro/introduction-to-object-oriented-programming.texy b/nette/ro/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..f8cb3c4f75
--- /dev/null
+++ b/nette/ro/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Introducere în programarea orientată pe obiecte
+***********************************************
+
+.[perex]
+Termenul "OOP" înseamnă Object-Oriented Programming (programare orientată pe obiecte), care reprezintă o modalitate de organizare și structurare a codului. OOP ne permite să privim un program ca pe o colecție de obiecte care comunică între ele, mai degrabă decât ca pe o secvență de comenzi și funcții.
+
+În OOP, un "obiect" este o unitate care conține date și funcții care operează cu aceste date. Obiectele sunt create pe baza unor "clase", care pot fi înțelese ca planuri sau șabloane pentru obiecte. Odată ce avem o clasă, putem crea o "instanță" a acesteia, care este un obiect specific creat din clasa respectivă.
+
+Să vedem cum putem crea o clasă simplă în PHP. Atunci când definim o clasă, folosim cuvântul cheie "class", urmat de numele clasei și apoi de parantezele curbe care înconjoară funcțiile clasei (numite "metode") și variabilele clasei (numite "proprietăți" sau "atribute"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+În acest exemplu, am creat o clasă numită `Car` cu o funcție (sau "metodă") numită `honk`.
+
+Fiecare clasă trebuie să rezolve o singură sarcină principală. În cazul în care o clasă face prea multe lucruri, ar putea fi oportună împărțirea ei în clase mai mici, specializate.
+
+Clasele sunt de obicei stocate în fișiere separate pentru a păstra codul organizat și ușor de navigat. Numele fișierului ar trebui să se potrivească cu numele clasei, astfel încât pentru clasa `Car`, numele fișierului ar fi `Car.php`.
+
+Atunci când denumiți clasele, este bine să urmați convenția "PascalCase", ceea ce înseamnă că fiecare cuvânt din nume începe cu majusculă și nu există sublinieri sau alți separatori. Metodele și proprietățile urmează convenția "camelCase", ceea ce înseamnă că încep cu o literă mică.
+
+Unele metode din PHP au roluri speciale și sunt prefixate cu `__` (două liniuțe de subliniere). Una dintre cele mai importante metode speciale este "constructorul", etichetat cu `__construct`. Constructorul este o metodă care este apelată automat atunci când se creează o nouă instanță a unei clase.
+
+Utilizăm adesea constructorul pentru a stabili starea inițială a unui obiect. De exemplu, atunci când creați un obiect care reprezintă o persoană, ați putea folosi constructorul pentru a seta vârsta, numele sau alte atribute ale acesteia.
+
+Să vedem cum să folosim un constructor în PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+În acest exemplu, clasa `Person` are o proprietate (variabilă) `$age` și un constructor care stabilește această proprietate. Metoda `howOldAreYou()` oferă apoi acces la vârsta persoanei.
+
+Pseudo-variabila `$this` este utilizată în interiorul clasei pentru a accesa proprietățile și metodele obiectului.
+
+Cuvântul cheie `new` este utilizat pentru a crea o nouă instanță a unei clase. În exemplul de mai sus, am creat o nouă persoană în vârstă de 25 de ani.
+
+De asemenea, puteți seta valori implicite pentru parametrii constructorului dacă nu sunt specificate la crearea unui obiect. De exemplu:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+În acest exemplu, dacă nu se specifică o vârstă la crearea unui obiect `Person`, se va utiliza valoarea implicită de 20 de ani.
+
+Lucrul bun este că definiția proprietății cu inițializarea acesteia prin intermediul constructorului poate fi scurtată și simplificată astfel:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Pentru a fi complet, pe lângă constructori, obiectele pot avea și destructori (metoda `__destruct`) care sunt apelați înainte ca obiectul să fie eliberat din memorie.
+
+
+Spații de nume .[#toc-namespaces]
+---------------------------------
+
+Spațiile de nume ne permit să organizăm și să grupăm clase, funcții și constante înrudite, evitând în același timp conflictele de denumire. Vă puteți gândi la ele ca la dosarele de pe un computer, unde fiecare dosar conține fișiere legate de un anumit proiect sau subiect.
+
+Spațiile de nume sunt deosebit de utile în proiectele mai mari sau atunci când se utilizează biblioteci de la terți, unde pot apărea conflicte de denumire a claselor.
+
+Imaginați-vă că aveți o clasă numită `Car` în proiectul dumneavoastră și doriți să o plasați într-un namespace numit `Transport`. Ați face acest lucru în felul următor:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Dacă doriți să utilizați clasa `Car` într-un alt fișier, trebuie să specificați din ce spațiu de nume provine clasa:
+
+```php
+$car = new Transport\Car;
+```
+
+Pentru simplificare, puteți specifica la începutul fișierului ce clasă dintr-un anumit spațiu de nume doriți să utilizați, ceea ce vă permite să creați instanțe fără a menționa calea completă:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Moștenirea .[#toc-inheritance]
+------------------------------
+
+Moștenirea este un instrument al programării orientate pe obiecte care permite crearea de noi clase pe baza celor existente, moștenind proprietățile și metodele acestora și extinzându-le sau redefinindu-le în funcție de necesități. Moștenirea asigură reutilizarea codului și ierarhia claselor.
+
+Pur și simplu, dacă avem o clasă și dorim să creăm o alta derivată din ea, dar cu unele modificări, putem "moșteni" noua clasă din cea originală.
+
+În PHP, moștenirea este implementată cu ajutorul cuvântului cheie `extends`.
+
+Clasa noastră `Person` stochează informații despre vârstă. Putem avea o altă clasă, `Student`, care extinde `Person` și adaugă informații despre domeniul de studiu.
+
+Să ne uităm la un exemplu:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Cum funcționează acest cod?
+
+- Am folosit cuvântul cheie `extends` pentru a extinde clasa `Person`, ceea ce înseamnă că clasa `Student` moștenește toate metodele și proprietățile de la `Person`.
+
+- Cuvântul cheie `parent::` ne permite să apelăm metode din clasa părinte. În acest caz, am apelat constructorul din clasa `Person` înainte de a adăuga propria noastră funcționalitate la clasa `Student`. Și, în mod similar, metoda strămoșului `printInformation()` înainte de a lista informațiile despre elev.
+
+Moștenirea este destinată situațiilor în care există o relație "este o" între clase. De exemplu, un `Student` este un `Person`. O pisică este un animal. Ne permite ca în cazurile în care ne așteptăm ca un obiect (de exemplu, "Persoană") din cod să folosim în schimb un obiect derivat (de exemplu, "Student").
+
+Este esențial să ne dăm seama că scopul principal al moștenirii **nu este** acela de a preveni duplicarea codului. Dimpotrivă, utilizarea greșită a moștenirii poate duce la un cod complex și greu de întreținut. În cazul în care nu există o relație "este un" între clase, ar trebui să luăm în considerare compoziția în locul moștenirii.
+
+Rețineți că metodele `printInformation()` din clasele `Person` și `Student` furnizează informații ușor diferite. Și putem adăuga alte clase (cum ar fi `Employee`) care vor furniza alte implementări ale acestei metode. Capacitatea obiectelor din clase diferite de a răspunde la aceeași metodă în moduri diferite se numește polimorfism:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Compoziția .[#toc-composition]
+------------------------------
+
+Compoziția este o tehnică prin care, în loc să moștenim proprietăți și metode dintr-o altă clasă, pur și simplu folosim instanța acesteia în clasa noastră. Acest lucru ne permite să combinăm funcționalitățile și proprietățile mai multor clase fără a crea structuri complexe de moștenire.
+
+De exemplu, avem o clasă `Engine` și o clasă `Car`. În loc să spunem "O mașină este un motor", spunem "O mașină are un motor", ceea ce reprezintă o relație de compoziție tipică.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Aici, `Car` nu are toate proprietățile și metodele clasei `Engine`, dar are acces la acestea prin intermediul proprietății `$engine`.
+
+Avantajul compoziției este o mai mare flexibilitate de proiectare și o mai bună adaptabilitate la schimbările viitoare.
+
+
+Vizibilitate .[#toc-visibility]
+-------------------------------
+
+În PHP, puteți defini "vizibilitatea" pentru proprietățile, metodele și constantele clasei. Vizibilitatea determină unde puteți accesa aceste elemente.
+
+1. **Public:** Dacă un element este marcat ca fiind `public`, înseamnă că îl puteți accesa de oriunde, chiar și din afara clasei.
+
+2. **Protected:** Un element marcat ca `protected` este accesibil numai în cadrul clasei și al tuturor descendenților săi (clase care moștenesc din aceasta).
+
+3. **Privat:** Dacă un element este marcat `private`, acesta poate fi accesat numai din interiorul clasei în care a fost definit.
+
+Dacă nu specificați vizibilitatea, PHP o va seta automat la `public`.
+
+Să ne uităm la un exemplu de cod:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Continuăm cu moștenirea claselor:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+În acest caz, metoda `printProperties()` din `ChildClass` poate accesa proprietățile publice și protejate, dar nu poate accesa proprietățile private ale clasei părinte.
+
+Datele și metodele ar trebui să fie cât mai ascunse posibil și să fie accesibile numai printr-o interfață definită. Acest lucru vă permite să modificați implementarea internă a clasei fără a afecta restul codului.
+
+
+Cuvântul cheie final .[#toc-final-keyword]
+------------------------------------------
+
+În PHP, putem folosi cuvântul cheie `final` dacă dorim să împiedicăm moștenirea sau suprapunerea unei clase, metode sau constante. Atunci când o clasă este marcată ca `final`, aceasta nu poate fi extinsă. Atunci când o metodă este marcată ca `final`, aceasta nu poate fi suprascrisă într-o subclasă.
+
+Faptul că știm că o anumită clasă sau metodă nu va mai fi modificată ne permite să facem modificări mai ușor, fără a ne face griji cu privire la eventualele conflicte. De exemplu, putem adăuga o nouă metodă fără să ne temem că un descendent ar putea avea deja o metodă cu același nume, ceea ce ar duce la o coliziune. Sau putem modifica parametrii unei metode, din nou fără riscul de a provoca o inconsecvență cu o metodă suprascrisă într-un descendent.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+În acest exemplu, încercarea de a moșteni din clasa finală `FinalClass` va duce la o eroare.
+
+
+Proprietăți și metode statice .[#toc-static-properties-and-methods]
+-------------------------------------------------------------------
+
+Când vorbim despre elemente "statice" ale unei clase în PHP, ne referim la metode și proprietăți care aparțin clasei în sine, nu unei instanțe specifice a clasei. Acest lucru înseamnă că nu trebuie să creați o instanță a clasei pentru a le accesa. În schimb, le apelați sau le accesați direct prin intermediul numelui clasei.
+
+Rețineți că, deoarece elementele statice aparțin clasei și nu instanțelor sale, nu puteți utiliza pseudo-variabila `$this` în cadrul metodelor statice.
+
+Utilizarea proprietăților statice duce la un [cod ofuscat și plin de capcane |dependency-injection:global-state], așa că nu ar trebui să le folosiți niciodată și nu vom arăta un exemplu aici. Pe de altă parte, metodele statice sunt utile. Iată un exemplu:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+În acest exemplu, am creat o clasă `Calculator` cu două metode statice. Putem apela aceste metode direct fără a crea o instanță a clasei folosind operatorul `::`. Metodele statice sunt utile în special pentru operațiile care nu depind de starea unei instanțe specifice a clasei.
+
+
+Constantele clasei .[#toc-class-constants]
+------------------------------------------
+
+În cadrul claselor, avem opțiunea de a defini constante. Constantele sunt valori care nu se schimbă niciodată în timpul execuției programului. Spre deosebire de variabile, valoarea unei constante rămâne aceeași.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+În acest exemplu, avem o clasă `Car` cu constanta `NumberOfWheels`. Atunci când accesăm constanta în interiorul clasei, putem folosi cuvântul cheie `self` în loc de numele clasei.
+
+
+Interfețe de obiecte .[#toc-object-interfaces]
+----------------------------------------------
+
+Interfețele de obiect acționează ca "contracte" pentru clase. Dacă o clasă trebuie să implementeze o interfață de obiect, aceasta trebuie să conțină toate metodele definite de interfață. Este o modalitate excelentă de a vă asigura că anumite clase respectă același "contract" sau structură.
+
+În PHP, interfețele sunt definite cu ajutorul cuvântului cheie `interface`. Toate metodele definite într-o interfață sunt publice (`public`). Atunci când o clasă implementează o interfață, aceasta utilizează cuvântul cheie `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+În cazul în care o clasă implementează o interfață, dar nu sunt definite toate metodele așteptate, PHP va genera o eroare.
+
+O clasă poate implementa mai multe interfețe în același timp, ceea ce este diferit de moștenire, unde o clasă poate moșteni doar de la o singură clasă:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Clase abstracte .[#toc-abstract-classes]
+----------------------------------------
+
+Clasele abstracte servesc drept șabloane de bază pentru alte clase, dar nu puteți crea instanțe ale acestora în mod direct. Ele conțin un amestec de metode complete și metode abstracte care nu au un conținut definit. Clasele care moștenesc din clase abstracte trebuie să furnizeze definiții pentru toate metodele abstracte de la părintele lor.
+
+Utilizăm cuvântul cheie `abstract` pentru a defini o clasă abstractă.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+În acest exemplu, avem o clasă abstractă cu o metodă obișnuită și una abstractă. Apoi avem o clasă `Child` care moștenește din `AbstractClass` și oferă o implementare pentru metoda abstractă.
+
+Prin ce se deosebesc interfețele și clasele abstracte? Clasele abstracte pot conține atât metode abstracte, cât și metode concrete, în timp ce interfețele definesc doar metodele pe care clasa trebuie să le implementeze, dar nu oferă nicio implementare. O clasă poate moșteni dintr-o singură clasă abstractă, dar poate implementa un număr nelimitat de interfețe.
+
+
+Verificarea tipurilor .[#toc-type-checking]
+-------------------------------------------
+
+În programare, este esențial să ne asigurăm că datele cu care lucrăm sunt de tipul corect. În PHP, dispunem de instrumente care oferă această asigurare. Verificarea faptului că datele sunt de tipul corect se numește "verificare de tip".
+
+Tipuri pe care le putem întâlni în PHP:
+
+1. **Tipuri de bază**: Acestea includ `int` (numere întregi), `float` (numere cu virgulă mobilă), `bool` (valori booleene), `string` (șiruri de caractere), `array` (matrice) și `null`.
+2. **Classe**: Atunci când dorim ca o valoare să fie o instanță a unei anumite clase.
+3. **Interfețe**: Definește un set de metode pe care o clasă trebuie să le implementeze. O valoare care corespunde unei interfețe trebuie să aibă aceste metode.
+4. **Tipuri mixte**: Putem specifica faptul că o variabilă poate avea mai multe tipuri permise.
+5. **Void**: Acest tip special indică faptul că o funcție sau o metodă nu returnează nicio valoare.
+
+Să vedem cum să modificăm codul pentru a include tipurile:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+În acest fel, ne asigurăm că codul nostru așteaptă și lucrează cu date de tipul corect, ceea ce ne ajută să prevenim eventualele erori.
+
+Unele tipuri nu pot fi scrise direct în PHP. În acest caz, ele sunt listate în comentariul phpDoc, care este formatul standard pentru documentarea codului PHP, începând cu `/**` și terminând cu `*/`. Acesta vă permite să adăugați descrieri ale claselor, metodelor și așa mai departe. Și, de asemenea, de a enumera tipurile complexe folosind așa-numitele adnotări `@var`, `@param` și `@return`. Aceste tipuri sunt apoi utilizate de instrumentele de analiză statică a codului, dar nu sunt verificate de PHP însuși.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Comparație și identitate .[#toc-comparison-and-identity]
+--------------------------------------------------------
+
+În PHP, puteți compara obiecte în două moduri:
+
+1. Compararea valorilor `==`: Verifică dacă obiectele sunt din aceeași clasă și au aceleași valori în proprietățile lor.
+2. Identitate `===`: Verifică dacă este vorba de aceeași instanță a obiectului.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Operatorul `instanceof` .[#toc-the-instanceof-operator]
+-------------------------------------------------------
+
+Operatorul `instanceof` vă permite să determinați dacă un obiect dat este o instanță a unei anumite clase, un descendent al acelei clase sau dacă implementează o anumită interfață.
+
+Imaginați-vă că avem o clasă `Person` și o altă clasă `Student`, care este un descendent al `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Din rezultatele obținute, este evident că obiectul `$student` este considerat o instanță atât a clasei `Student`, cât și a clasei `Person`.
+
+
+Interfețe fluente .[#toc-fluent-interfaces]
+-------------------------------------------
+
+O "interfață fluidă" este o tehnică din OOP care permite înlănțuirea metodelor într-un singur apel. Acest lucru simplifică și clarifică adesea codul.
+
+Elementul cheie al unei interfețe fluente este că fiecare metodă din lanț returnează o referință la obiectul curent. Acest lucru se realizează prin utilizarea `return $this;` la sfârșitul metodei. Acest stil de programare este adesea asociat cu metode numite "setters", care stabilesc valorile proprietăților unui obiect.
+
+Să vedem cum ar putea arăta o interfață fluentă pentru trimiterea de e-mailuri:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+În acest exemplu, metodele `setFrom()`, `setRecipient()`, și `setMessage()` sunt utilizate pentru a seta valorile corespunzătoare (expeditor, destinatar, conținutul mesajului). După stabilirea fiecăreia dintre aceste valori, metodele returnează obiectul curent (`$email`), permițându-ne să înlănțuim o altă metodă după ea. În cele din urmă, apelăm metoda `send()`, care trimite efectiv e-mailul.
+
+Datorită interfețelor fluente, putem scrie un cod intuitiv și ușor de citit.
+
+
+Copiere cu `clone` .[#toc-copying-with-clone]
+---------------------------------------------
+
+În PHP, putem crea o copie a unui obiect folosind operatorul `clone`. În acest fel, obținem o nouă instanță cu conținut identic.
+
+Dacă avem nevoie să modificăm unele dintre proprietăți atunci când copiem un obiect, putem defini o metodă specială `__clone()` în clasă. Această metodă este apelată automat atunci când obiectul este clonat.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+În acest exemplu, avem o clasă `Sheep` cu o proprietate `$name`. Atunci când clonăm o instanță a acestei clase, metoda `__clone()` se asigură că numele oii clonate primește prefixul "Clone of".
+
+
+Trăsături .[#toc-traits]
+------------------------
+
+În PHP, trăsăturile sunt un instrument care permite partajarea metodelor, proprietăților și constantelor între clase și previne duplicarea codului. Vă puteți gândi la ele ca la un mecanism de "copy and paste" (Ctrl-C și Ctrl-V), în care conținutul unei trăsături este "lipit" în clase. Acest lucru vă permite să reutilizați codul fără a fi nevoie să creați ierarhii complicate de clase.
+
+Să aruncăm o privire la un exemplu simplu de utilizare a trăsăturilor în PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+În acest exemplu, avem o trăsătură numită `Honking` care conține o metodă `honk()`. Apoi, avem două clase: `Car` și `Truck`, ambele folosind trăsătura `Honking`. Ca urmare, ambele clase "au" metoda `honk()` și o putem apela pe obiectele ambelor clase.
+
+Trăsăturile vă permit să partajați ușor și eficient codul între clase. Ele nu intră în ierarhia de moștenire, adică `$car instanceof Honking` va returna `false`.
+
+
+Excepții
+--------
+
+Excepțiile din OOP ne permit să gestionăm cu grație erorile și situațiile neașteptate din codul nostru. Acestea sunt obiecte care conțin informații despre o eroare sau o situație neobișnuită.
+
+În PHP, avem o clasă încorporată `Exception`, care servește drept bază pentru toate excepțiile. Aceasta are mai multe metode care ne permit să obținem mai multe informații despre excepție, cum ar fi mesajul de eroare, fișierul și linia în care a apărut eroarea etc.
+
+Atunci când apare o eroare în cod, putem "arunca" excepția folosind cuvântul cheie `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Atunci când funcția `division()` primește null ca al doilea argument, se aruncă o excepție cu mesajul de eroare `'Division by zero!'`. Pentru a preveni blocarea programului atunci când este lansată excepția, o blocăm în blocul `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Codul care poate arunca o excepție este inclus într-un bloc `try`. În cazul în care excepția este lansată, execuția codului se mută într-un bloc `catch`, unde putem gestiona excepția (de exemplu, scriind un mesaj de eroare).
+
+După blocurile `try` și `catch`, putem adăuga un bloc opțional `finally`, care este întotdeauna executat, indiferent dacă excepția a fost sau nu lansată (chiar dacă folosim `return`, `break` sau `continue` în blocul `try` sau `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Putem, de asemenea, să ne creăm propriile clase de excepții (ierarhie) care moștenesc din clasa Exception. Ca exemplu, să considerăm o aplicație bancară simplă care permite depuneri și retrageri:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Se pot specifica mai multe blocuri `catch` pentru un singur bloc `try` dacă se așteaptă diferite tipuri de excepții.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+În acest exemplu, este important să rețineți ordinea blocurilor `catch`. Deoarece toate excepțiile moștenesc de la `BankingException`, dacă am avea acest bloc primul, toate excepțiile ar fi prinse în el fără ca codul să ajungă la blocurile `catch` ulterioare. Prin urmare, este important ca excepțiile mai specifice (adică cele care moștenesc de la altele) să fie mai sus în ordinea blocului `catch` decât excepțiile părinte.
+
+
+Iterații .[#toc-iterations]
+---------------------------
+
+În PHP, puteți parcurge obiectele în buclă folosind bucla `foreach`, la fel cum parcurgeți o matrice. Pentru ca acest lucru să funcționeze, obiectul trebuie să implementeze o interfață specială.
+
+Prima opțiune este să implementați interfața `Iterator`, care are metodele `current()` care returnează valoarea curentă, `key()` care returnează cheia, `next()` care trece la următoarea valoare, `rewind()` care trece la început și `valid()` care verifică dacă am ajuns deja la sfârșit.
+
+Cealaltă opțiune este să implementăm o interfață `IteratorAggregate`, care are o singură metodă `getIterator()`. Aceasta fie returnează un obiect de tip "placeholder" care va furniza traversarea, fie poate fi un generator, care este o funcție specială care utilizează `yield` pentru a returna chei și valori în mod secvențial:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Cele mai bune practici .[#toc-best-practices]
+---------------------------------------------
+
+Odată ce ați învățat principiile de bază ale programării orientate pe obiecte, este esențial să vă concentrați asupra celor mai bune practici în OOP. Acestea vă vor ajuta să scrieți un cod care să fie nu numai funcțional, ci și ușor de citit, de înțeles și de întreținut.
+
+1) **Separarea preocupărilor**: Fiecare clasă ar trebui să aibă o responsabilitate clar definită și ar trebui să abordeze doar o singură sarcină principală. Dacă o clasă face prea multe lucruri, ar putea fi indicat să o împărțiți în clase mai mici, specializate.
+2) **Încapsularea**: Datele și metodele ar trebui să fie cât mai ascunse posibil și să fie accesibile numai printr-o interfață definită. Acest lucru vă permite să modificați implementarea internă a unei clase fără a afecta restul codului.
+3) **Injectarea dependenței**: În loc să creați dependențe direct în interiorul unei clase, ar trebui să le "injectați" din exterior. Pentru o înțelegere mai profundă a acestui principiu, vă recomandăm [capitolele despre Injecția de dependență |dependency-injection:introduction].
diff --git a/nette/ro/troubleshooting.texy b/nette/ro/troubleshooting.texy
index 254c6434ec..2435740c53 100644
--- a/nette/ro/troubleshooting.texy
+++ b/nette/ro/troubleshooting.texy
@@ -18,7 +18,7 @@ Puteți găsi întotdeauna motivul erorii în directorul `log/`. Cu toate aceste
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // adresa dumneavoastră IP
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Eroare 404, rutarea nu funcționează .[#toc-error-404-routing-not-working]
 Atunci când toate paginile (cu excepția paginii de start) returnează o eroare 404, se pare că este vorba de o problemă de configurare a serverului pentru [URL-urile frumoase |#How to Configure a Server for Nice URLs?].
 
 
+Cum se dezactivează memoria cache în timpul dezvoltării? .[#toc-how-to-disable-cache-during-development]
+--------------------------------------------------------------------------------------------------------
+Nette este inteligent și nu este nevoie să dezactivați memoria cache în el. În timpul dezvoltării, acesta actualizează automat memoria cache ori de câte ori există o modificare în șablon sau în configurația containerului DI. Mai mult, modul de dezvoltare este activat prin autodetecție, așa că, de obicei, nu este nevoie să configurați nimic, [sau doar adresa IP |application:bootstrap#development-vs-production-mode].
+
+Atunci când depanați routerul, vă recomandăm să dezactivați memoria cache a browserului, unde, de exemplu, ar putea fi stocate redirecționările: deschideți Developer Tools (Ctrl+Shift+I sau Cmd+Option+I) și în panoul Network (Rețea), bifați caseta pentru dezactivarea memoriei cache.
+
+
 Eroare `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Această eroare apare în cazul în care ați actualizat PHP la versiunea 8.1, dar utilizați Nette, care nu este compatibil cu aceasta. Așadar, soluția este să actualizați Nette la o versiune mai nouă folosind `composer update`. Nette suportă PHP 8.1 încă de la versiunea 3.0. Dacă folosiți o versiune mai veche (puteți afla căutând în `composer.json`), [actualizați Nette |migrations:en] sau rămâneți cu PHP 8.0.
@@ -67,7 +74,7 @@ Directorul `www/` utilizat în proiectele de exemplu din Nette este așa-numitul
 
 Pentru a rula aplicația pe găzduire, trebuie să setați documentul-root la acest director în configurația de găzduire. Sau, dacă găzduirea are un dosar predefinit pentru directorul public cu un nume diferit (de exemplu `web`, `public_html` etc.), pur și simplu redenumiți-l `www/`.
 
-Soluția **nu este** de a "scăpa" de folderul `www/` folosind reguli în fișierul `.htaccess` sau în router. Dacă găzduirea nu v-ar permite să setați document-root la un subdirectoriu (adică să creați directoare cu un nivel deasupra directorului public), căutați alta. În caz contrar, v-ați asuma un risc de securitate semnificativ. Ar fi ca și cum ați locui într-un apartament în care nu puteți închide ușa de la intrare și este mereu larg deschisă.
+Soluția **nu este** de a împiedica accesul la toate dosarele, cu excepția `www/`, folosind reguli în fișierul `.htaccess` sau în router. În cazul în care serviciul de găzduire nu permite setarea rădăcinii documentului într-un subdirectoriu (adică crearea de directoare la un nivel superior directorului public), ar trebui să căutați un alt serviciu de găzduire. În caz contrar, v-ați expune la riscuri de securitate semnificative. Ar fi ca și cum ați locui într-un apartament în care ușa de la intrare nu poate fi închisă și este întotdeauna larg deschisă.
 
 
 Cum se configurează un server pentru URL-uri frumoase? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/ru/@home.texy b/nette/ru/@home.texy
index fbf9ee8c63..e00f7de000 100644
--- a/nette/ru/@home.texy
+++ b/nette/ru/@home.texy
@@ -84,11 +84,11 @@
 - [utils:JSON]
 - [NEON|neon:]
 - [Password Hashing |security:passwords]
-- [utils:SmartObject]
 - [PHP Reflection |utils:reflection]
 - [utils:Strings]
 - [Валидаторы |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...другое |utils:]
 </div>
diff --git a/nette/ru/installation.texy b/nette/ru/installation.texy
index 230676af6a..97bbf8671f 100644
--- a/nette/ru/installation.texy
+++ b/nette/ru/installation.texy
@@ -20,7 +20,7 @@ Nette представляет собой набор полезных и сло
 composer require nette/utils
 ```
 
-Вы предпочитаете графический интерфейс? Ознакомьтесь с [руководством |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] по установке пакетов в среде PhpStrom.
+Вы предпочитаете графический интерфейс? Ознакомьтесь с [руководством |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] по установке пакетов в среде PhpStorm.
 
 
 Как начать новый проект с помощью Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/ru/introduction-to-object-oriented-programming.texy b/nette/ru/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..a8ab9c61e5
--- /dev/null
+++ b/nette/ru/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Введение в объектно-ориентированное программирование
+****************************************************
+
+.[perex]
+Термин "ООП" означает объектно-ориентированное программирование - способ организации и структурирования кода. ООП позволяет рассматривать программу не как последовательность команд и функций, а как набор объектов, взаимодействующих друг с другом.
+
+В ООП "объект" - это единица, содержащая данные и функции, которые оперируют этими данными. Объекты создаются на основе "классов", которые можно понимать как чертежи или шаблоны объектов. Имея класс, мы можем создать его "экземпляр", то есть конкретный объект, созданный на основе этого класса.
+
+Рассмотрим, как можно создать простой класс в PHP. При определении класса используется ключевое слово "class", за которым следует имя класса, а затем фигурные скобки, в которые заключаются функции класса (называемые "методами") и переменные класса (называемые "свойствами" или "атрибутами"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+В данном примере мы создали класс `Car` с одной функцией (или "методом") `honk`.
+
+Каждый класс должен решать только одну основную задачу. Если класс решает слишком много задач, то целесообразно разделить его на более мелкие, специализированные классы.
+
+Классы обычно хранятся в отдельных файлах, что позволяет упорядочить код и облегчить навигацию по нему. Имя файла должно совпадать с именем класса, поэтому для класса `Car` имя файла будет `Car.php`.
+
+При именовании классов следует придерживаться правила "PascalCase", то есть каждое слово в имени начинается с заглавной буквы, без подчеркиваний и других разделителей. Методы и свойства следует называть в "camelCase", то есть со строчной буквы.
+
+Некоторые методы в PHP играют особую роль и имеют префикс `__` (два знака подчеркивания). Одним из наиболее важных специальных методов является "конструктор", обозначаемый как `__construct`. Конструктор - это метод, который автоматически вызывается при создании нового экземпляра класса.
+
+Мы часто используем конструктор для установки начального состояния объекта. Например, при создании объекта, представляющего человека, с помощью конструктора можно задать его возраст, имя или другие атрибуты.
+
+Рассмотрим, как использовать конструктор в PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+В данном примере класс `Person` имеет свойство (переменную) `$age` и конструктор, который устанавливает это свойство. Затем метод `howOldAreYou()` предоставляет доступ к возрасту человека.
+
+Псевдопеременная `$this` используется внутри класса для доступа к свойствам и методам объекта.
+
+Ключевое слово `new` используется для создания нового экземпляра класса. В приведенном примере мы создали нового человека в возрасте 25 лет.
+
+Также можно задать значения по умолчанию для параметров конструктора, если они не указаны при создании объекта. Например:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+В данном примере, если при создании объекта `Person` не указать возраст, будет использовано значение по умолчанию 20.
+
+Приятно то, что определение свойства с его инициализацией через конструктор можно сократить и упростить следующим образом:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Для полноты картины, в дополнение к конструкторам, объекты могут иметь деструкторы (метод `__destruct`), которые вызываются перед освобождением объекта из памяти.
+
+
+Пространства имен .[#toc-namespaces]
+------------------------------------
+
+Пространства имен позволяют упорядочить и сгруппировать связанные классы, функции и константы, избегая при этом конфликтов имен. Их можно представить себе как папки на компьютере, где каждая папка содержит файлы, относящиеся к определенному проекту или теме.
+
+Пространства имен особенно полезны в больших проектах или при использовании сторонних библиотек, где могут возникать конфликты в наименованиях классов.
+
+Представьте, что в вашем проекте есть класс с именем `Car`, и вы хотите поместить его в пространство имен `Transport`. Это можно сделать следующим образом:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Если вы хотите использовать класс `Car` в другом файле, то вам необходимо указать, из какого пространства имен он происходит:
+
+```php
+$car = new Transport\Car;
+```
+
+Для упрощения можно указать в начале файла, какой класс из того или иного пространства имен вы хотите использовать, что позволит создавать экземпляры без указания полного пути:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Наследование .[#toc-inheritance]
+--------------------------------
+
+Наследование - это инструмент объектно-ориентированного программирования, позволяющий создавать новые классы на основе существующих, наследуя их свойства и методы, а также расширяя или переопределяя их по мере необходимости. Наследование обеспечивает многократное использование кода и иерархию классов.
+
+Проще говоря, если у нас есть один класс и мы хотим создать другой, производный от него, но с некоторыми изменениями, то мы можем "унаследовать" новый класс от исходного.
+
+В PHP наследование реализуется с помощью ключевого слова `extends`.
+
+Наш класс `Person` хранит информацию о возрасте. Мы можем иметь другой класс, `Student`, который расширяет `Person` и добавляет информацию о специальности.
+
+Рассмотрим пример:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Как работает этот код?
+
+- Мы использовали ключевое слово `extends` для расширения класса `Person`, то есть класс `Student` наследует все методы и свойства от `Person`.
+
+- Ключевое слово `parent::` позволяет нам вызывать методы из родительского класса. В данном случае мы вызвали конструктор из класса `Person`, прежде чем добавить собственную функциональность в класс `Student`. И аналогично, метод предка `printInformation()` перед выводом информации о студентах.
+
+Наследование предназначено для ситуаций, когда между классами существует связь "есть". Например, `Student` - это `Person`. Кошка - это животное. Это позволяет нам в случаях, когда в коде ожидается один объект (например, "Person"), использовать вместо него производный объект (например, "Student").
+
+Важно понимать, что основная цель наследования **не** заключается в предотвращении дублирования кода. Напротив, неправильное использование наследования может привести к появлению сложного и трудноразрешимого кода. Если между классами нет отношения "является", то вместо наследования следует рассмотреть композицию.
+
+Обратите внимание, что методы `printInformation()` в классах `Person` и `Student` выводят немного другую информацию. И мы можем добавить другие классы (например, `Employee`), которые будут предоставлять другие реализации этого метода. Способность объектов разных классов по-разному реагировать на один и тот же метод называется полиморфизмом:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Композиция .[#toc-composition]
+------------------------------
+
+Композиция - это техника, при которой вместо наследования свойств и методов другого класса мы просто используем его экземпляр в своем классе. Это позволяет объединить функциональные возможности и свойства нескольких классов без создания сложных структур наследования.
+
+Например, у нас есть класс `Engine` и класс `Car`. Вместо того чтобы сказать "Автомобиль - это двигатель", мы говорим "Автомобиль имеет двигатель", что является типичным композиционным отношением.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Здесь `Car` не имеет всех свойств и методов `Engine`, но имеет доступ к ним через свойство `$engine`.
+
+Преимуществом композиции является большая гибкость проектирования и лучшая адаптируемость к будущим изменениям.
+
+
+Наглядность .[#toc-visibility]
+------------------------------
+
+В PHP можно определить "видимость" для свойств, методов и констант класса. Видимость определяет, где можно получить доступ к этим элементам.
+
+1. **Public:** Если элемент помечен как `public`, это означает, что вы можете получить к нему доступ из любого места, даже за пределами класса.
+
+2. **Защищенный:** Элемент, помеченный как `protected`, доступен только в пределах данного класса и всех его потомков (классов, наследующих от него).
+
+3. **Private:** Если элемент помечен как `private`, то доступ к нему возможен только из класса, в котором он был определен.
+
+Если не указать значение видимости, PHP автоматически установит его равным `public`.
+
+Рассмотрим пример кода:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Продолжаем наследование классов:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+В данном случае метод `printProperties()` в `ChildClass` может получить доступ к публичным и защищенным свойствам, но не может получить доступ к приватным свойствам родительского класса.
+
+Данные и методы должны быть максимально скрыты и доступны только через определенный интерфейс. Это позволяет изменять внутреннюю реализацию класса, не затрагивая остальной части кода.
+
+
+Ключевое слово final .[#toc-final-keyword]
+------------------------------------------
+
+В PHP мы можем использовать ключевое слово `final`, если хотим запретить наследование или переопределение класса, метода или константы. Если класс помечен как `final`, он не может быть расширен. Если метод помечен как `final`, он не может быть переопределен в подклассе.
+
+Знание того, что определенный класс или метод больше не будет модифицироваться, позволяет нам легче вносить изменения, не беспокоясь о возможных конфликтах. Например, мы можем добавить новый метод, не опасаясь, что у потомка уже есть метод с таким же именем, что приведет к коллизии. Или мы можем изменить параметры метода, опять же не опасаясь, что это приведет к несоответствию с переопределенным методом потомка.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+В данном примере попытка наследоваться от конечного класса `FinalClass` приведет к ошибке.
+
+
+Статические свойства и методы .[#toc-static-properties-and-methods]
+-------------------------------------------------------------------
+
+Когда мы говорим о "статических" элементах класса в PHP, мы имеем в виду методы и свойства, которые принадлежат самому классу, а не его конкретному экземпляру. Это означает, что для доступа к ним не нужно создавать экземпляр класса. Вместо этого вы вызываете или обращаетесь к ним непосредственно через имя класса.
+
+Следует помнить, что поскольку статические элементы принадлежат классу, а не его экземплярам, то внутри статических методов нельзя использовать псевдопеременную `$this`.
+
+Использование статических свойств приводит к [обфусцированному коду, полному подводных камней |dependency-injection:global-state], поэтому их никогда не следует использовать, и мы не будем приводить здесь пример. С другой стороны, статические методы полезны. Вот пример:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+В этом примере мы создали класс `Calculator` с двумя статическими методами. Мы можем вызывать эти методы напрямую, не создавая экземпляр класса, используя оператор `::`. Статические методы особенно полезны для операций, которые не зависят от состояния конкретного экземпляра класса.
+
+
+Константы класса .[#toc-class-constants]
+----------------------------------------
+
+Внутри классов мы имеем возможность определять константы. Константы - это значения, которые никогда не изменяются в процессе выполнения программы. В отличие от переменных, значение константы остается неизменным.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+В данном примере мы имеем класс `Car` с константой `NumberOfWheels`. При обращении к константе внутри класса мы можем использовать ключевое слово `self` вместо имени класса.
+
+
+Объектные интерфейсы .[#toc-object-interfaces]
+----------------------------------------------
+
+Объектные интерфейсы выступают в роли "контрактов" для классов. Если класс должен реализовать объектный интерфейс, то он должен содержать все методы, определяемые интерфейсом. Это отличный способ гарантировать, что определенные классы придерживаются одного и того же "контракта" или структуры.
+
+В PHP интерфейсы определяются с помощью ключевого слова `interface`. Все методы, определенные в интерфейсе, являются публичными (`public`). Когда класс реализует интерфейс, он использует ключевое слово `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Если класс реализует интерфейс, но не все ожидаемые методы определены, PHP выдаст ошибку.
+
+Класс может реализовывать несколько интерфейсов одновременно, что отличается от наследования, когда класс может наследоваться только от одного класса:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Абстрактные классы .[#toc-abstract-classes]
+-------------------------------------------
+
+Абстрактные классы служат базовыми шаблонами для других классов, но их экземпляры нельзя создавать напрямую. Они содержат смесь полных методов и абстрактных методов, которые не имеют определенного содержания. Классы, наследующие от абстрактных классов, должны предоставлять определения для всех абстрактных методов родительского класса.
+
+Для определения абстрактного класса мы используем ключевое слово `abstract`.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+В данном примере мы имеем абстрактный класс с одним обычным и одним абстрактным методом. Затем у нас есть класс `Child`, который наследуется от `AbstractClass` и предоставляет реализацию абстрактного метода.
+
+Чем отличаются интерфейсы и абстрактные классы? Абстрактные классы могут содержать как абстрактные, так и конкретные методы, в то время как интерфейсы только определяют, какие методы должен реализовать класс, но не предоставляют никакой реализации. Класс может наследоваться только от одного абстрактного класса, но может реализовать любое количество интерфейсов.
+
+
+Проверка типа .[#toc-type-checking]
+-----------------------------------
+
+В программировании очень важно убедиться в том, что данные, с которыми мы работаем, имеют правильный тип. В PHP есть инструменты, позволяющие обеспечить такую гарантию. Проверка правильности типа данных называется "проверкой типа".
+
+Типы, с которыми мы можем столкнуться в PHP:
+
+1. **Базовые типы**: К ним относятся `int` (целые числа), `float` (числа с плавающей точкой), `bool` (булевы значения), `string` (строки), `array` (массивы) и `null`.
+2. **Классы**: Когда мы хотим, чтобы значение было экземпляром определенного класса.
+3. **Интерфейсы**: Определяют набор методов, которые должен реализовать класс. Значение, удовлетворяющее интерфейсу, должно обладать этими методами.
+4. **Смешанные типы**: Мы можем указать, что переменная может иметь несколько допустимых типов.
+5. **Void**: Этот специальный тип указывает на то, что функция или метод не возвращает никакого значения.
+
+Рассмотрим, как модифицировать код для включения типов:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Таким образом, мы гарантируем, что наш код ожидает и работает с данными правильного типа, что помогает нам предотвратить возможные ошибки.
+
+Некоторые типы не могут быть написаны непосредственно в PHP. В этом случае они перечисляются в комментариях phpDoc - это стандартный формат документирования PHP-кода, начинающийся с `/**` и заканчивающийся `*/`. Он позволяет добавлять описания классов, методов и так далее. А также перечислять сложные типы с помощью так называемых аннотаций `@var`, `@param` и `@return`. Эти типы затем используются инструментами статического анализа кода, но не проверяются самим PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Сравнение и идентичность .[#toc-comparison-and-identity]
+--------------------------------------------------------
+
+В PHP можно сравнивать объекты двумя способами:
+
+1. Сравнение по значению `==`: проверяется, относятся ли объекты к одному классу и имеют ли они одинаковые значения в своих свойствах.
+2. Идентичность `===`: Проверяет, является ли объект одним и тем же экземпляром.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Оператор `instanceof` .[#toc-the-instanceof-operator]
+-----------------------------------------------------
+
+Оператор `instanceof` позволяет определить, является ли данный объект экземпляром определенного класса, потомком этого класса или реализует ли он определенный интерфейс.
+
+Представьте, что у нас есть класс `Person` и другой класс `Student`, который является потомком `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Из выводов видно, что объект `$student` считается экземпляром обоих классов `Student` и `Person`.
+
+
+Текучие интерфейсы .[#toc-fluent-interfaces]
+--------------------------------------------
+
+Fluent Interface" - это техника в ООП, позволяющая объединять методы в цепочку одним вызовом. Это часто упрощает и уточняет код.
+
+Ключевым элементом флюентного интерфейса является то, что каждый метод в цепочке возвращает ссылку на текущий объект. Это достигается за счет использования `return $this;` в конце метода. Такой стиль программирования часто ассоциируется с методами, называемыми "сеттерами", которые устанавливают значения свойств объекта.
+
+Давайте посмотрим, как может выглядеть свободный интерфейс для отправки электронной почты:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+В данном примере методы `setFrom()`, `setRecipient()` и `setMessage()` используются для установки соответствующих значений (отправитель, получатель, содержание сообщения). После установки каждого из этих значений методы возвращают текущий объект (`$email`), что позволяет выстроить после него цепочку других методов. Наконец, мы вызываем метод `send()`, который, собственно, и отправляет письмо.
+
+Благодаря свободным интерфейсам мы можем писать интуитивно понятный и легко читаемый код.
+
+
+Копирование с помощью `clone` .[#toc-copying-with-clone]
+--------------------------------------------------------
+
+В PHP мы можем создать копию объекта с помощью оператора `clone`. Таким образом, мы получаем новый экземпляр с идентичным содержимым.
+
+Если при копировании объекта нам необходимо изменить некоторые его свойства, мы можем определить в классе специальный метод `__clone()`. Этот метод автоматически вызывается при клонировании объекта.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+В данном примере мы имеем класс `Sheep` с одним свойством `$name`. Когда мы клонируем экземпляр этого класса, метод `__clone()` гарантирует, что имя клонированной овцы получит префикс "Clone of".
+
+
+Свойства .[#toc-traits]
+-----------------------
+
+Трейты в PHP - это инструмент, позволяющий совместно использовать методы, свойства и константы между классами и предотвращающий дублирование кода. Их можно рассматривать как механизм "копирования и вставки" (Ctrl-C и Ctrl-V), когда содержимое трейта "вставляется" в классы. Это позволяет повторно использовать код без создания сложных иерархий классов.
+
+Рассмотрим простой пример использования трейтов в PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+В этом примере у нас есть тред `Honking`, содержащий один метод `honk()`. Затем у нас есть два класса: `Car` и `Truck`, оба из которых используют признак `Honking`. В результате оба класса "имеют" метод `honk()`, и мы можем вызывать его на объектах обоих классов.
+
+Трейты позволяют легко и эффективно обмениваться кодом между классами. Они не входят в иерархию наследования, т.е. `$car instanceof Honking` вернет `false`.
+
+
+Исключения
+----------
+
+Исключения в ООП позволяют нам изящно обрабатывать ошибки и неожиданные ситуации в нашем коде. Они представляют собой объекты, которые несут информацию об ошибке или необычной ситуации.
+
+В PHP есть встроенный класс `Exception`, который служит основой для всех исключений. Он имеет несколько методов, которые позволяют получить дополнительную информацию об исключении, например, сообщение об ошибке, файл и строку, в которой произошла ошибка, и т.д.
+
+Когда в коде возникает ошибка, мы можем "выбросить" исключение, используя ключевое слово `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Когда функция `division()` получает null в качестве второго аргумента, она выбрасывает исключение с сообщением об ошибке `'Division by zero!'`. Чтобы предотвратить аварийное завершение программы при возникновении исключения, мы перехватываем его в блоке `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Код, который может выбросить исключение, оборачивается в блок `try`. Если исключение выброшено, выполнение кода переходит в блок `catch`, где мы можем обработать исключение (например, написать сообщение об ошибке).
+
+После блоков `try` и `catch` можно добавить необязательный блок `finally`, который выполняется всегда, независимо от того, было ли выброшено исключение или нет (даже если мы используем `return`, `break` или `continue` в блоке `try` или `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Мы также можем создавать собственные классы исключений (иерархию), которые наследуются от класса Exception. В качестве примера рассмотрим простое банковское приложение, которое позволяет вносить и снимать деньги:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Для одного блока `try` можно указать несколько блоков `catch`, если вы ожидаете различные типы исключений.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+В этом примере важно обратить внимание на порядок следования блоков `catch`. Поскольку все исключения наследуются от `BankingException`, то если бы этот блок был первым, то все исключения были бы пойманы в нем, а код не дошел бы до последующих блоков `catch`. Поэтому важно, чтобы более специфические исключения (т.е. те, которые наследуются от других) располагались выше в порядке блоков `catch`, чем их родительские исключения.
+
+
+Итерации .[#toc-iterations]
+---------------------------
+
+В PHP вы можете перебирать объекты с помощью цикла `foreach`, подобно тому, как вы перебираете массивы. Чтобы это работало, объект должен реализовать специальный интерфейс.
+
+Первый вариант - реализовать интерфейс `Iterator`, в котором есть методы `current()`, возвращающие текущее значение, `key()`, возвращающие ключ, `next()`, переходящие к следующему значению, `rewind()`, переходящие к началу, и `valid()`, проверяющие, дошли ли мы до конца.
+
+Другой вариант - реализовать интерфейс `IteratorAggregate`, который имеет только один метод `getIterator()`. Он либо возвращает объект-заполнитель, который обеспечит обход, либо может быть генератором, то есть специальной функцией, которая использует `yield` для последовательного возврата ключей и значений:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Лучшие практики .[#toc-best-practices]
+--------------------------------------
+
+После того как вы освоили основные принципы объектно-ориентированного программирования, необходимо обратить внимание на лучшие практики ООП. Это поможет вам писать не только функциональный, но и читабельный, понятный и легко сопровождаемый код.
+
+1) **Разделение обязанностей**: Каждый класс должен иметь четко определенную ответственность и решать только одну основную задачу. Если класс выполняет слишком много задач, то целесообразно разделить его на более мелкие специализированные классы.
+2) **Инкапсуляция**: Данные и методы должны быть максимально скрыты и доступны только через определенный интерфейс. Это позволяет изменять внутреннюю реализацию класса, не затрагивая остальной код.
+3) **Инъекция зависимостей**: Вместо того чтобы создавать зависимости непосредственно внутри класса, следует "инжектировать" их извне. Для более глубокого понимания этого принципа мы рекомендуем [главы, посвященные Dependency Injection |dependency-injection:introduction].
diff --git a/nette/ru/troubleshooting.texy b/nette/ru/troubleshooting.texy
index 4717eed854..4db89b8096 100644
--- a/nette/ru/troubleshooting.texy
+++ b/nette/ru/troubleshooting.texy
@@ -18,7 +18,7 @@ Nette не работает, отображается белая страниц
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // ваш IP-адрес
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Tracy сообщит, почему он не может вести журнал.
 Когда все страницы (кроме домашней) выдают ошибку 404, это похоже на проблему конфигурации сервера для [красивых URL |#How to Configure a Server for Nice URLs?].
 
 
+Как отключить кэш во время разработки? .[#toc-how-to-disable-cache-during-development]
+--------------------------------------------------------------------------------------
+Nette - умный продукт, и отключать кэширование в нем не нужно. Во время разработки он автоматически обновляет кэш при каждом изменении шаблона или конфигурации DI-контейнера. Более того, режим разработки включается по автоопределению, поэтому обычно не требуется ничего настраивать, [или только IP-адрес |application:bootstrap#development-vs-production-mode].
+
+При отладке маршрутизатора рекомендуется отключить кэш браузера, в котором, например, могут храниться редиректы: откройте Developer Tools (Ctrl+Shift+I или Cmd+Option+I) и в панели Network установите флажок на отключение кэша.
+
+
 Ошибка `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Эта ошибка возникает, если вы обновили PHP до версии 8.1, но используете Nette, который не совместим с ней. Поэтому решением является обновление Nette до более новой версии с помощью `composer update`. Nette поддерживает PHP 8.1 с версии 3.0. Если вы используете более старую версию (вы можете узнать это, посмотрев в `composer.json`), [обновите Nette |migrations:en] или оставайтесь с PHP 8.0.
@@ -67,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on
 
 Чтобы запустить приложение на хостинге, необходимо в конфигурации хостинга установить document-root в эту директорию. Или, если на хостинге есть готовая папка для публичного каталога с другим именем (например, `web`, `public_html` и т.д.), просто переименуйте `www/`.
 
-Решение **не** состоит в том, чтобы "избавиться" от папки `www/` с помощью правил в файле `.htaccess` или в роутере. Если хостинг не позволяет вам установить document-root в подкаталог (т.е. создавать каталоги на один уровень выше публичного каталога), поищите другой. В противном случае вы существенно рискуете безопасностью. Это похоже на жизнь в квартире, где вы не можете закрыть входную дверь, и она всегда открыта.
+Решение **не** заключается в том, чтобы запретить доступ ко всем папкам, кроме `www/`, с помощью правил в файле `.htaccess` или в маршрутизаторе. Если ваш хостинг не позволяет устанавливать корень документа в подкаталог (т. е. создавать каталоги на уровень выше публичного каталога), вам следует поискать другой хостинг. В противном случае вы подвергаете себя значительным рискам безопасности. Это все равно что жить в квартире, где входная дверь не закрывается и всегда нараспашку.
 
 
 Как настроить сервер для красивых URL? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/sl/@home.texy b/nette/sl/@home.texy
index bafe6b5d10..170bbd9789 100644
--- a/nette/sl/@home.texy
+++ b/nette/sl/@home.texy
@@ -84,11 +84,11 @@ Storitve
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Hashing gesel |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Tipi PHP |utils:type]
 - [Nizi |utils:Strings]
 - [Validatorji |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...drugi |utils:]
 </div>
diff --git a/nette/sl/installation.texy b/nette/sl/installation.texy
index b7d5e84ccc..66c1d70baa 100644
--- a/nette/sl/installation.texy
+++ b/nette/sl/installation.texy
@@ -20,7 +20,7 @@ Nette ponuja zbirko uporabnih in izpopolnjenih paketov (knjižnic) za PHP. Če j
 composer require nette/utils
 ```
 
-Ali imate raje grafični vmesnik? Oglejte si [vodnik za |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] nameščanje paketov v okolje PhpStrom.
+Ali imate raje grafični vmesnik? Oglejte si [vodnik za |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] nameščanje paketov v okolje PhpStorm.
 
 
 Kako začeti nov projekt z Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/sl/introduction-to-object-oriented-programming.texy b/nette/sl/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..0e9f227fa2
--- /dev/null
+++ b/nette/sl/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Uvod v objektno usmerjeno programiranje
+***************************************
+
+.[perex]
+Izraz "OOP" pomeni objektno usmerjeno programiranje, ki je način organiziranja in strukturiranja kode. OOP nam omogoča, da na program gledamo kot na zbirko predmetov, ki med seboj komunicirajo, in ne kot na zaporedje ukazov in funkcij.
+
+V OOP je "objekt" enota, ki vsebuje podatke in funkcije, ki delujejo na teh podatkih. Objekti so ustvarjeni na podlagi "razredov", ki jih lahko razumemo kot načrte ali predloge za objekte. Ko imamo razred, lahko ustvarimo njegov "primerek", ki je poseben objekt, narejen iz tega razreda.
+
+Oglejmo si, kako lahko ustvarimo preprost razred v PHP. Pri definiranju razreda uporabimo ključno besedo "class", ki ji sledi ime razreda, nato pa še oglati oklepaji, ki zapirajo funkcije razreda (imenovane "metode") in spremenljivke razreda (imenovane "lastnosti" ali "atributi"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+V tem primeru smo ustvarili razred z imenom `Car` z eno funkcijo (ali "metodo") z imenom `honk`.
+
+Vsak razred mora rešiti le eno glavno nalogo. Če razred opravlja preveč stvari, ga je morda primerno razdeliti na manjše, specializirane razrede.
+
+Razredi so običajno shranjeni v ločenih datotekah, da bi bila koda urejena in bi bilo po njej lažje krmariti. Ime datoteke se mora ujemati z imenom razreda, tako da bi bilo ime datoteke za razred `Car` `Car.php` .
+
+Pri poimenovanju razredov je dobro upoštevati konvencijo "PascalCase", kar pomeni, da se vsaka beseda v imenu začne z veliko črko in ni podčrtank ali drugih ločil. Za metode in lastnosti velja konvencija "camelCase", kar pomeni, da se začnejo z malo črko.
+
+Nekatere metode v PHP imajo posebne vloge in imajo predpono `__` (dva podčrtaja). Ena najpomembnejših posebnih metod je "konstruktor", ki je označen kot `__construct`. Konstruktor je metoda, ki se samodejno pokliče pri ustvarjanju novega primerka razreda.
+
+Konstruktor pogosto uporabljamo za določanje začetnega stanja predmeta. Na primer, ko ustvarjate objekt, ki predstavlja osebo, lahko konstruktor uporabite za nastavitev njene starosti, imena ali drugih atributov.
+
+Oglejmo si, kako uporabiti konstruktor v PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+V tem primeru ima razred `Person` lastnost (spremenljivko) `$age` in konstruktor, ki to lastnost nastavi. Metoda `howOldAreYou()` nato omogoča dostop do starosti osebe.
+
+Psevdopremenljivka `$this` se uporablja znotraj razreda za dostop do lastnosti in metod objekta.
+
+Ključna beseda `new` se uporablja za ustvarjanje novega primerka razreda. V zgornjem primeru smo ustvarili novo osebo, staro 25 let.
+
+Nastavite lahko tudi privzete vrednosti za parametre konstruktorja, če niso določeni pri ustvarjanju predmeta. Na primer:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Če pri ustvarjanju predmeta `Person` ne določite starosti, bo uporabljena privzeta vrednost 20.
+
+Lepo je, da lahko definicijo lastnosti z njeno inicializacijo prek konstruktorja skrajšamo in poenostavimo na naslednji način:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Za popolnost dodajmo, da imajo lahko objekti poleg konstruktorjev tudi destruktorje (metoda `__destruct`), ki se kličejo, preden se objekt sprosti iz pomnilnika.
+
+
+Prostori imen .[#toc-namespaces]
+--------------------------------
+
+Prostori imen nam omogočajo organiziranje in združevanje sorodnih razredov, funkcij in konstant, pri čemer se izognemo konfliktom pri poimenovanju. Predstavljamo si jih lahko kot mape v računalniku, kjer vsaka mapa vsebuje datoteke, povezane z določenim projektom ali temo.
+
+Prostori imen so še posebej uporabni v večjih projektih ali pri uporabi knjižnic tretjih oseb, kjer lahko pride do sporov v poimenovanju razredov.
+
+Predstavljajte si, da imate v svojem projektu razred z imenom `Car` in ga želite postaviti v imenski prostor z imenom `Transport`. To bi storili takole:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Če želite razred `Car` uporabiti v drugi datoteki, morate navesti, iz katerega imenskega prostora razred izhaja:
+
+```php
+$car = new Transport\Car;
+```
+
+Za poenostavitev lahko na začetku datoteke navedete, kateri razred iz določenega imenskega prostora želite uporabiti, kar vam omogoča ustvarjanje primerkov brez navajanja celotne poti:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Dedovanje .[#toc-inheritance]
+-----------------------------
+
+Dedovanje je orodje objektno usmerjenega programiranja, ki omogoča ustvarjanje novih razredov na podlagi obstoječih, dedovanje njihovih lastnosti in metod ter njihovo razširitev ali redefiniranje po potrebi. Dedovanje zagotavlja ponovno uporabnost kode in hierarhijo razredov.
+
+Preprosto povedano, če imamo en razred in želimo ustvariti drugega, ki izhaja iz njega, vendar z nekaterimi spremembami, lahko novi razred "podedujemo" od prvotnega.
+
+V jeziku PHP se dedovanje izvaja s ključno besedo `extends`.
+
+Naš razred `Person` shranjuje informacije o starosti. Imamo lahko še en razred, `Student`, ki razširja `Person` in dodaja informacije o področju študija.
+
+Oglejmo si primer:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Kako deluje ta koda?
+
+- S ključno besedo `extends` smo razširili razred `Person`, kar pomeni, da razred `Student` podeduje vse metode in lastnosti od razreda `Person`.
+
+- Ključna beseda `parent::` nam omogoča klicanje metod iz nadrejenega razreda. V tem primeru smo poklicali konstruktor iz razreda `Person`, preden smo v razred `Student` dodali svojo funkcionalnost. In podobno tudi metodo razreda `printInformation()` prednika, preden smo izpisali podatke o učencu.
+
+Dedovanje je namenjeno situacijam, v katerih med razredi obstaja razmerje "is a". Na primer, razred `Student` je razred `Person`. Mačka je žival. Omogoča nam, da v primerih, ko v kodi pričakujemo en objekt (npr. "Oseba"), namesto njega uporabimo izpeljani objekt (npr. "Študent").
+
+Bistveno se je zavedati, da glavni namen dedovanja **ni** preprečevanje podvajanja kode. Ravno nasprotno, napačna uporaba dedovanja lahko privede do zapletene in težko vzdrževane kode. Če med razredi ni razmerja "je a", moramo namesto dedovanja razmisliti o kompoziciji.
+
+Upoštevajte, da metode `printInformation()` v razredih `Person` in `Student` prikazujejo nekoliko drugačne informacije. Dodamo lahko tudi druge razrede (na primer `Employee`), ki bodo zagotovili druge izvedbe te metode. Sposobnost objektov različnih razredov, da se na isto metodo odzivajo na različne načine, se imenuje polimorfizem:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Sestavljanje .[#toc-composition]
+--------------------------------
+
+Kompozicija je tehnika, pri kateri namesto dedovanja lastnosti in metod iz drugega razreda preprosto uporabimo njegov primerek v svojem razredu. Tako lahko združimo funkcionalnosti in lastnosti več razredov, ne da bi ustvarjali zapletene strukture dedovanja.
+
+Na primer, imamo razred `Engine` in razred `Car`. Namesto da bi rekli "Avto je motor", rečemo "Avto ima motor", kar je tipično kompozicijsko razmerje.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+V tem primeru razred `Car` nima vseh lastnosti in metod razreda `Engine`, vendar ima do njih dostop prek lastnosti razreda `$engine`.
+
+Prednost sestave je večja prilagodljivost načrtovanja in boljša prilagodljivost za prihodnje spremembe.
+
+
+Vidnost .[#toc-visibility]
+--------------------------
+
+V jeziku PHP lahko za lastnosti, metode in konstante razreda določite vidnost. Vidnost določa, kje lahko dostopate do teh elementov.
+
+1. **Public:** Če je element označen kot `public`, to pomeni, da lahko do njega dostopate od koder koli, tudi zunaj razreda.
+
+2. **Zaščiten:** Element, označen kot `protected`, je dostopen le znotraj razreda in vseh njegovih potomcev (razredov, ki dedujejo od njega).
+
+3. **Zasebno:** Če je element označen kot `private`, lahko do njega dostopate le znotraj razreda, v katerem je bil opredeljen.
+
+Če ne določite vidnosti, PHP samodejno nastavi vidnost na `public`.
+
+Oglejmo si vzorec kode:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Nadaljujemo z dedovanjem razredov:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+V tem primeru lahko metoda `printProperties()` v razredu `ChildClass` dostopa do javnih in zaščitenih lastnosti, ne more pa dostopati do zasebnih lastnosti nadrejenega razreda.
+
+Podatki in metode morajo biti čim bolj skriti in dostopni le prek določenega vmesnika. Tako lahko spremenite notranjo implementacijo razreda, ne da bi to vplivalo na preostalo kodo.
+
+
+Končna ključna beseda .[#toc-final-keyword]
+-------------------------------------------
+
+V jeziku PHP lahko ključno besedo `final` uporabimo, če želimo preprečiti, da bi razred, metodo ali konstanto podedovali ali prepisali. Če je razred označen kot `final`, ga ni mogoče razširiti. Če je metoda označena kot `final`, je ni mogoče prepisati v podrazredu.
+
+Če se zavedamo, da določenega razreda ali metode ne bomo več spreminjali, lahko lažje izvajamo spremembe, ne da bi nas skrbelo za morebitne konflikte. Tako lahko na primer dodamo novo metodo, ne da bi se bali, da ima potomec že metodo z istim imenom, kar bi povzročilo kolizijo. Ali pa lahko spremenimo parametre metode, spet brez tveganja, da bi povzročili neskladje s prepisano metodo v potomcu.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+V tem primeru bo poskus dedovanja iz končnega razreda `FinalClass` povzročil napako.
+
+
+Statične lastnosti in metode .[#toc-static-properties-and-methods]
+------------------------------------------------------------------
+
+Ko v jeziku PHP govorimo o "statičnih" elementih razreda, imamo v mislih metode in lastnosti, ki pripadajo samemu razredu in ne določenemu primerku razreda. To pomeni, da vam za dostop do njih ni treba ustvariti primerka razreda. Namesto tega jih pokličete ali do njih dostopate neposredno prek imena razreda.
+
+Upoštevajte, da ker statični elementi pripadajo razredu in ne njegovim instancam, znotraj statičnih metod ne morete uporabljati psevdo-premenljivke `$this`.
+
+Uporaba statičnih lastnosti vodi v [obskurno kodo, polno pasti |dependency-injection:global-state], zato jih nikoli ne smete uporabljati in tu ne bomo prikazali primera. Po drugi strani pa so statične metode uporabne. Tukaj je primer:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+V tem primeru smo ustvarili razred `Calculator` z dvema statičnima metodama. Ti metodi lahko pokličemo neposredno, ne da bi ustvarili primerek razreda z uporabo operatorja `::`. Statične metode so še posebej uporabne za operacije, ki niso odvisne od stanja določenega primerka razreda.
+
+
+Konstante razreda .[#toc-class-constants]
+-----------------------------------------
+
+Znotraj razredov lahko določimo konstante. Konstante so vrednosti, ki se med izvajanjem programa nikoli ne spremenijo. V nasprotju s spremenljivkami ostane vrednost konstante enaka.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+V tem primeru imamo razred `Car` s konstanto `NumberOfWheels`. Pri dostopu do konstante znotraj razreda lahko namesto imena razreda uporabimo ključno besedo `self`.
+
+
+Objektni vmesniki .[#toc-object-interfaces]
+-------------------------------------------
+
+Objektni vmesniki delujejo kot "pogodbe" za razrede. Če naj razred implementira objektni vmesnik, mora vsebovati vse metode, ki jih vmesnik opredeljuje. To je odličen način za zagotavljanje, da se določeni razredi držijo iste "pogodbe" ali strukture.
+
+V PHP so vmesniki opredeljeni s ključno besedo `interface`. Vse metode, opredeljene v vmesniku, so javne (`public`). Ko razred implementira vmesnik, uporabi ključno besedo `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Če razred implementira vmesnik, vendar niso definirane vse pričakovane metode, PHP vrže napako.
+
+Razred lahko implementira več vmesnikov hkrati, kar se razlikuje od dedovanja, pri katerem lahko razred deduje samo od enega razreda:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Abstraktni razredi .[#toc-abstract-classes]
+-------------------------------------------
+
+Abstraktni razredi služijo kot osnovne predloge za druge razrede, vendar njihovih primerkov ne morete ustvariti neposredno. Vsebujejo mešanico popolnih metod in abstraktnih metod, ki nimajo določene vsebine. Razredi, ki dedujejo od abstraktnih razredov, morajo zagotoviti definicije za vse abstraktne metode iz starševskega razreda.
+
+Za opredelitev abstraktnega razreda uporabimo ključno besedo `abstract`.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+V tem primeru imamo abstraktni razred z eno redno in eno abstraktno metodo. Nato imamo razred `Child`, ki podeduje od `AbstractClass` in zagotavlja implementacijo abstraktne metode.
+
+V čem se vmesniki in abstraktni razredi razlikujejo? Abstraktni razredi lahko vsebujejo tako abstraktne kot konkretne metode, medtem ko vmesniki le določajo, katere metode mora razred implementirati, ne zagotavljajo pa implementacije. Razred lahko podeduje le en abstraktni razred, implementira pa lahko poljubno število vmesnikov.
+
+
+Preverjanje tipa .[#toc-type-checking]
+--------------------------------------
+
+Pri programiranju je ključnega pomena, da zagotovimo, da so podatki, s katerimi delamo, pravilnega tipa. V jeziku PHP imamo na voljo orodja, ki to zagotavljajo. Preverjanje, ali so podatki pravilnega tipa, se imenuje "preverjanje tipa".
+
+Tipi, ki jih lahko srečamo v PHP:
+
+1. **Osnovne vrste**: To so `int` (cela števila), `float` (števila s plavajočo vejico), `bool` (logične vrednosti), `string` (nizi), `array` (polja) in `null`.
+2. **Tredi**: Kadar želimo, da je vrednost primerek določenega razreda.
+3. **Vmesniki**: Opredeljuje nabor metod, ki jih mora razred implementirati. Vrednost, ki ustreza vmesniku, mora imeti te metode.
+4. **Mešani tipi**: Določimo lahko, da ima lahko spremenljivka več dovoljenih tipov.
+5. **Void**: Ta posebni tip označuje, da funkcija ali metoda ne vrača nobene vrednosti.
+
+Oglejmo si, kako spremeniti kodo, da bo vključevala tipe:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Na ta način zagotovimo, da naša koda pričakuje in dela s podatki pravilne vrste, kar nam pomaga preprečiti morebitne napake.
+
+Nekaterih vrst ni mogoče neposredno zapisati v PHP. V tem primeru so navedeni v komentarju phpDoc, ki je standardna oblika za dokumentiranje kode PHP in se začne s `/**` in konča s `*/`. Omogoča dodajanje opisov razredov, metod itd. Prav tako pa tudi za navajanje kompleksnih tipov s tako imenovanimi opombami `@var`, `@param` in `@return`. Te vrste nato uporabljajo orodja za statično analizo kode, vendar jih PHP sam ne preverja.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Primerjava in identiteta .[#toc-comparison-and-identity]
+--------------------------------------------------------
+
+V PHP lahko predmete primerjate na dva načina:
+
+1. Primerjava vrednosti `==`: Preveri, ali sta objekta istega razreda in imata v svojih lastnostih enake vrednosti.
+2. Primerjava identitete `===`: Preveri, ali gre za isti primerek objekta.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Upravljavec spletne strani `instanceof` .[#toc-the-instanceof-operator]
+-----------------------------------------------------------------------
+
+Operator `instanceof` omogoča ugotavljanje, ali je dani predmet primerek določenega razreda, potomec tega razreda ali pa implementira določen vmesnik.
+
+Predstavljajte si, da imamo razred `Person` in še en razred `Student`, ki je potomec razreda `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Iz izpisov je razvidno, da objekt `$student` velja za primerek obeh razredov `Student` in `Person`.
+
+
+Fluentni vmesniki .[#toc-fluent-interfaces]
+-------------------------------------------
+
+"Fluentni vmesnik" je tehnika v OOP, ki omogoča veriženje metod v enem samem klicu. To pogosto poenostavi in razjasni kodo.
+
+Ključni element tekočega vmesnika je, da vsaka metoda v verigi vrne referenco na trenutni objekt. To dosežemo z uporabo `return $this;` na koncu metode. Ta slog programiranja je pogosto povezan z metodami, imenovanimi "nastavljalci", ki nastavljajo vrednosti lastnosti objekta.
+
+Oglejmo si, kako bi lahko bil videti tekoči vmesnik za pošiljanje e-pošte:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+V tem primeru so metode `setFrom()`, `setRecipient()` in `setMessage()` uporabljene za nastavitev ustreznih vrednosti (pošiljatelj, prejemnik, vsebina sporočila). Po nastavitvi vsake od teh vrednosti metode vrnejo trenutni objekt (`$email`), kar nam omogoča, da za njo verižno priključimo drugo metodo. Na koncu pokličemo metodo `send()`, ki dejansko pošlje elektronsko sporočilo.
+
+Zahvaljujoč tekočim vmesnikom lahko pišemo kodo, ki je intuitivna in lahko berljiva.
+
+
+Kopiranje s `clone` .[#toc-copying-with-clone]
+----------------------------------------------
+
+V jeziku PHP lahko ustvarimo kopijo predmeta z uporabo operatorja `clone`. Tako dobimo nov primerek z enako vsebino.
+
+Če moramo pri kopiranju objekta spremeniti nekatere njegove lastnosti, lahko v razredu definiramo posebno metodo `__clone()`. Ta metoda se samodejno pokliče, ko je objekt kloniran.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+V tem primeru imamo razred `Sheep` z eno lastnostjo `$name`. Ko kloniramo primerek tega razreda, metoda `__clone()` poskrbi, da ime klonirane ovce dobi predpono "Clone of".
+
+
+Lastnosti .[#toc-traits]
+------------------------
+
+Značilnosti v PHP so orodje, ki omogoča souporabo metod, lastnosti in konstant med razredi ter preprečuje podvajanje kode. Lahko si jih predstavljate kot mehanizem "kopiraj in prilepi" (Ctrl-C in Ctrl-V), pri katerem se vsebina lastnosti "prilepi" v razrede. To vam omogoča ponovno uporabo kode, ne da bi morali ustvarjati zapletene hierarhije razredov.
+
+Oglejmo si preprost primer uporabe lastnosti v jeziku PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+V tem primeru imamo lastnost z imenom `Honking`, ki vsebuje eno metodo `honk()`. Nato imamo dva razreda: `Car` in `Truck`, ki oba uporabljata lastnost `Honking`. Posledično oba razreda "imata" metodo `honk()` in jo lahko kličemo na predmetih obeh razredov.
+
+Značilnosti omogočajo enostavno in učinkovito izmenjavo kode med razredi. Ne vstopajo v hierarhijo dedovanja, tj. `$car instanceof Honking` bo vrnil `false`.
+
+
+Izjeme
+------
+
+Izjeme v OOP nam omogočajo elegantno obravnavanje napak in nepričakovanih situacij v naši kodi. So predmeti, ki nosijo informacije o napaki ali nenavadni situaciji.
+
+V jeziku PHP imamo vgrajen razred `Exception`, ki služi kot osnova za vse izjeme. Ta ima več metod, s katerimi lahko pridobimo več informacij o izjemi, kot so sporočilo o napaki, datoteka in vrstica, v kateri se je napaka pojavila, itd.
+
+Ko se v kodi pojavi napaka, lahko izjemo "vržemo" z uporabo ključne besede `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Ko funkcija `division()` kot drugi argument prejme ničlo, vrže izjemo s sporočilom o napaki `'Division by zero!'`. Da bi preprečili sesutje programa, ko se vrže izjema, jo ujamemo v blok `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Koda, ki lahko vrže izjemo, je zavita v blok `try`. Če je izjema vržena, se izvajanje kode premakne v blok `catch`, kjer lahko obravnavamo izjemo (npr. napišemo sporočilo o napaki).
+
+Za blokoma `try` in `catch` lahko dodamo neobvezni blok `finally`, ki se vedno izvede ne glede na to, ali je bila izjema vržena ali ne (tudi če v bloku `try` ali `catch` uporabimo `return`, `break` ali `continue` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Ustvarimo lahko tudi lastne razrede izjem (hierarhijo), ki dedujejo po razredu Exception. Kot primer si oglejmo preprosto bančno aplikacijo, ki omogoča vplačila in izplačila:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Če pričakujete različne vrste izjem, lahko za en sam blok `try` določite več blokov `catch`.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+V tem primeru je pomembno upoštevati vrstni red blokov `catch`. Ker vse izjeme dedujejo od `BankingException`, bi se, če bi imeli ta blok prvi, vse izjeme ujele v njem, ne da bi koda dosegla naslednje bloke `catch`. Zato je pomembno, da so bolj specifične izjeme (tj. tiste, ki dedujejo od drugih) višje v vrstnem redu blokov `catch` kot njihove nadrejene izjeme.
+
+
+Iteracije .[#toc-iterations]
+----------------------------
+
+V jeziku PHP lahko z zanko `foreach` krožite po predmetih, podobno kot krožite po polju. Da bi to delovalo, mora objekt implementirati poseben vmesnik.
+
+Prva možnost je implementacija vmesnika `Iterator`, ki ima metode `current()`, ki vrača trenutno vrednost, `key()`, ki vrača ključ, `next()`, ki se premakne na naslednjo vrednost, `rewind()`, ki se premakne na začetek, in `valid()`, ki preveri, ali smo že na koncu.
+
+Druga možnost je, da implementiramo vmesnik `IteratorAggregate`, ki ima samo eno metodo `getIterator()`. Ta bodisi vrne nadomestni objekt, ki bo zagotovil prehod, bodisi je lahko generator, ki je posebna funkcija, ki uporablja `yield` za zaporedno vračanje ključev in vrednosti:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Najboljše prakse .[#toc-best-practices]
+---------------------------------------
+
+Ko obvladate osnovna načela objektno usmerjenega programiranja, se je treba osredotočiti na najboljše prakse v OOP. Te vam bodo pomagale pri pisanju kode, ki ni le funkcionalna, temveč tudi berljiva, razumljiva in jo je mogoče zlahka vzdrževati.
+
+1) **Oddelitev interesov**: Vsak razred mora imeti jasno opredeljeno odgovornost in mora obravnavati le eno primarno nalogo. Če razred počne preveč stvari, je morda primerno, da ga razdelite na manjše, specializirane razrede.
+2) **Enkapsulacija**: Podatki in metode morajo biti čim bolj skriti in dostopni le prek opredeljenega vmesnika. To omogoča spreminjanje notranje implementacije razreda, ne da bi to vplivalo na preostalo kodo.
+3) **Vključevanje odvisnosti**: Namesto da bi odvisnosti ustvarjali neposredno v razredu, bi jih morali "vbrizgati" od zunaj. Za globlje razumevanje tega načela priporočamo [poglavja o vbrizgavanju odvisnosti |dependency-injection:introduction].
diff --git a/nette/sl/troubleshooting.texy b/nette/sl/troubleshooting.texy
index 846f03b532..7cf04d42bf 100644
--- a/nette/sl/troubleshooting.texy
+++ b/nette/sl/troubleshooting.texy
@@ -18,7 +18,7 @@ Razlog za napako lahko vedno najdete v imeniku `log/`. Če pa je v sporočilu o
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // vaš naslov IP.
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Napaka 404, usmerjanje ne deluje .[#toc-error-404-routing-not-working]
 Če vse strani (razen domače strani) vrnejo napako 404, je videti, da gre za težavo s konfiguracijo strežnika za [lepe naslove URL |#How to Configure a Server for Nice URLs?].
 
 
+Kako onemogočiti predpomnilnik med razvojem? .[#toc-how-to-disable-cache-during-development]
+--------------------------------------------------------------------------------------------
+Nette je pameten in v njem vam ni treba onemogočiti predpomnjenja. Med razvojem samodejno posodablja predpomnilnik, kadar koli se spremeni predlogo ali konfiguracija vsebnika DI. Poleg tega se razvojni način aktivira s samodejnim zaznavanjem, zato običajno ni treba nastavljati ničesar [ali le naslova IP |application:bootstrap#development-vs-production-mode].
+
+Pri odpravljanju napak v usmerjevalniku priporočamo, da onemogočite predpomnilnik brskalnika, v katerem so na primer lahko shranjene preusmeritve: odprite Razvojna orodja (Ctrl+Shift+I ali Cmd+Option+I) in na plošči Omrežje označite polje za onemogočanje predpomnilnika.
+
+
 Napaka `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 ----------------------------------------------------------------------------------------------------------------------
 Ta napaka se pojavi, če ste PHP nadgradili na različico 8.1, vendar uporabljate Nette, ki z njo ni združljiv. Rešitev je, da Nette posodobite na novejšo različico z uporabo `composer update`. Nette podpira PHP 8.1 od različice 3.0. Če uporabljate starejšo različico (to lahko ugotovite z vpogledom v `composer.json`), [nadgradite Nette |migrations:en] ali pa ostanite pri PHP 8.0.
@@ -67,7 +74,7 @@ Imenik `www/`, ki se uporablja v vzorčnih projektih v Nette, je tako imenovani
 
 Če želite zagnati aplikacijo na gostovanju, morate v konfiguraciji gostovanja nastaviti document-root na ta imenik. Če pa ima gostovanje vnaprej pripravljeno mapo za javni imenik z drugačnim imenom (na primer `web`, `public_html` itd.), preprosto preimenujte `www/`.
 
-Rešitev **ni**, da bi se mape `www/` "znebili" z uporabo pravil v datoteki `.htaccess` ali v usmerjevalniku. Če gostovanje ne bi dovolilo nastavitve document-root na podimenik (tj. ustvarjanje imenikov eno raven nad javnim imenikom), poiščite drugega. V nasprotnem primeru bi se izpostavili precejšnjemu varnostnemu tveganju. To bi bilo tako, kot če bi živeli v stanovanju, v katerem ne morete zapreti vhodnih vrat in so ta vedno na široko odprta.
+Rešitev ni** preprečevanje dostopa do vseh map razen `www/` s pravili v datoteki `.htaccess` ali v usmerjevalniku. Če vaše gostovanje ne dovoljuje nastavitve korena dokumenta v podimenik (tj. ustvarjanja imenikov eno raven nad javnim imenikom), morate poiskati drugo storitev gostovanja. V nasprotnem primeru bi se izpostavili velikim varnostnim tveganjem. To bi bilo tako, kot če bi živeli v stanovanju, kjer vhodnih vrat ni mogoče zapreti in so vedno na široko odprta.
 
 
 Kako konfigurirati strežnik za lepe naslove URL? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/tr/@home.texy b/nette/tr/@home.texy
index 095f3e9aff..cb5c58765f 100644
--- a/nette/tr/@home.texy
+++ b/nette/tr/@home.texy
@@ -84,11 +84,11 @@ Yardımcı Programlar
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Parola Hashing |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [PHP Türleri |utils:type]
 - [Dizeler |utils:Strings]
 - [Doğrulayıcılar |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...diğerleri |utils:]
 </div>
diff --git a/nette/tr/installation.texy b/nette/tr/installation.texy
index 9acc4f5ba5..7f82f49a85 100644
--- a/nette/tr/installation.texy
+++ b/nette/tr/installation.texy
@@ -20,7 +20,7 @@ Nette, PHP için kullanışlı ve sofistike paketlerden (kütüphaneler) oluşan
 composer require nette/utils
 ```
 
-Grafik arayüzü mü tercih ediyorsunuz? PhpStrom ortamında paket yükleme [kılavuzuna |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] göz atın.
+Grafik arayüzü mü tercih ediyorsunuz? PhpStorm ortamında paket yükleme [kılavuzuna |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] göz atın.
 
 
 Nette ile Yeni Bir Projeye Nasıl Başlanır .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/tr/introduction-to-object-oriented-programming.texy b/nette/tr/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..3ce739c184
--- /dev/null
+++ b/nette/tr/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Nesne Yönelimli Programlamaya Giriş
+***********************************
+
+.[perex]
+"OOP" terimi, kodu organize etmenin ve yapılandırmanın bir yolu olan Nesne Yönelimli Programlama anlamına gelir. OOP, bir programı bir dizi komut ve işlev yerine birbirleriyle iletişim kuran nesneler topluluğu olarak görmemizi sağlar.
+
+OOP'de "nesne", veri ve bu veri üzerinde çalışan fonksiyonları içeren bir birimdir. Nesneler, nesneler için planlar veya şablonlar olarak anlaşılabilecek "sınıflar" temelinde oluşturulur. Bir sınıfa sahip olduğumuzda, o sınıftan yapılmış belirli bir nesne olan "örneğini" oluşturabiliriz.
+
+PHP'de basit bir sınıfı nasıl oluşturabileceğimize bakalım. Bir sınıfı tanımlarken, "class" anahtar sözcüğünü, ardından sınıf adını ve ardından sınıfın işlevlerini ("yöntemler" olarak adlandırılır) ve sınıf değişkenlerini ("özellikler" veya "nitelikler" olarak adlandırılır) çevreleyen küme parantezlerini kullanırız:
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Bu örnekte, `honk` adında bir işlevi (veya "yöntemi") olan `Car` adında bir sınıf oluşturduk.
+
+Her sınıf sadece bir ana görevi çözmelidir. Bir sınıf çok fazla şey yapıyorsa, onu daha küçük, uzmanlaşmış sınıflara bölmek uygun olabilir.
+
+Sınıflar, kodu düzenli tutmak ve gezinmeyi kolaylaştırmak için genellikle ayrı dosyalarda saklanır. Dosya adı sınıf adıyla eşleşmelidir, bu nedenle `Car` sınıfı için dosya adı `Car.php` olacaktır.
+
+Sınıfları adlandırırken, "PascalCase" kuralını takip etmek iyidir, yani isimdeki her kelime büyük harfle başlar ve alt çizgi veya başka ayırıcılar yoktur. Yöntemler ve özellikler "camelCase" kuralını takip eder, yani küçük harfle başlarlar.
+
+PHP'de bazı yöntemlerin özel rolleri vardır ve ön ekleri `__` (iki alt çizgi) ile gösterilir. En önemli özel yöntemlerden biri `__construct` olarak etiketlenen "kurucu "dur. Yapıcı, bir sınıfın yeni bir örneğini oluştururken otomatik olarak çağrılan bir yöntemdir.
+
+Yapıcıyı genellikle bir nesnenin başlangıç durumunu ayarlamak için kullanırız. Örneğin, bir kişiyi temsil eden bir nesne oluştururken, yaşı, adı veya diğer nitelikleri ayarlamak için kurucuyu kullanabilirsiniz.
+
+PHP'de bir yapıcının nasıl kullanılacağını görelim:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+Bu örnekte, `Person` sınıfının bir özelliği (değişkeni) `$age` ve bu özelliği ayarlayan bir kurucusu vardır. Daha sonra `howOldAreYou()` yöntemi kişinin yaşına erişim sağlar.
+
+ `$this` sözde değişkeni, nesnenin özelliklerine ve yöntemlerine erişmek için sınıf içinde kullanılır.
+
+ `new` anahtar sözcüğü bir sınıfın yeni bir örneğini oluşturmak için kullanılır. Yukarıdaki örnekte, 25 yaşında yeni bir kişi oluşturduk.
+
+Bir nesne oluştururken belirtilmemişlerse, kurucu parametreleri için varsayılan değerler de ayarlayabilirsiniz. Örneğin:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+Bu örnekte, bir `Person` nesnesi oluştururken bir yaş belirtmezseniz, varsayılan değer olan 20 kullanılacaktır.
+
+Güzel olan şey, yapıcı aracılığıyla başlatılmasıyla birlikte özellik tanımının bu şekilde kısaltılabilmesi ve basitleştirilebilmesidir:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Bütünlük için, kuruculara ek olarak, nesneler bellekten serbest bırakılmadan önce çağrılan yıkıcılara (yöntem `__destruct`) sahip olabilir.
+
+
+İsim Alanları .[#toc-namespaces]
+--------------------------------
+
+Ad alanları, adlandırma çakışmalarını önlerken ilgili sınıfları, işlevleri ve sabitleri düzenlememize ve gruplandırmamıza olanak tanır. Bunları, her klasörün belirli bir proje veya konuyla ilgili dosyaları içerdiği bir bilgisayardaki klasörler gibi düşünebilirsiniz.
+
+Ad alanları özellikle büyük projelerde veya sınıf adlandırma çakışmalarının ortaya çıkabileceği üçüncü taraf kütüphaneleri kullanırken kullanışlıdır.
+
+Projenizde `Car` adında bir sınıfınız olduğunu ve bunu `Transport` adında bir ad alanına yerleştirmek istediğinizi düşünün. Bunu şu şekilde yaparsınız:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+ `Car` sınıfını başka bir dosyada kullanmak istiyorsanız, sınıfın hangi ad alanından geldiğini belirtmeniz gerekir:
+
+```php
+$car = new Transport\Car;
+```
+
+Basitleştirmek için, dosyanın başında belirli bir ad alanından hangi sınıfı kullanmak istediğinizi belirtebilir, böylece tam yolu belirtmeden örnekler oluşturabilirsiniz:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Kalıtım .[#toc-inheritance]
+---------------------------
+
+Kalıtım, mevcut sınıflara dayalı olarak yeni sınıfların oluşturulmasına, özelliklerinin ve yöntemlerinin miras alınmasına ve gerektiğinde genişletilmesine veya yeniden tanımlanmasına olanak tanıyan bir nesne yönelimli programlama aracıdır. Kalıtım, kodun yeniden kullanılabilirliğini ve sınıf hiyerarşisini sağlar.
+
+Basitçe söylemek gerekirse, bir sınıfımız varsa ve ondan türetilmiş ancak bazı değişikliklerle başka bir sınıf oluşturmak istiyorsak, yeni sınıfı orijinal sınıftan "miras" alabiliriz.
+
+PHP'de kalıtım `extends` anahtar sözcüğü kullanılarak gerçekleştirilir.
+
+ `Person` sınıfımız yaş bilgisini saklar. `Person` 'i genişleten ve çalışma alanı hakkında bilgi ekleyen `Student` adlı başka bir sınıfımız olabilir.
+
+Bir örneğe bakalım:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Bu kod nasıl çalışıyor?
+
+- `Person` sınıfını genişletmek için `extends` anahtar sözcüğünü kullandık, yani `Student` sınıfı tüm yöntemleri ve özellikleri `Person` sınıfından devralır.
+
+- `parent::` anahtar sözcüğü, üst sınıftaki yöntemleri çağırmamızı sağlar. Bu durumda, `Student` sınıfına kendi işlevselliğimizi eklemeden önce `Person` sınıfından kurucuyu çağırdık. Ve benzer şekilde, öğrenci bilgilerini listelemeden önce `printInformation()` ata yöntemini çağırdık.
+
+Kalıtım, sınıflar arasında "is a" ilişkisinin olduğu durumlar içindir. Örneğin, bir `Student` bir `Person`. Bir kedi bir hayvandır. Kodda bir nesne (örn. "Kişi") beklediğimiz durumlarda bunun yerine türetilmiş bir nesne (örn. "Öğrenci") kullanmamızı sağlar.
+
+Kalıtımın birincil amacının **kod tekrarını önlemek** olmadığının farkına varmak çok önemlidir. Aksine, kalıtımın yanlış kullanımı karmaşık ve bakımı zor kodlara yol açabilir. Sınıflar arasında "is a" ilişkisi yoksa, kalıtım yerine bileşimi düşünmeliyiz.
+
+`Person` ve `Student` sınıflarındaki `printInformation()` yöntemlerinin biraz farklı bilgiler verdiğine dikkat edin. Ve bu yöntemin başka uygulamalarını sağlayacak başka sınıflar ( `Employee` gibi) ekleyebiliriz. Farklı sınıflardaki nesnelerin aynı yönteme farklı şekillerde yanıt verebilmesine çok biçimlilik denir:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Kompozisyon .[#toc-composition]
+-------------------------------
+
+Kompozisyon, başka bir sınıftan özellikleri ve yöntemleri miras almak yerine, sınıfımızda onun örneğini kullandığımız bir tekniktir. Bu, karmaşık kalıtım yapıları oluşturmadan birden fazla sınıfın işlevlerini ve özelliklerini birleştirmemizi sağlar.
+
+Örneğin, bir `Engine` sınıfımız ve bir `Car` sınıfımız var. "Bir araba bir motordur" demek yerine, tipik bir bileşim ilişkisi olan "Bir arabanın motoru vardır" deriz.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Burada, `Car`, `Engine`'un tüm özelliklerine ve yöntemlerine sahip değildir, ancak `$engine` özelliği aracılığıyla bunlara erişebilir.
+
+Kompozisyonun avantajı, daha fazla tasarım esnekliği ve gelecekteki değişiklikler için daha iyi uyarlanabilirliktir.
+
+
+Görünürlük .[#toc-visibility]
+-----------------------------
+
+PHP'de sınıf özellikleri, yöntemleri ve sabitleri için "görünürlük" tanımlayabilirsiniz. Görünürlük, bu öğelere nereden erişebileceğinizi belirler.
+
+1. **Public:** Eğer bir eleman `public` olarak işaretlenmişse, bu ona her yerden, hatta sınıf dışından bile erişebileceğiniz anlamına gelir.
+
+2. **Korumalı:** `protected` olarak işaretlenmiş bir öğeye yalnızca sınıf ve tüm torunları (ondan miras alan sınıflar) içinde erişilebilir.
+
+3. **Özel:** Bir eleman `private` ise, ona yalnızca tanımlandığı sınıf içinden erişebilirsiniz.
+
+Görünürlük belirtmezseniz, PHP bunu otomatik olarak `public` olarak ayarlayacaktır.
+
+Örnek bir koda bakalım:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Sınıf kalıtımına devam ediyoruz:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+Bu durumda, `ChildClass` adresindeki `printProperties()` yöntemi public ve protected özelliklere erişebilir ancak ana sınıfın private özelliklerine erişemez.
+
+Veri ve yöntemler mümkün olduğunca gizli olmalı ve sadece tanımlanmış bir arayüz üzerinden erişilebilir olmalıdır. Bu, kodun geri kalanını etkilemeden sınıfın dahili uygulamasını değiştirmenize olanak tanır.
+
+
+Son Anahtar Kelime .[#toc-final-keyword]
+----------------------------------------
+
+PHP'de, bir sınıfın, yöntemin veya sabitin miras alınmasını veya geçersiz kılınmasını önlemek istiyorsak `final` anahtar sözcüğünü kullanabiliriz. Bir sınıf `final` olarak işaretlendiğinde genişletilemez. Bir yöntem `final` olarak işaretlendiğinde, bir alt sınıfta geçersiz kılınamaz.
+
+Belirli bir sınıf veya yöntemin artık değiştirilmeyeceğinin farkında olmak, olası çakışmalar konusunda endişelenmeden daha kolay değişiklik yapmamızı sağlar. Örneğin, bir alt sınıfın zaten aynı isimde bir metoda sahip olmasından ve bunun bir çakışmaya yol açmasından korkmadan yeni bir metot ekleyebiliriz. Ya da bir yöntemin parametrelerini, yine alttaki bir yöntemde geçersiz kılınmış bir yöntemle tutarsızlığa neden olma riski olmadan değiştirebiliriz.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+Bu örnekte, `FinalClass` nihai sınıfından miras almaya çalışmak bir hatayla sonuçlanacaktır.
+
+
+Statik Özellikler ve Yöntemler .[#toc-static-properties-and-methods]
+--------------------------------------------------------------------
+
+PHP'de bir sınıfın "statik" öğelerinden bahsettiğimizde, sınıfın belirli bir örneğine değil, sınıfın kendisine ait olan yöntemleri ve özellikleri kastediyoruz. Bu, onlara erişmek için sınıfın bir örneğini oluşturmanız gerekmediği anlamına gelir. Bunun yerine, bunları doğrudan sınıf adı üzerinden çağırır veya bunlara erişirsiniz.
+
+Statik öğeler örneklere değil sınıfa ait olduğundan, statik yöntemlerin içinde `$this` sözde değişkenini kullanamayacağınızı unutmayın.
+
+Statik özelliklerin kullanılması [tuzaklarla dolu karmaşık kodlara |dependency-injection:global-state] yol açar, bu nedenle bunları asla kullanmamalısınız ve burada bir örnek göstermeyeceğiz. Öte yandan, statik yöntemler kullanışlıdır. İşte bir örnek:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+Bu örnekte, iki statik yöntemi olan bir `Calculator` sınıfı oluşturduk. Bu yöntemleri, `::` operatörünü kullanarak sınıfın bir örneğini oluşturmadan doğrudan çağırabiliriz. Statik yöntemler özellikle belirli bir sınıf örneğinin durumuna bağlı olmayan işlemler için kullanışlıdır.
+
+
+Sınıf Sabitleri .[#toc-class-constants]
+---------------------------------------
+
+Sınıflar içinde sabitler tanımlama seçeneğimiz vardır. Sabitler, programın yürütülmesi sırasında asla değişmeyen değerlerdir. Değişkenlerin aksine, bir sabitin değeri aynı kalır.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+Bu örnekte, `NumberOfWheels` sabitine sahip bir `Car` sınıfımız var. Sınıf içindeki sabite erişirken, sınıf adı yerine `self` anahtar sözcüğünü kullanabiliriz.
+
+
+Nesne Arayüzleri .[#toc-object-interfaces]
+------------------------------------------
+
+Nesne arayüzleri sınıflar için "sözleşme" görevi görür. Bir sınıf bir nesne arayüzünü uygulayacaksa, arayüzün tanımladığı tüm yöntemleri içermelidir. Bu, belirli sınıfların aynı "sözleşmeye" veya yapıya bağlı kalmasını sağlamanın harika bir yoludur.
+
+PHP'de arayüzler `interface` anahtar sözcüğü kullanılarak tanımlanır. Bir arayüzde tanımlanan tüm yöntemler public'tir (`public`). Bir sınıf bir arayüzü uyguladığında, `implements` anahtar sözcüğünü kullanır.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Eğer bir sınıf bir arayüzü uyguluyor, ancak beklenen tüm yöntemler tanımlanmamışsa, PHP bir hata verir.
+
+Bir sınıf aynı anda birden fazla arayüzü uygulayabilir; bu, bir sınıfın yalnızca bir sınıftan miras alabildiği kalıtımdan farklıdır:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Soyut Sınıflar .[#toc-abstract-classes]
+---------------------------------------
+
+Soyut sınıflar diğer sınıflar için temel şablon görevi görür, ancak örneklerini doğrudan oluşturamazsınız. Tam yöntemler ve tanımlanmış bir içeriği olmayan soyut yöntemlerin bir karışımını içerirler. Soyut sınıflardan miras alan sınıflar, üst sınıftaki tüm soyut yöntemler için tanımlar sağlamalıdır.
+
+Soyut bir sınıf tanımlamak için `abstract` anahtar sözcüğünü kullanırız.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+Bu örnekte, bir normal ve bir soyut yöntemi olan soyut bir sınıfımız var. Ardından, `AbstractClass` adresinden miras alan ve soyut yöntem için bir uygulama sağlayan bir `Child` sınıfımız var.
+
+Arayüzler ve soyut sınıflar nasıl farklıdır? Soyut sınıflar hem soyut hem de somut yöntemler içerebilirken, arayüzler yalnızca sınıfın hangi yöntemleri uygulaması gerektiğini tanımlar, ancak hiçbir uygulama sağlamaz. Bir sınıf yalnızca bir soyut sınıftan miras alabilir, ancak herhangi bir sayıda arayüzü uygulayabilir.
+
+
+Tip Kontrolü .[#toc-type-checking]
+----------------------------------
+
+Programlamada, birlikte çalıştığımız verilerin doğru türde olduğundan emin olmak çok önemlidir. PHP'de bu güvenceyi sağlayan araçlarımız vardır. Verilerin doğru türde olduğunu doğrulamaya "tür denetimi" denir.
+
+PHP'de karşılaşabileceğimiz türler:
+
+1. **Temel tipler**: Bunlar `int` (tam sayılar), `float` (kayan noktalı sayılar), `bool` (boolean değerler), `string` (dizeler), `array` (diziler) ve `null` içerir.
+2. **Sınıflar**: Bir değerin belirli bir sınıfın örneği olmasını istediğimizde.
+3. **Arayüzler**: Bir sınıfın uygulaması gereken bir dizi yöntemi tanımlar. Bir arayüzü karşılayan bir değer bu yöntemlere sahip olmalıdır.
+4. **Karışık tipler**: Bir değişkenin birden fazla izin verilen türe sahip olabileceğini belirtebiliriz.
+5. **Void**: Bu özel tip, bir fonksiyon veya metodun herhangi bir değer döndürmediğini belirtir.
+
+Türleri dahil etmek için kodu nasıl değiştireceğimizi görelim:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Bu şekilde, kodumuzun doğru türdeki verileri beklediğinden ve bunlarla çalıştığından emin olarak olası hataları önlememize yardımcı oluruz.
+
+Bazı türler PHP'de doğrudan yazılamaz. Bu durumda, PHP kodunu belgelemek için standart biçim olan phpDoc yorumunda listelenirler, `/**` ile başlar ve `*/` ile biter. Sınıfların, yöntemlerin vb. açıklamalarını eklemenize olanak tanır. Ayrıca `@var`, `@param` ve `@return` ek açıklamalarını kullanarak karmaşık türleri listelemenizi sağlar. Bu tipler daha sonra statik kod analiz araçları tarafından kullanılır, ancak PHP'nin kendisi tarafından kontrol edilmez.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Karşılaştırma ve Kimlik .[#toc-comparison-and-identity]
+-------------------------------------------------------
+
+PHP'de nesneleri iki şekilde karşılaştırabilirsiniz:
+
+1. Değer karşılaştırması `==`: Nesnelerin aynı sınıftan olup olmadığını ve özelliklerinde aynı değerlere sahip olup olmadığını kontrol eder.
+2. Kimlik `===`: Nesnenin aynı örneği olup olmadığını kontrol eder.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+`instanceof` Operatör .[#toc-the-instanceof-operator]
+-----------------------------------------------------
+
+ `instanceof` operatörü, belirli bir nesnenin belirli bir sınıfın örneği olup olmadığını, bu sınıfın soyundan gelip gelmediğini veya belirli bir arayüzü uygulayıp uygulamadığını belirlemenizi sağlar.
+
+Bir `Person` sınıfımız ve `Person` sınıfının soyundan gelen başka bir `Student` sınıfımız olduğunu düşünün:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+Çıktılardan, `$student` nesnesinin hem `Student` hem de `Person` sınıflarının bir örneği olarak kabul edildiği açıktır.
+
+
+Akıcı Arayüzler .[#toc-fluent-interfaces]
+-----------------------------------------
+
+"Akıcı Arayüz", OOP'de yöntemlerin tek bir çağrıda bir araya getirilmesini sağlayan bir tekniktir. Bu genellikle kodu basitleştirir ve netleştirir.
+
+Akıcı bir arayüzün temel unsuru, zincirdeki her yöntemin geçerli nesneye bir referans döndürmesidir. Bu, yöntemin sonunda `return $this;` kullanılarak gerçekleştirilir. Bu programlama tarzı genellikle bir nesnenin özelliklerinin değerlerini ayarlayan "setter" adı verilen yöntemlerle ilişkilendirilir.
+
+E-posta göndermek için akıcı bir arayüzün nasıl görünebileceğini görelim:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+Bu örnekte, `setFrom()`, `setRecipient()`, ve `setMessage()` yöntemleri ilgili değerleri (gönderen, alıcı, mesaj içeriği) ayarlamak için kullanılır. Bu değerlerin her birini ayarladıktan sonra, yöntemler geçerli nesneyi (`$email`) döndürür, böylece ondan sonra başka bir yöntemi zincirlememize izin verir. Son olarak, e-postayı gerçekten gönderen `send()` yöntemini çağırıyoruz.
+
+Akıcı arayüzler sayesinde sezgisel ve kolay okunabilir kodlar yazabiliyoruz.
+
+
+`clone` ile kopyalama .[#toc-copying-with-clone]
+------------------------------------------------
+
+PHP'de `clone` operatörünü kullanarak bir nesnenin kopyasını oluşturabiliriz. Bu şekilde, aynı içeriğe sahip yeni bir örnek elde ederiz.
+
+Bir nesneyi kopyalarken bazı özelliklerini değiştirmemiz gerekiyorsa, sınıfta özel bir `__clone()` yöntemi tanımlayabiliriz. Nesne klonlandığında bu yöntem otomatik olarak çağrılır.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+Bu örnekte, bir özelliği `$name` olan bir `Sheep` sınıfımız var. Bu sınıfın bir örneğini klonladığımızda, `__clone()` yöntemi klonlanan koyunun adının "Clone of" ön ekini almasını sağlar.
+
+
+Özellikler .[#toc-traits]
+-------------------------
+
+PHP'deki özellikler, sınıflar arasında yöntemlerin, özelliklerin ve sabitlerin paylaşılmasını sağlayan ve kod tekrarını önleyen bir araçtır. Bunları, bir özelliğin içeriğinin sınıflara "yapıştırıldığı" bir "kopyala ve yapıştır" mekanizması (Ctrl-C ve Ctrl-V) olarak düşünebilirsiniz. Bu, karmaşık sınıf hiyerarşileri oluşturmak zorunda kalmadan kodu yeniden kullanmanıza olanak tanır.
+
+PHP'de özelliklerin nasıl kullanılacağına dair basit bir örneğe göz atalım:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+Bu örnekte, bir yöntem içeren `Honking` adlı bir özelliğimiz var `honk()`. Sonra iki sınıfımız var: `Car` ve `Truck`, her ikisi de `Honking` özelliğini kullanıyor. Sonuç olarak, her iki sınıf da `honk()` yöntemine "sahiptir" ve bu yöntemi her iki sınıfın nesneleri üzerinde çağırabiliriz.
+
+Özellikler, sınıflar arasında kolay ve verimli bir şekilde kod paylaşımı yapmanızı sağlar. Kalıtım hiyerarşisine girmezler, yani `$car instanceof Honking`, `false` döndürür.
+
+
+İstisnalar .[#toc-exceptions]
+-----------------------------
+
+OOP'deki istisnalar, kodumuzdaki hataları ve beklenmedik durumları zarif bir şekilde ele almamızı sağlar. Bunlar, bir hata veya olağandışı durum hakkında bilgi taşıyan nesnelerdir.
+
+PHP'de, tüm istisnalar için temel teşkil eden yerleşik bir `Exception` sınıfımız vardır. Bunun, hata mesajı, hatanın oluştuğu dosya ve satır gibi istisna hakkında daha fazla bilgi almamızı sağlayan çeşitli yöntemleri vardır.
+
+Kodda bir hata oluştuğunda, `throw` anahtar sözcüğünü kullanarak istisnayı "atabiliriz".
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+`division()` fonksiyonu ikinci argüman olarak null aldığında, `'Division by zero!'` hata mesajını içeren bir istisna fırlatır. İstisna fırlatıldığında programın çökmesini önlemek için, istisnayı `try/catch` bloğuna hapsediyoruz:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+İstisna fırlatabilen kod bir blok `try` içine sarılır. İstisna atılırsa, kod yürütmesi istisnayı ele alabileceğimiz (örneğin, bir hata mesajı yazabileceğimiz) bir bloğa `catch` taşınır.
+
+ `try` ve `catch` bloklarından sonra, istisna atılsa da atılmasa da her zaman çalıştırılan isteğe bağlı bir `finally` bloğu ekleyebiliriz ( `try` veya `catch` bloğunda `return`, `break` veya `continue` kullansak bile):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Exception sınıfından miras alan kendi istisna sınıflarımızı (hiyerarşi) da oluşturabiliriz. Örnek olarak, para yatırma ve çekme işlemlerine izin veren basit bir bankacılık uygulaması düşünün:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Farklı türde istisnalar bekliyorsanız, tek bir `try` bloğu için birden fazla `catch` bloğu belirtilebilir.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+Bu örnekte, `catch` bloklarının sırasına dikkat etmek önemlidir. Tüm istisnalar `BankingException`dan miras alındığından, bu bloğu ilk olarak kullansaydık, kod sonraki `catch` bloklarına ulaşmadan tüm istisnalar bu blokta yakalanırdı. Bu nedenle, daha spesifik istisnaların (yani diğerlerinden miras kalanların) `catch` bloğu sıralamasında ana istisnalardan daha üstte olması önemlidir.
+
+
+Yinelemeler .[#toc-iterations]
+------------------------------
+
+PHP'de, `foreach` döngüsünü kullanarak, bir dizi içinde döngü yapar gibi nesneler arasında döngü yapabilirsiniz. Bunun çalışması için nesnenin özel bir arayüz uygulaması gerekir.
+
+İlk seçenek, `current()` mevcut değeri döndüren, `key()` anahtarı döndüren, `next()` bir sonraki değere geçen, `rewind()` başa geçen ve `valid()` henüz sona gelip gelmediğimizi kontrol eden yöntemlere sahip `Iterator` arayüzünü uygulamaktır.
+
+Diğer seçenek ise sadece bir metodu olan `IteratorAggregate` arayüzünü uygulamaktır `getIterator()`. Bu, çapraz geçişi sağlayacak bir yer tutucu nesne döndürür ya da anahtarları ve değerleri sırayla döndürmek için `yield` kullanan özel bir işlev olan bir üreteç olabilir:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+En İyi Uygulamalar .[#toc-best-practices]
+-----------------------------------------
+
+Nesne yönelimli programlamanın temel ilkelerini öğrendikten sonra, OOP'deki en iyi uygulamalara odaklanmak çok önemlidir. Bunlar yalnızca işlevsel değil aynı zamanda okunabilir, anlaşılabilir ve bakımı kolay kodlar yazmanıza yardımcı olacaktır.
+
+1) **İlgilerin Ayrılması**: Her sınıfın açıkça tanımlanmış bir sorumluluğu olmalı ve yalnızca bir birincil görevi ele almalıdır. Bir sınıf çok fazla şey yapıyorsa, onu daha küçük, uzmanlaşmış sınıflara bölmek uygun olabilir.
+2) **Kapsülleme**: Veri ve yöntemler mümkün olduğunca gizli olmalı ve yalnızca tanımlanmış bir arayüz aracılığıyla erişilebilir olmalıdır. Bu, kodun geri kalanını etkilemeden bir sınıfın dahili uygulamasını değiştirmenize olanak tanır.
+3) **Dependency Injection**: Bağımlılıkları doğrudan bir sınıfın içinde oluşturmak yerine, onları dışarıdan "enjekte etmelisiniz". Bu prensibi daha iyi anlamak için [Bağımlılık Enjeksiyonu bölümünü |dependency-injection:introduction] okumanızı tavsiye ederiz.
diff --git a/nette/tr/troubleshooting.texy b/nette/tr/troubleshooting.texy
index 1bfffdea1c..5e94434a53 100644
--- a/nette/tr/troubleshooting.texy
+++ b/nette/tr/troubleshooting.texy
@@ -18,7 +18,7 @@ Hatanın nedenini her zaman `log/` dizininde bulabilirsiniz. Ancak, hata mesajı
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // IP adresiniz
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Hata 404, yönlendirme çalışmıyor .[#toc-error-404-routing-not-working]
 Tüm sayfalar (ana sayfa hariç) 404 hatası döndürdüğünde, [güzel URL' |#How to Configure a Server for Nice URLs?]ler için bir sunucu yapılandırma sorunu gibi görünür.
 
 
+Geliştirme Sırasında Önbellek Nasıl Devre Dışı Bırakılır? .[#toc-how-to-disable-cache-during-development]
+---------------------------------------------------------------------------------------------------------
+Nette akıllıdır ve içinde önbelleği devre dışı bırakmanıza gerek yoktur. Geliştirme sırasında, şablonda veya DI konteyner yapılandırmasında bir değişiklik olduğunda önbelleği otomatik olarak günceller. Dahası, geliştirme modu otomatik algılama ile etkinleştirilir, bu nedenle genellikle herhangi bir şeyi [veya yalnızca IP adresini |application:bootstrap#development-vs-production-mode] yapılandırmaya gerek yoktur.
+
+Yönlendiricide hata ayıklarken, örneğin yönlendirmelerin depolanabileceği tarayıcı önbelleğini devre dışı bırakmanızı öneririz: Geliştirici Araçları'nı açın (Ctrl+Shift+I veya Cmd+Option+I) ve Ağ panelinde önbelleği devre dışı bırakmak için kutuyu işaretleyin.
+
+
 Hata `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 --------------------------------------------------------------------------------------------------------------------
 Bu hata, PHP'yi 8.1 sürümüne yükselttiyseniz ancak onunla uyumlu olmayan Nette kullanıyorsanız ortaya çıkar. Çözüm, `composer update` adresini kullanarak Nette'yi daha yeni bir sürüme güncellemektir. Nette, PHP 8.1'i 3.0 sürümünden beri desteklemektedir. Daha eski bir sürüm kullanıyorsanız ( `composer.json` adresine bakarak öğrenebilirsiniz), Nette'yi [yükseltin |migrations:en] veya PHP 8.0 ile kalın.
@@ -67,7 +74,7 @@ Nette'deki örnek projelerde kullanılan `www/` dizini, projenin genel dizini ve
 
 Uygulamayı hosting üzerinde çalıştırmak için, hosting yapılandırmasında document-root'u bu dizine ayarlamanız gerekir. Veya, barındırma, farklı bir adla (örneğin `web`, `public_html` vb.) genel dizin için önceden oluşturulmuş bir klasöre sahipse, `www/` adını değiştirmeniz yeterlidir.
 
-Çözüm, `.htaccess` dosyasındaki veya yönlendiricideki kuralları kullanarak `www/` klasöründen "kurtulmak" değildir. Hosting, document-root'u bir alt dizine ayarlamanıza (yani genel dizinin bir seviye üstünde dizinler oluşturmanıza) izin vermiyorsa, başka bir tane arayın. Aksi takdirde önemli bir güvenlik riski almış olursunuz. Bu, ön kapısını kapatamadığınız ve her zaman ardına kadar açık olan bir apartman dairesinde yaşamaya benzer.
+Çözüm, `.htaccess` dosyasındaki veya yönlendiricideki kuralları kullanarak `www/` dışındaki tüm klasörlere erişimi engellemek **değildir**. Barındırma hizmetiniz belge kökünü bir alt dizine ayarlamaya (yani genel dizinin bir seviye üstünde dizinler oluşturmaya) izin vermiyorsa, farklı bir barındırma hizmeti aramalısınız. Aksi takdirde, kendinizi önemli güvenlik risklerine maruz bırakmış olursunuz. Bu, ön kapısı kapatılamayan ve her zaman ardına kadar açık olan bir apartman dairesinde yaşamaya benzer.
 
 
 Güzel URL'ler için Sunucu Nasıl Yapılandırılır? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/nette/uk/@home.texy b/nette/uk/@home.texy
index 22a16c5c9d..1783ac19fe 100644
--- a/nette/uk/@home.texy
+++ b/nette/uk/@home.texy
@@ -84,11 +84,11 @@
 - [JSON |utils:JSON]
 - [NEON |neon:]
 - [Зашивання пароля |security:passwords]
-- [SmartObject |utils:SmartObject]
 - [Типи PHP |utils:type]
 - [Strings |utils:Strings]
 - [Валідатори |utils:validators]
 - [RobotLoader |robot-loader:]
+- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass]
 - [SafeStream |safe-stream:]
 - [...інше |utils:]
 </div>
diff --git a/nette/uk/installation.texy b/nette/uk/installation.texy
index d0bb92c629..af5ff9936a 100644
--- a/nette/uk/installation.texy
+++ b/nette/uk/installation.texy
@@ -20,7 +20,7 @@ Nette пропонує колекцію корисних і складних п
 composer require nette/utils
 ```
 
-Віддаєте перевагу графічному інтерфейсу? Ознайомтеся з [посібником |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] зі встановлення пакунків у середовищі PhpStrom.
+Віддаєте перевагу графічному інтерфейсу? Ознайомтеся з [посібником |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] зі встановлення пакунків у середовищі PhpStorm.
 
 
 Як розпочати новий проект за допомогою Nette .[#toc-how-to-start-a-new-project-with-nette]
diff --git a/nette/uk/introduction-to-object-oriented-programming.texy b/nette/uk/introduction-to-object-oriented-programming.texy
new file mode 100644
index 0000000000..5934433158
--- /dev/null
+++ b/nette/uk/introduction-to-object-oriented-programming.texy
@@ -0,0 +1,841 @@
+Вступ до об'єктно-орієнтованого програмування
+*********************************************
+
+.[perex]
+Термін "ООП" розшифровується як об'єктно-орієнтоване програмування - спосіб організації та структурування коду. ООП дозволяє розглядати програму як набір об'єктів, які взаємодіють між собою, а не як послідовність команд і функцій.
+
+В ООП "об'єкт" - це одиниця, яка містить дані та функції, що оперують цими даними. Об'єкти створюються на основі "класів", які можна розуміти як схеми або шаблони для об'єктів. Маючи клас, ми можемо створити його "екземпляр", тобто конкретний об'єкт, створений на основі цього класу.
+
+Давайте розглянемо, як можна створити простий клас в PHP. При визначенні класу ми використовуємо ключове слово "class", за яким слідує ім'я класу, а потім фігурні дужки, в які вкладаються функції класу (звані "методами") і змінні класу (звані "властивостями" або "атрибутами"):
+
+```php
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+У цьому прикладі ми створили клас з іменем `Car` з однією функцією (або "методом") `honk`.
+
+Кожен клас повинен вирішувати лише одне основне завдання. Якщо клас виконує занадто багато завдань, може бути доцільно розділити його на менші, спеціалізовані класи.
+
+Класи зазвичай зберігаються в окремих файлах, щоб упорядкувати код і полегшити навігацію по ньому. Ім'я файлу має відповідати імені класу, тому для класу `Car` ім'я файлу буде `Car.php`.
+
+Називаючи класи, варто дотримуватися конвенції "PascalCase", тобто кожне слово в назві починається з великої літери, без підкреслень або інших роздільників. Методи та властивості слідують конвенції "camelCase", тобто починаються з малої літери.
+
+Деякі методи в PHP відіграють особливу роль і мають префікс `__` (два підкреслення). Одним з найважливіших спеціальних методів є "конструктор", позначений як `__construct`. Конструктор - це метод, який автоматично викликається при створенні нового екземпляра класу.
+
+Ми часто використовуємо конструктор для встановлення початкового стану об'єкта. Наприклад, при створенні об'єкта, що представляє людину, ви можете використовувати конструктор, щоб встановити її вік, ім'я або інші атрибути.
+
+Давайте подивимося, як використовувати конструктор в PHP:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person(25);
+echo $person->howOldAreYou(); // Outputs: 25
+```
+
+У цьому прикладі клас `Person` має властивість (змінну) `$age` і конструктор, який встановлює цю властивість. Метод `howOldAreYou()` надає доступ до віку людини.
+
+Псевдозмінна `$this` використовується всередині класу для доступу до властивостей і методів об'єкта.
+
+Ключове слово `new` використовується для створення нового екземпляра класу. У наведеному вище прикладі ми створили нову особу віком 25 років.
+
+Ви також можете встановити значення за замовчуванням для параметрів конструктора, якщо вони не вказані при створенні об'єкта. Наприклад:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age = 20)
+	{
+		$this->age = $age;
+	}
+
+	function howOldAreYou()
+	{
+		return $this->age;
+	}
+}
+
+$person = new Person;  // if no argument is passed, parentheses can be omitted
+echo $person->howOldAreYou(); // Outputs: 20
+```
+
+У цьому прикладі, якщо не вказати вік при створенні об'єкта `Person`, буде використано значення за замовчуванням 20.
+
+Приємно те, що визначення властивості з її ініціалізацією через конструктор можна скоротити і спростити таким чином:
+
+```php
+class Person
+{
+	function __construct(
+		private $age = 20,
+	) {
+	}
+}
+```
+
+Для повноти, окрім конструкторів, об'єкти можуть мати деструктори (метод `__destruct`), які викликаються перед звільненням об'єкта з пам'яті.
+
+
+Простори імен .[#toc-namespaces]
+--------------------------------
+
+Простори імен дозволяють нам організовувати і групувати пов'язані класи, функції і константи, уникаючи конфліктів імен. Ви можете уявити їх як папки на комп'ютері, де кожна папка містить файли, пов'язані з певним проектом або темою.
+
+Простори імен особливо корисні у великих проектах або при використанні сторонніх бібліотек, де можуть виникати конфлікти імен класів.
+
+Уявіть, що у вашому проекті є клас з іменем `Car`, і ви хочете розмістити його у просторі імен `Transport`. Ви можете зробити це таким чином:
+
+```php
+namespace Transport;
+
+class Car
+{
+	function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+```
+
+Якщо ви хочете використати клас `Car` в іншому файлі, вам потрібно вказати, з якого простору імен походить клас:
+
+```php
+$car = new Transport\Car;
+```
+
+Для спрощення ви можете вказати на початку файлу, який саме клас з певного простору імен ви хочете використовувати, що дозволить вам створювати екземпляри без зазначення повного шляху:
+
+```php
+use Transport\Car;
+
+$car = new Car;
+```
+
+
+Спадщина .[#toc-inheritance]
+----------------------------
+
+Спадкування - це інструмент об'єктно-орієнтованого програмування, який дозволяє створювати нові класи на основі існуючих, успадковувати їх властивості та методи, а також розширювати або перевизначати їх за потреби. Спадкування забезпечує повторне використання коду та ієрархію класів.
+
+Простіше кажучи, якщо ми маємо один клас і хочемо створити інший, похідний від нього, але з деякими змінами, ми можемо "успадкувати" новий клас від початкового.
+
+У PHP успадкування реалізується за допомогою ключового слова `extends`.
+
+Наш клас `Person` зберігає інформацію про вік. Ми можемо створити ще один клас, `Student`, який розширює `Person` і додає інформацію про галузь навчання.
+
+Давайте розглянемо приклад:
+
+```php
+class Person
+{
+	private $age;
+
+	function __construct($age)
+	{
+		$this->age = $age;
+	}
+
+	function printInformation()
+	{
+		echo "Age: {$this->age} years\n";
+	}
+}
+
+class Student extends Person
+{
+	private $fieldOfStudy;
+
+	function __construct($age, $fieldOfStudy)
+	{
+		parent::__construct($age);
+		$this->fieldOfStudy = $fieldOfStudy;
+	}
+
+	function printInformation()
+	{
+		parent::printInformation();
+		echo "Field of study: {$this->fieldOfStudy} \n";
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+$student->printInformation();
+```
+
+Як працює цей код?
+
+- Ми використали ключове слово `extends` для розширення класу `Person`, тобто клас `Student` успадковує всі методи та властивості від `Person`.
+
+- Ключове слово `parent::` дозволяє нам викликати методи з батьківського класу. У цьому випадку ми викликали конструктор з класу `Person` перед тим, як додати власну функціональність до класу `Student`. І аналогічно, метод предка `printInformation()` перед виведенням інформації про студента.
+
+Спадкування призначене для ситуацій, коли між класами існує відношення "є". Наприклад, `Student` є `Person`. Кіт - це тварина. Це дозволяє нам у випадках, коли ми очікуємо один об'єкт (наприклад, "Людина") в коді, використовувати замість нього похідний об'єкт (наприклад, "Студент").
+
+Важливо розуміти, що основною метою успадкування **не є** запобігання дублюванню коду. Навпаки, зловживання успадкуванням може призвести до створення складного і важкого для супроводу коду. Якщо між класами немає відношення "є", то замість успадкування слід розглядати композицію.
+
+Зверніть увагу, що методи `printInformation()` у класах `Person` та `Student` виводять дещо різну інформацію. І ми можемо додати інші класи (наприклад, `Employee`), які будуть надавати інші реалізації цього методу. Здатність об'єктів різних класів по-різному реагувати на один і той самий метод називається поліморфізмом:
+
+```php
+$people = [
+	new Person(30),
+	new Student(20, 'Computer Science'),
+	new Employee(45, 'Director'),
+];
+
+foreach ($people as $person) {
+	$person->printInformation();
+}
+```
+
+
+Композиція .[#toc-composition]
+------------------------------
+
+Композиція - це техніка, коли замість того, щоб успадковувати властивості та методи з іншого класу, ми просто використовуємо його екземпляр у своєму класі. Це дозволяє об'єднати функціональність і властивості декількох класів без створення складних структур успадкування.
+
+Наприклад, у нас є клас `Engine` і клас `Car`. Замість того, щоб сказати "Автомобіль - це двигун", ми скажемо "Автомобіль має двигун", що є типовим відношенням композиції.
+
+```php
+class Engine
+{
+	function start()
+	{
+		echo 'Engine is running.';
+	}
+}
+
+class Car
+{
+	private $engine;
+
+	function __construct()
+	{
+		$this->engine = new Engine;
+	}
+
+	function start()
+	{
+		$this->engine->start();
+		echo 'The car is ready to drive!';
+	}
+}
+
+$car = new Car;
+$car->start();
+```
+
+Тут `Car` не має всіх властивостей і методів класу `Engine`, але має доступ до нього через властивість `$engine`.
+
+Перевагою композиції є більша гнучкість дизайну та краща адаптивність до майбутніх змін.
+
+
+Видимість .[#toc-visibility]
+----------------------------
+
+У PHP ви можете визначити "видимість" для властивостей, методів і констант класу. Видимість визначає, де ви можете отримати доступ до цих елементів.
+
+1. **Публічний:** Якщо елемент позначено як `public`, це означає, що ви можете отримати до нього доступ з будь-якого місця, навіть за межами класу.
+
+2. **Protected:** Елемент, позначений як `protected`, доступний тільки в межах класу та всіх його нащадків (класів, що успадковуються від нього).
+
+3. **Приватний:** Якщо елемент позначено як `private`, ви можете отримати доступ до нього лише з класу, в якому його було визначено.
+
+Якщо ви не вкажете видимість, PHP автоматично встановить її на `public`.
+
+Давайте розглянемо приклад коду:
+
+```php
+class VisibilityExample
+{
+	public $publicProperty = 'Public';
+	protected $protectedProperty = 'Protected';
+	private $privateProperty = 'Private';
+
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		echo $this->privateProperty;    // Works
+	}
+}
+
+$object = new VisibilityExample;
+$object->printProperties();
+echo $object->publicProperty;        // Works
+// echo $object->protectedProperty;   // Throws an error
+// echo $object->privateProperty;     // Throws an error
+```
+
+Продовження успадкування класів:
+
+```php
+class ChildClass extends VisibilityExample
+{
+	public function printProperties()
+	{
+		echo $this->publicProperty;     // Works
+		echo $this->protectedProperty;  // Works
+		// echo $this->privateProperty;   // Throws an error
+	}
+}
+```
+
+У цьому випадку метод `printProperties()` у класі `ChildClass` може отримати доступ до загальнодоступних та захищених властивостей, але не може отримати доступ до приватних властивостей батьківського класу.
+
+Дані та методи повинні бути максимально прихованими і доступними лише через визначений інтерфейс. Це дозволяє змінювати внутрішню реалізацію класу, не впливаючи на решту коду.
+
+
+Заключне ключове слово .[#toc-final-keyword]
+--------------------------------------------
+
+У PHP ми можемо використовувати ключове слово `final`, якщо ми хочемо запобігти успадкуванню або перевизначенню класу, методу або константи. Коли клас позначено як `final`, він не може бути розширений. Коли метод позначено як `final`, його не можна перевизначити в підкласі.
+
+Усвідомлення того, що певний клас або метод більше не буде модифіковано, дозволяє нам легше вносити зміни, не турбуючись про потенційні конфлікти. Наприклад, ми можемо додати новий метод, не боячись, що у нащадка вже може бути метод з такою ж назвою, що призведе до колізії. Або ми можемо змінити параметри методу, знову ж таки без ризику спричинити неузгодженість з перевизначеним методом у нащадка.
+
+```php
+final class FinalClass
+{
+}
+
+// The following code will throw an error because we cannot inherit from a final class.
+class ChildOfFinalClass extends FinalClass
+{
+}
+```
+
+У цьому прикладі спроба успадкувати від кінцевого класу `FinalClass` призведе до помилки.
+
+
+Статичні властивості та методи .[#toc-static-properties-and-methods]
+--------------------------------------------------------------------
+
+Коли ми говоримо про "статичні" елементи класу в PHP, ми маємо на увазі методи і властивості, які належать самому класу, а не конкретному екземпляру класу. Це означає, що вам не потрібно створювати екземпляр класу, щоб отримати до них доступ. Замість цього ви викликаєте або отримуєте доступ до них безпосередньо через ім'я класу.
+
+Майте на увазі, що оскільки статичні елементи належать класу, а не його екземплярам, ви не можете використовувати псевдо-змінну `$this` всередині статичних методів.
+
+Використання статичних властивостей призводить до [заплутаного коду, повного підводних каменів |dependency-injection:global-state], тому ви ніколи не повинні використовувати їх, і ми не будемо показувати приклад тут. З іншого боку, статичні методи корисні. Ось приклад:
+
+```php
+class Calculator
+{
+	public static function add($a, $b)
+	{
+		return $a + $b;
+	}
+
+	public static function subtract($a, $b)
+	{
+		return $a - $b;
+	}
+}
+
+// Using the static method without creating an instance of the class
+echo Calculator::add(5, 3); // Output: 8
+echo Calculator::subtract(5, 3); // Output: 2
+```
+
+У цьому прикладі ми створили клас `Calculator` з двома статичними методами. Ми можемо викликати ці методи безпосередньо, не створюючи екземпляр класу за допомогою оператора `::`. Статичні методи особливо корисні для операцій, які не залежать від стану конкретного екземпляра класу.
+
+
+Константи класу .[#toc-class-constants]
+---------------------------------------
+
+У класах ми маємо можливість визначати константи. Константи - це значення, які ніколи не змінюються під час виконання програми. На відміну від змінних, значення константи залишається незмінним.
+
+```php
+class Car
+{
+	public const NumberOfWheels = 4;
+
+	public function displayNumberOfWheels(): int
+	{
+		echo self::NumberOfWheels;
+	}
+}
+
+echo Car::NumberOfWheels;  // Output: 4
+```
+
+У цьому прикладі ми маємо клас `Car` з константою `NumberOfWheels`. При зверненні до константи всередині класу ми можемо використовувати ключове слово `self` замість імені класу.
+
+
+Інтерфейси об'єктів .[#toc-object-interfaces]
+---------------------------------------------
+
+Об'єктні інтерфейси діють як "контракти" для класів. Якщо клас реалізує об'єктний інтерфейс, він повинен містити всі методи, які визначає інтерфейс. Це чудовий спосіб гарантувати, що певні класи дотримуються одного "контракту" або структури.
+
+У PHP інтерфейси визначаються за допомогою ключового слова `interface`. Всі методи, визначені в інтерфейсі, є загальнодоступними (`public`). Коли клас реалізує інтерфейс, він використовує ключове слово `implements`.
+
+```php
+interface Animal
+{
+	function makeSound();
+}
+
+class Cat implements Animal
+{
+	public function makeSound()
+	{
+		echo 'Meow';
+	}
+}
+
+$cat = new Cat;
+$cat->makeSound();
+```
+
+Якщо клас реалізує інтерфейс, але не всі очікувані методи визначені, PHP видасть помилку.
+
+Клас може реалізовувати декілька інтерфейсів одночасно, що відрізняється від успадкування, де клас може успадковувати тільки від одного класу:
+
+```php
+interface Guardian
+{
+	function guardHouse();
+}
+
+class Dog implements Animal, Guardian
+{
+	public function makeSound()
+	{
+		echo 'Bark';
+	}
+
+	public function guardHouse()
+	{
+		echo 'Dog diligently guards the house';
+	}
+}
+```
+
+
+Абстрактні класи .[#toc-abstract-classes]
+-----------------------------------------
+
+Абстрактні класи слугують базовими шаблонами для інших класів, але ви не можете створювати їхні екземпляри безпосередньо. Вони містять суміш повних методів та абстрактних методів, які не мають визначеного змісту. Класи, які успадковують абстрактні класи, повинні надавати визначення для всіх абстрактних методів батьківського класу.
+
+Ми використовуємо ключове слово `abstract` для визначення абстрактного класу.
+
+```php
+abstract class AbstractClass
+{
+	public function regularMethod()
+	{
+		echo 'This is a regular method';
+	}
+
+	abstract public function abstractMethod();
+}
+
+class Child extends AbstractClass
+{
+	public function abstractMethod()
+	{
+		echo 'This is the implementation of the abstract method';
+	}
+}
+
+$instance = new Child;
+$instance->regularMethod();
+$instance->abstractMethod();
+```
+
+У цьому прикладі ми маємо абстрактний клас з одним звичайним і одним абстрактним методом. Потім у нас є клас `Child`, який успадковується від `AbstractClass` і надає реалізацію для абстрактного методу.
+
+Чим відрізняються інтерфейси від абстрактних класів? Абстрактні класи можуть містити як абстрактні, так і конкретні методи, в той час як інтерфейси лише визначають, які методи повинен реалізовувати клас, але не надають їх реалізації. Клас може успадковувати лише один абстрактний клас, але може реалізовувати будь-яку кількість інтерфейсів.
+
+
+Перевірка типів .[#toc-type-checking]
+-------------------------------------
+
+У програмуванні дуже важливо переконатися, що дані, з якими ми працюємо, мають правильний тип. У PHP є інструменти, які забезпечують таку впевненість. Перевірка того, що дані мають правильний тип, називається "перевіркою типу".
+
+Типи, з якими ми можемо зіткнутися в PHP:
+
+1. **Базові типи**: До них відносяться `int` (цілі числа), `float` (числа з плаваючою комою), `bool` (логічні значення), `string` (рядки), `array` (масиви) і `null`.
+2. **Класи**: Коли ми хочемо, щоб значення було екземпляром певного класу.
+3. **Інтерфейси**: Визначає набір методів, які клас повинен реалізувати. Значення, яке відповідає інтерфейсу, повинно мати ці методи.
+4. **Змішані типи**: Ми можемо вказати, що змінна може мати декілька дозволених типів.
+5. **Немає значення**: Цей спеціальний тип вказує на те, що функція або метод не повертає жодного значення.
+
+Давайте подивимося, як модифікувати код для включення типів:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+
+	public function printAge(): void
+	{
+		echo "This person is {$this->age} years old.";
+	}
+}
+
+/**
+ * A function that accepts a Person object and prints the person's age.
+ */
+function printPersonAge(Person $person): void
+{
+	$person->printAge();
+}
+```
+
+Таким чином, ми гарантуємо, що наш код очікує і працює з даними правильного типу, що допоможе нам запобігти потенційним помилкам.
+
+Деякі типи не можуть бути написані безпосередньо в PHP. В такому випадку вони перераховуються в коментарі phpDoc, який є стандартним форматом для документування PHP-коду, починаючи з `/**` і закінчуючи `*/`. Він дозволяє додавати описи класів, методів і так далі. А також перераховувати складні типи за допомогою так званих анотацій `@var`, `@param` і `@return`. Ці типи потім використовуються інструментами статичного аналізу коду, але не перевіряються самим PHP.
+
+```php
+class Registry
+{
+	/** @var array<Person>  indicates that it's an array of Person objects */
+	private array $persons = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->persons[] = $person;
+	}
+}
+```
+
+
+Порівняння та ідентифікація .[#toc-comparison-and-identity]
+-----------------------------------------------------------
+
+У PHP ви можете порівнювати об'єкти двома способами:
+
+1. Порівняння значень `==`: Перевіряє, чи об'єкти належать до одного класу і мають однакові значення у своїх властивостях.
+2. Ідентифікація `===`: Перевіряє, чи це той самий екземпляр об'єкта.
+
+```php
+class Car
+{
+	public string $brand;
+
+	public function __construct(string $brand)
+	{
+		$this->brand = $brand;
+	}
+}
+
+$car1 = new Car('Skoda');
+$car2 = new Car('Skoda');
+$car3 = $car1;
+
+var_dump($car1 == $car2);   // true, because they have the same value
+var_dump($car1 === $car2);  // false, because they are not the same instance
+var_dump($car1 === $car3);  // true, because $car3 is the same instance as $car1
+```
+
+
+Оператор `instanceof` .[#toc-the-instanceof-operator]
+-----------------------------------------------------
+
+Оператор `instanceof` дозволяє визначити, чи є даний об'єкт екземпляром певного класу, нащадком цього класу або чи реалізує він певний інтерфейс.
+
+Уявімо, що у нас є клас `Person` і ще один клас `Student`, який є нащадком класу `Person`:
+
+```php
+class Person
+{
+	private int $age;
+
+	public function __construct(int $age)
+	{
+		$this->age = $age;
+	}
+}
+
+class Student extends Person
+{
+	private string $major;
+
+	public function __construct(int $age, string $major)
+	{
+		parent::__construct($age);
+		$this->major = $major;
+	}
+}
+
+$student = new Student(20, 'Computer Science');
+
+// Check if $student is an instance of the Student class
+var_dump($student instanceof Student);  // Output: bool(true)
+
+// Check if $student is an instance of the Person class (because Student is a descendant of Person)
+var_dump($student instanceof Person);   // Output: bool(true)
+```
+
+З результатів видно, що об'єкт `$student` вважається екземпляром класів `Student` та `Person`.
+
+
+Зручні інтерфейси .[#toc-fluent-interfaces]
+-------------------------------------------
+
+"Вільний інтерфейс" - це техніка в ООП, яка дозволяє об'єднувати методи в ланцюжок в одному виклику. Це часто спрощує і робить код зрозумілішим.
+
+Ключовим елементом вільного інтерфейсу є те, що кожен метод у ланцюжку повертає посилання на поточний об'єкт. Це досягається за рахунок використання `return $this;` в кінці методу. Цей стиль програмування часто асоціюється з методами, що називаються "сеттерами", які встановлюють значення властивостей об'єкта.
+
+Давайте подивимося, як може виглядати зручний інтерфейс для надсилання електронних листів:
+
+```php
+public function sendMessage()
+{
+	$email = new Email;
+	$email->setFrom('sender@example.com')
+		  ->setRecipient('admin@example.com')
+		  ->setMessage('Hello, this is a message.')
+		  ->send();
+}
+```
+
+У цьому прикладі методи `setFrom()`, `setRecipient()` і `setMessage()` використовуються для встановлення відповідних значень (відправник, одержувач, зміст повідомлення). Після встановлення кожного з цих значень методи повертають поточний об'єкт (`$email`), що дозволяє нам підключити інший метод після нього. Нарешті, ми викликаємо метод `send()`, який власне і надсилає лист.
+
+Завдяки вільним інтерфейсам ми можемо писати код, який є інтуїтивно зрозумілим і легко читається.
+
+
+Копіювання за допомогою `clone` .[#toc-copying-with-clone]
+----------------------------------------------------------
+
+У PHP ми можемо створити копію об'єкта за допомогою оператора `clone`. Таким чином, ми отримуємо новий екземпляр з ідентичним вмістом.
+
+Якщо при копіюванні об'єкта нам потрібно змінити деякі його властивості, ми можемо визначити в класі спеціальний метод `__clone()`. Цей метод автоматично викликається при клонуванні об'єкта.
+
+```php
+class Sheep
+{
+	public string $name;
+
+	public function __construct(string $name)
+	{
+		$this->name = $name;
+	}
+
+	public function __clone()
+	{
+		$this->name = 'Clone of ' . $this->name;
+	}
+}
+
+$original = new Sheep('Dolly');
+echo $original->name . "\n";  // Outputs: Dolly
+
+$clone = clone $original;
+echo $clone->name . "\n";     // Outputs: Clone of Dolly
+```
+
+У нашому прикладі є клас `Sheep` з однією властивістю `$name`. Коли ми клонуємо екземпляр цього класу, метод `__clone()` гарантує, що ім'я клонованої вівці отримає префікс "Clone of".
+
+
+Властивості .[#toc-traits]
+--------------------------
+
+Риси в PHP - це інструмент, який дозволяє обмінюватися методами, властивостями і константами між класами і запобігає дублюванню коду. Ви можете думати про них як про механізм "копіювання і вставки" (Ctrl-C і Ctrl-V), де вміст трейту "вставляється" в класи. Це дозволяє повторно використовувати код без необхідності створювати складні ієрархії класів.
+
+Давайте розглянемо простий приклад використання трейтів в PHP:
+
+```php
+trait Honking
+{
+	public function honk()
+	{
+		echo 'Beep beep!';
+	}
+}
+
+class Car
+{
+	use Honking;
+}
+
+class Truck
+{
+	use Honking;
+}
+
+$car = new Car;
+$car->honk(); // Outputs 'Beep beep!'
+
+$truck = new Truck;
+$truck->honk(); // Also outputs 'Beep beep!'
+```
+
+У цьому прикладі у нас є трейт з іменем `Honking`, який містить один метод `honk()`. Потім у нас є два класи: `Car` і `Truck`, обидва з яких використовують трейта `Honking`. У результаті обидва класи "мають" метод `honk()`, і ми можемо викликати його в об'єктах обох класів.
+
+Трейти дозволяють легко і ефективно обмінюватися кодом між класами. Вони не входять в ієрархію успадкування, тобто `$car instanceof Honking` поверне `false`.
+
+
+Винятки
+-------
+
+Винятки в ООП дозволяють нам витончено обробляти помилки та непередбачувані ситуації в нашому коді. Це об'єкти, які несуть інформацію про помилку або нестандартну ситуацію.
+
+У PHP є вбудований клас `Exception`, який служить основою для всіх винятків. Він має кілька методів, які дозволяють отримати більше інформації про виняток, наприклад, повідомлення про помилку, файл і рядок, де сталася помилка, тощо.
+
+Коли в коді виникає помилка, ми можемо "згенерувати" виключення за допомогою ключового слова `throw`.
+
+```php
+function division(float $a, float $b): float
+{
+	if ($b === 0) {
+		throw new Exception('Division by zero!');
+	}
+	return $a / $b;
+}
+```
+
+Коли функція `division()` отримує другим аргументом null, вона генерує виключення з повідомленням про помилку `'Division by zero!'`. Щоб запобігти аварійному завершенню роботи програми при виникненні виключення, ми перехоплюємо його у блоці `try/catch`:
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+}
+```
+
+Код, що може згенерувати виключення, обгорнутий в блок `try`. Якщо виняток згенеровано, виконання коду переходить до блоку `catch`, де ми можемо обробити виняток (наприклад, написати повідомлення про помилку).
+
+Після блоків `try` і `catch` можна додати необов'язковий блок `finally`, який завжди виконується незалежно від того, чи було згенеровано виключення чи ні (навіть якщо ми використовуємо `return`, `break` або `continue` в блоці `try` або `catch` ):
+
+```php
+try {
+	echo division(10, 0);
+} catch (Exception $e) {
+	echo 'Exception caught: '. $e->getMessage();
+} finally {
+	// Code that is always executed whether the exception has been thrown or not
+}
+```
+
+Ми також можемо створювати власні класи винятків (ієрархію), які успадковуються від класу Exception. Як приклад, розглянемо простий банківський додаток, який дозволяє вносити та знімати кошти:
+
+```php
+class BankingException extends Exception {}
+class InsufficientFundsException extends BankingException {}
+class ExceededLimitException extends BankingException {}
+
+class BankAccount
+{
+	private int $balance = 0;
+	private int $dailyLimit = 1000;
+
+	public function deposit(int $amount): int
+	{
+		$this->balance += $amount;
+		return $this->balance;
+	}
+
+	public function withdraw(int $amount): int
+	{
+		if ($amount > $this->balance) {
+			throw new InsufficientFundsException('Not enough funds in the account.');
+		}
+
+		if ($amount > $this->dailyLimit) {
+			throw new ExceededLimitException('Daily withdrawal limit exceeded.');
+		}
+
+		$this->balance -= $amount;
+		return $this->balance;
+	}
+}
+```
+
+Для одного блоку `try` можна вказати кілька блоків `catch`, якщо ви очікуєте різні типи виключень.
+
+```php
+$account = new BankAccount;
+$account->deposit(500);
+
+try {
+	$account->withdraw(1500);
+} catch (ExceededLimitException $e) {
+	echo $e->getMessage();
+} catch (InsufficientFundsException $e) {
+	echo $e->getMessage();
+} catch (BankingException $e) {
+	echo 'An error occurred during the operation.';
+}
+```
+
+У цьому прикладі важливо звернути увагу на порядок розташування блоків `catch`. Оскільки всі винятки успадковуються від `BankingException`, якби цей блок був першим, то всі винятки були б перехоплені в ньому без того, щоб код дійшов до наступних блоків `catch`. Тому важливо, щоб більш специфічні винятки (тобто ті, що успадковуються від інших) були вище в порядку блоків `catch`, ніж їхні батьківські винятки.
+
+
+Ітерації .[#toc-iterations]
+---------------------------
+
+У PHP ви можете циклічно перебирати об'єкти за допомогою циклу `foreach`, подібно до того, як ви перебираєте масив. Щоб це працювало, об'єкт повинен реалізовувати спеціальний інтерфейс.
+
+Перший варіант - реалізувати інтерфейс `Iterator`, який має методи `current()`, що повертає поточне значення, `key()`, що повертає ключ, `next()`, що переходить до наступного значення, `rewind()`, що переходить на початок, і `valid()`, що перевіряє, чи ми ще не дійшли до кінця.
+
+Інший варіант - реалізувати інтерфейс `IteratorAggregate`, який має лише один метод `getIterator()`. Він або повертає об'єкт-заповнювач, який забезпечить обхід, або може бути генератором, тобто спеціальною функцією, яка використовує `yield` для послідовного повернення ключів і значень:
+
+```php
+class Person
+{
+	public function __construct(
+		public int $age,
+	) {
+	}
+}
+
+class Registry implements IteratorAggregate
+{
+	private array $people = [];
+
+	public function addPerson(Person $person): void
+	{
+		$this->people[] = $person;
+	}
+
+	public function getIterator(): Generator
+	{
+		foreach ($this->people as $person) {
+			yield $person;
+		}
+	}
+}
+
+$list = new Registry;
+$list->addPerson(new Person(30));
+$list->addPerson(new Person(25));
+
+foreach ($list as $person) {
+	echo "Age: {$person->age} years\n";
+}
+```
+
+
+Кращі практики .[#toc-best-practices]
+-------------------------------------
+
+Після того, як ви засвоїли основні принципи об'єктно-орієнтованого програмування, дуже важливо зосередитися на найкращих практиках ООП. Вони допоможуть вам писати код, який буде не лише функціональним, але й читабельним, зрозумілим та легко підтримуваним.
+
+1) **Розподіл обов'язків: Кожен клас повинен мати чітко визначену відповідальність і вирішувати лише одну основну задачу. Якщо клас робить занадто багато речей, може бути доцільно розділити його на менші, спеціалізовані класи.
+2) **Інкапсуляція**: Дані та методи повинні бути максимально приховані і доступні лише через визначений інтерфейс. Це дозволяє змінювати внутрішню реалізацію класу, не впливаючи на решту коду.
+3) **Ін'єкція залежностей**: Замість того, щоб створювати залежності безпосередньо всередині класу, ви повинні "впорскувати" їх ззовні. Для більш глибокого розуміння цього принципу ми рекомендуємо прочитати [главу про |dependency-injection:introduction] ін'єкцію залежностей.
diff --git a/nette/uk/troubleshooting.texy b/nette/uk/troubleshooting.texy
index 0819381017..04aa3d523f 100644
--- a/nette/uk/troubleshooting.texy
+++ b/nette/uk/troubleshooting.texy
@@ -18,7 +18,7 @@ Nette не працює, відображається біла сторінка
 ```php
 // Bootstrap.php
 $configurator->setDebugMode('23.75.345.200'); // вашу IP-адресу
-$configurator->enableTracy($appDir . '/log');
+$configurator->enableTracy($rootDir . '/log');
 \Tracy\Debugger::log('hello');
 ```
 
@@ -32,6 +32,13 @@ Tracy повідомить вам, чому вона не може вести ж
 Коли всі сторінки (крім головної) повертають помилку 404, це схоже на проблему конфігурації сервера для [красивих URL-адрес |#How to Configure a Server for Nice URLs?].
 
 
+Як відключити кеш під час розробки? .[#toc-how-to-disable-cache-during-development]
+-----------------------------------------------------------------------------------
+Nette розумний, і вам не потрібно відключати кешування в ньому. Під час розробки він автоматично оновлює кеш щоразу, коли змінюється шаблон або конфігурація контейнера DI. Більше того, режим розробки активується за допомогою автоматичного визначення, тому зазвичай не потрібно нічого налаштовувати, окрім [IP-адреси |application:bootstrap#development-vs-production-mode].
+
+Під час налагодження роутера ми рекомендуємо вимкнути кеш браузера, де можуть зберігатися, наприклад, редиректи: відкрийте Інструменти розробника (Ctrl+Shift+I або Cmd+Option+I) і в панелі "Мережа" поставте галочку, щоб вимкнути кеш.
+
+
 Помилка `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
 -----------------------------------------------------------------------------------------------------------------------
 Ця помилка виникає, якщо ви оновили PHP до версії 8.1, але використовуєте Nette, який не сумісний з нею. Тому рішенням є оновлення Nette до новішої версії за допомогою `composer update`. Nette підтримує PHP 8.1 з версії 3.0. Якщо ви використовуєте старішу версію (ви можете дізнатися це, подивившись у `composer.json`), [оновіть Nette |migrations:en] або залишайтеся з PHP 8.0.
@@ -67,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on
 
 Щоб запустити додаток на хостингу, необхідно в конфігурації хостингу встановити document-root у цю директорію. Або, якщо на хостингу є готова папка для публічного каталогу з іншим ім'ям (наприклад, `web`, `public_html` тощо), просто перейменуйте `www/`.
 
-Рішення **не** полягає в тому, щоб "позбутися" папки `www/` за допомогою правил у файлі `.htaccess` або в роутері. Якщо хостинг не дозволяє вам встановити document-root у підкаталог (тобто створювати каталоги на один рівень вище публічного каталогу), пошукайте інший. В іншому разі ви істотно ризикуєте безпекою. Це схоже на життя у квартирі, де ви не можете закрити вхідні двері, і вони завжди відчинені.
+Рішенням **не є** заборонити доступ до всіх папок, крім `www/`, за допомогою правил у файлі `.htaccess` або в маршрутизаторі. Якщо ваш хостинг не дозволяє встановлювати корінь документа в підкаталозі (тобто створювати каталоги на рівень вище загальнодоступного каталогу), вам слід пошукати інший хостинг. В іншому випадку ви наражаєте себе на значні ризики безпеки. Це все одно, що жити в квартирі, де вхідні двері не можна закрити і вони завжди навстіж відчинені.
 
 
 Як налаштувати сервер для красивих URL? .[#toc-how-to-configure-a-server-for-nice-urls]
diff --git a/php-generator/bg/@home.texy b/php-generator/bg/@home.texy
index 6eda3b9886..80b6ed7027 100644
--- a/php-generator/bg/@home.texy
+++ b/php-generator/bg/@home.texy
@@ -2,11 +2,12 @@
 ********************
 
 <div class=perex>
-- Трябва да генерирате PHP код за класове, функции, PHP файлове и др.
-- Поддържа всички най-нови функции на PHP като енуми, атрибути и др.
+Търсите ли инструмент за генериране на PHP код за класове, функции или цели файлове?
+
+- Поддържа всички най-нови функции на PHP (като enums и др.)
 - Позволява ви лесно да променяте съществуващи класове
-- Изход, съвместим с PSR-12 / PER coding style
-- Високо развита, стабилна и широко използвана библиотека
+- Изход, съвместим със стила на кодиране PSR-12 / PER
+- Зряла, стабилна и широко използвана библиотека
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-За да дефинирате т.нар. вариационни параметри (а също и оператора splat, spread, ellipsis, unpacking или three dots), използвайте `setVariadics()`:
+За да дефинирате т.нар. вариационни параметри (а също и оператора splat, spread, ellipsis, unpacking или three dots), използвайте `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Метод и тяло на функцията .[#toc-method-and-function-body]
-----------------------------------------------------------
+Метод и тяло на функцията .[#toc-method-and-function-bodies]
+------------------------------------------------------------
 
 Тялото може да се предаде на метода `setBody()` наведнъж или последователно (ред по ред) чрез многократно извикване на `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// поставяне на един параметър на един ред, дори ако той има атрибут или е повишен
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// разделител между дясната скоба и типа за връщане на функции и методи
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // или Type::Array;
-$member->setType('array|string'); // или Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // или Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // премахва тип
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Можете също така да подавате параметри на `Literal` и да ги форматирате във валиден PHP код, като използвате [специални заместители |#method-and-function-body-generator]:
+Можете също така да подавате параметри на `Literal` и да ги форматирате във валиден PHP код, като използвате [специални заместители |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Преобразуване на имена на класове .[#toc-class-names-resolving]
 ---------------------------------------------------------------
 
-**Когато класът е част от пространството от имена, той се визуализира по малко по-различен начин**: всички типове (т.е. подсказките за тип, типовете за връщане, името на родителския клас,
-имплементирани интерфейси, използвани черти и атрибути) се решават автоматично* (освен ако не го изключите, вижте по-долу).
-Това означава, че трябва да **използвате пълни имена на класове** в дефинициите и те ще бъдат заменени с псевдоними (в съответствие с декларациите за употреба) или с напълно квалифицирани имена в получения код:
+**Когато един клас е част от пространство от имена, той се визуализира по малко по-различен начин:** всички типове (напр. подсказки за тип, типове връщане, име на родителския клас, имплементирани интерфейси, използвани черти и атрибути) се решават автоматично (освен ако не го изключите, вижте по-долу).
+Това означава, че трябва да използвате **пълно квалифицирани имена на класове** в дефинициите и те ще бъдат заменени с псевдоними (въз основа на клаузи за използване) или напълно квалифицирани имена в получения код:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Забележете:** Във файловете не може да се добавя допълнителен код извън функциите и класовете.
+
 
 Генериране според съществуващите .[#toc-generating-according-to-existing-ones]
 ------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ $file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
 Ако трябва да манипулирате глобален код във файлове или отделни оператори в тялото на метод, по-добре е да използвате директно библиотеката `nikic/php-parser`.
 
 
+Манипулатор на класове .[#toc-class-manipulator]
+------------------------------------------------
+
+Класът [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] предоставя инструменти за манипулиране на класове.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Методът `inheritMethod()` копира метод от родителски клас или имплементиран интерфейс във вашия клас. Това ви позволява да замените метода или да разширите неговата сигнатура:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Методът `inheritProperty()` копира свойство от родителски клас във вашия клас. Това е полезно, когато искате да имате същото свойство във вашия клас, но евентуално с различна стойност по подразбиране:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Методът `implementInterface()` автоматично имплементира всички методи от дадения интерфейс във вашия клас:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Сега вашият клас имплементира SomeInterface и включва всички негови методи
+```
+
+
 Дъмпер за променливи .[#toc-variables-dumper]
 ---------------------------------------------
 
diff --git a/php-generator/cs/@home.texy b/php-generator/cs/@home.texy
index a4562005f3..241b06e39e 100644
--- a/php-generator/cs/@home.texy
+++ b/php-generator/cs/@home.texy
@@ -1,11 +1,12 @@
 Generátor PHP kódu
 ******************
 
-<div class=perex>
-- Potřebujete generovat kód tříd, funkcí, PHP souborů atd?
+<div class="perex">
+Hledáte nástroj pro generování PHP kódu tříd, funkcí či kompletních souborů?
+
 - Umí všechny nejnovější vychytávky v PHP (jako enumy atd.)
-- Dovolí vám snadno modifikovat existující třídy
-- Výstup vyhovující PSR-12 / PER coding style
+- Umožní vám snadno modifikovat existující třídy
+- Výstupní kód je v souladu s PSR-12 / PER coding style
 - Zralá, stabilní a široce používaná knihovna
 </div>
 
@@ -361,7 +362,7 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Pro definici tzv. variadics parametrů (nebo též splat operátor) slouží `setVariadics()`:
+Pro definici tzv. variadics parametrů (nebo též splat operátor) slouží `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// umístěte jeden parametr na jeden řádek, i když má atribut nebo je podporován
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// oddělovač mezi pravou závorkou a návratovým typem funkcí a metod
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Každý typ nebo union/intersection typ lze předat jako řetězec, můžete tak
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // nebo Type::Array;
-$member->setType('array|string'); // nebo Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // nebo Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // odstraní typ
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Můžete také předat parametry do `Literal` a nechat je zformátovat do platného kódu PHP pomocí [zástupných znaků|#Generování těl metod a funkcí]:
+Můžete také předat parametry do `Literal` a nechat je zformátovat do platného kódu PHP pomocí [zástupných znaků|#tela-metod-a-funkci]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,8 +683,7 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Překlady názvů tříd
 -------------------
 
-**Když je třída součástí jmenného prostoru, je vykreslena mírně odlišně:** všechny typy (například typehinty, návratové typy, název rodičovské třídy,
-implementovaná rozhraní, použité vlastnosti a atributy) jsou automaticky *překládány* (pokud to nevypnete, viz níže).
+**Když je třída součástí jmenného prostoru, je vykreslena mírně odlišně:** všechny typy (například typehinty, návratové typy, název rodičovské třídy, implementovaná rozhraní, použité vlastnosti a atributy) jsou automaticky *překládány* (pokud to nevypnete, viz níže).
 To znamená, že musíte v definicích **používat úplné názvy tříd** a ty budou nahrazeny za aliasy (podle klauzulí use) nebo za plně kvalifikovaná jména ve výsledném kódu:
 
 ```php
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Upozornění:** Do souborů není možné přidávat žádný další kód mimo funkce a třídy.
+
 
 Generování podle existujících
 -----------------------------
@@ -838,6 +843,38 @@ Vyžaduje se, aby byl nainstalován `nikic/php-parser`.
 Pokud potřebujete manipulovat s globálním kódem v souborech nebo s jednotlivými příkazy v tělech metod, je lepší použít přímo knihovnu `nikic/php-parser`.
 
 
+Class Manipulator
+-----------------
+
+Třída [ClassManipulator|api:Nette\PhpGenerator\ClassManipulator] poskytuje nástroje pro manipulaci s třídami.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Metoda `inheritMethod()` zkopíruje metodu z rodičovské třídy nebo implementovaného rozhraní do vaší třídy. To vám umožní přepsat metodu nebo rozšířit její signaturu:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+  ```
+
+Metoda `inheritProperty()` zkopíruje vlastnost z rodičovské třídy do vaší třídy. Je to užitečné, když chcete ve své třídě mít stejnou vlastnost, ale třeba s jinou výchozí hodnotou:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Metoda `implementInterface()` automaticky implementuje všechny metody z daného rozhraní ve vaší třídě:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Nyní vaše třída implementuje SomeInterface a obsahuje všechny jeho metody
+```
+
+
 Výpis proměnných
 ----------------
 
@@ -857,5 +894,4 @@ Tabulka kompatibility
 
 PhpGenerator 4.0 a 4.1 jsou kompatibilní s PHP 8.0 až 8.3.
 
-
 {{leftbar: nette:@menu-topics}}
diff --git a/php-generator/de/@home.texy b/php-generator/de/@home.texy
index 25ef0fccca..de0662647b 100644
--- a/php-generator/de/@home.texy
+++ b/php-generator/de/@home.texy
@@ -2,11 +2,12 @@ PHP-Code-Generator
 ******************
 
 <div class=perex>
-- Müssen Sie PHP-Code für Klassen, Funktionen, PHP-Dateien usw. generieren?
-- Unterstützt alle aktuellen PHP-Funktionen wie Enums, Attribute, etc.
+Suchen Sie ein Tool, um PHP-Code für Klassen, Funktionen oder komplette Dateien zu generieren?
+
+- Unterstützt alle aktuellen PHP-Funktionen (wie Enums, etc.)
 - Ermöglicht die einfache Änderung bestehender Klassen
-- PSR-12-konforme Ausgabe
-- Hochgradig ausgereifte, stabile und weit verbreitete Bibliothek
+- Ausgabe in Übereinstimmung mit PSR-12 / PER-Kodierung
+- Ausgereifte, stabile und weit verbreitete Bibliothek
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Um die sogenannten Variadics-Parameter (oder auch den Splat-, Spread-, Ellipsis-, Unpacking- oder Three Dots-Operator) zu definieren, verwenden Sie `setVariadics()`:
+Um die sogenannten Variadics-Parameter (oder auch den Splat-, Spread-, Ellipsis-, Unpacking- oder Three Dots-Operator) zu definieren, verwenden Sie `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Methode und Funktionskörper .[#toc-method-and-function-body]
-------------------------------------------------------------
+Methode und Funktionskörper .[#toc-method-and-function-bodies]
+--------------------------------------------------------------
 
 Der Körper kann der Methode `setBody()` auf einmal oder sequentiell (Zeile für Zeile) durch wiederholten Aufruf von `addBody()` übergeben werden:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// Platzierung eines Parameters in einer Zeile, auch wenn er ein Attribut hat oder promotet wird
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// Trennzeichen zwischen der rechten Klammer und dem Rückgabetyp von Funktionen und Methoden
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Jeder Typ oder Gewerkschafts-/Schnittstellentyp kann als String übergeben werde
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // oder Type::Array;
-$member->setType('array|string'); // oder Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // oder Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // Entfernt Typ
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Sie können auch Parameter an `Literal` übergeben und diese mit Hilfe [spezieller Platzhalter |#method-and-function-body-generator] in gültigen PHP-Code umwandeln lassen:
+Sie können auch Parameter an `Literal` übergeben und diese mit Hilfe [spezieller Platzhalter |#method-and-function-bodies] in gültigen PHP-Code umwandeln lassen:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Auflösen von Klassennamen .[#toc-class-names-resolving]
 -------------------------------------------------------
 
-**Wenn die Klasse Teil des Namespaces ist, wird sie etwas anders dargestellt**: alle Typen (d.h. Typ-Hinweise, Rückgabetypen, Name der Elternklasse,
-implementierte Schnittstellen, verwendete Traits und Attribute) werden automatisch *aufgelöst* (es sei denn, Sie schalten dies aus, siehe unten).
-Das bedeutet, dass Sie **vollständige Klassennamen** in Definitionen verwenden müssen und diese im resultierenden Code durch Aliasnamen (entsprechend den Verwendungsbestimmungen) oder voll qualifizierte Namen ersetzt werden:
+**Wenn eine Klasse Teil eines Namensraums ist, wird sie etwas anders dargestellt:** Alle Typen (z.B. Typ-Hinweise, Rückgabetypen, Name der Elternklasse, implementierte Schnittstellen, verwendete Traits und Attribute) werden automatisch *aufgelöst* (es sei denn, Sie schalten dies aus, siehe unten).
+Das bedeutet, dass Sie **voll qualifizierte Klassennamen** in Definitionen verwenden müssen, und diese werden im resultierenden Code durch Aliase (basierend auf Verwendungsklauseln) oder voll qualifizierte Namen ersetzt:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Bitte beachten Sie:** Außer den Funktionen und Klassen kann den Dateien kein weiterer Code hinzugefügt werden.
+
 
 Generierung nach vorhandenen Elementen .[#toc-generating-according-to-existing-ones]
 ------------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Dazu muss `nikic/php-parser` installiert sein.
 Wenn Sie globalen Code in Dateien oder einzelne Anweisungen in Methodenkörpern manipulieren müssen, ist es besser, die Bibliothek `nikic/php-parser` direkt zu verwenden.
 
 
+Klasse Manipulator .[#toc-class-manipulator]
+--------------------------------------------
+
+Die Klasse [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] bietet Werkzeuge zur Manipulation von Klassen.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Die Methode `inheritMethod()` kopiert eine Methode aus einer übergeordneten Klasse oder einer implementierten Schnittstelle in Ihre Klasse. Auf diese Weise können Sie die Methode außer Kraft setzen oder ihre Signatur erweitern:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Die Methode `inheritProperty()` kopiert eine Eigenschaft aus einer übergeordneten Klasse in Ihre Klasse. Dies ist nützlich, wenn Sie die gleiche Eigenschaft in Ihrer Klasse haben möchten, aber möglicherweise mit einem anderen Standardwert:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Die Methode `implementInterface()` implementiert automatisch alle Methoden der angegebenen Schnittstelle in Ihrer Klasse:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Ihre Klasse implementiert nun SomeInterface und enthält alle seine Methoden
+```
+
+
 Variablen-Dumper .[#toc-variables-dumper]
 -----------------------------------------
 
diff --git a/php-generator/el/@home.texy b/php-generator/el/@home.texy
index 14df08af86..ca87244ab6 100644
--- a/php-generator/el/@home.texy
+++ b/php-generator/el/@home.texy
@@ -2,11 +2,12 @@
 ********************
 
 <div class=perex>
-- Χρειάζεται να δημιουργήσετε κώδικα PHP για κλάσεις, συναρτήσεις, αρχεία PHP κ.λπ.
-- Υποστηρίζει όλα τα τελευταία χαρακτηριστικά της PHP, όπως enums, attributes κ.λπ.
+Ψάχνετε ένα εργαλείο για τη δημιουργία κώδικα PHP για κλάσεις, συναρτήσεις ή πλήρη αρχεία;
+
+- Υποστηρίζει όλα τα τελευταία χαρακτηριστικά της PHP (όπως enums κ.λπ.)
 - Σας επιτρέπει να τροποποιείτε εύκολα τις υπάρχουσες κλάσεις
-- Έξοδος συμβατή με το PSR-12 / PER coding style
-- Εξαιρετικά ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη
+- Έξοδος συμβατή με το στυλ κωδικοποίησης PSR-12 / PER
+- Ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Για να ορίσετε τις λεγόμενες παραμέτρους variadics (ή επίσης τον τελεστή splat, spread, ellipsis, unpacking ή three dots), χρησιμοποιήστε `setVariadics()`:
+Για να ορίσετε τις λεγόμενες παραμέτρους variadics (ή επίσης τον τελεστή splat, spread, ellipsis, unpacking ή three dots), χρησιμοποιήστε `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Σώμα μεθόδου και συνάρτησης .[#toc-method-and-function-body]
-------------------------------------------------------------
+Σώμα μεθόδου και συνάρτησης .[#toc-method-and-function-bodies]
+--------------------------------------------------------------
 
 Το σώμα μπορεί να περάσει στη μέθοδο `setBody()` αμέσως ή διαδοχικά (γραμμή προς γραμμή) καλώντας επανειλημμένα τη μέθοδο `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// τοποθέτηση μιας παραμέτρου σε μια γραμμή, ακόμη και αν έχει ένα χαρακτηριστικό ή αν προωθείται
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// διαχωριστικό μεταξύ της δεξιάς παρένθεσης και του τύπου επιστροφής των συναρτήσεων και των μεθόδων
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // ή Type::Array,
-$member->setType('array|string'); // ή Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // ή Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // αφαιρεί τον τύπο
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Μπορείτε επίσης να περάσετε παραμέτρους στη διεύθυνση `Literal` και να τις μορφοποιήσετε σε έγκυρο κώδικα PHP χρησιμοποιώντας [ειδικούς συμπαραστάτες |#method-and-function-body-generator]:
+Μπορείτε επίσης να περάσετε παραμέτρους στη διεύθυνση `Literal` και να τις μορφοποιήσετε σε έγκυρο κώδικα PHP χρησιμοποιώντας [ειδικούς συμπαραστάτες |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Επίλυση ονομάτων κλάσεων .[#toc-class-names-resolving]
 ------------------------------------------------------
 
-**Όταν η κλάση είναι μέρος του χώρου ονομάτων, αποδίδεται ελαφρώς διαφορετικά**: όλοι οι τύποι (δηλαδή οι υποδείξεις τύπου, οι τύποι επιστροφής, το όνομα της γονικής κλάσης,
-υλοποιημένες διεπαφές, χρησιμοποιούμενα γνωρίσματα και χαρακτηριστικά) *επιλύονται* αυτόματα (εκτός αν το απενεργοποιήσετε, βλ. παρακάτω).
-Αυτό σημαίνει ότι πρέπει να **χρησιμοποιείτε πλήρη ονόματα κλάσεων** στους ορισμούς και αυτά θα αντικατασταθούν με ψευδώνυμα (σύμφωνα με τις δηλώσεις χρήσης) ή πλήρως προσδιορισμένα ονόματα στον κώδικα που θα προκύψει:
+**Όταν μια κλάση είναι μέρος ενός χώρου ονομάτων, αποδίδεται ελαφρώς διαφορετικά:** όλοι οι τύποι (π.χ. υποδείξεις τύπου, τύποι επιστροφής, όνομα γονικής κλάσης, υλοποιημένες διασυνδέσεις, χρησιμοποιούμενα γνωρίσματα και χαρακτηριστικά) *επιλύονται* αυτόματα (εκτός αν το απενεργοποιήσετε, δείτε παρακάτω).
+Αυτό σημαίνει ότι πρέπει να χρησιμοποιείτε **πλήρως προσδιορισμένα ονόματα κλάσεων** στους ορισμούς, και θα αντικατασταθούν με ψευδώνυμα (με βάση τις ρήτρες χρήσης) ή πλήρως προσδιορισμένα ονόματα στον κώδικα που θα προκύψει:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Παρακαλώ σημειώστε:** Δεν μπορεί να προστεθεί πρόσθετος κώδικας στα αρχεία εκτός των συναρτήσεων και των κλάσεων.
+
 
 Δημιουργία σύμφωνα με τις υπάρχουσες .[#toc-generating-according-to-existing-ones]
 ----------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ $file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
 Αν πρέπει να χειριστείτε συνολικό κώδικα σε αρχεία ή μεμονωμένες εντολές σε σώματα μεθόδων, είναι προτιμότερο να χρησιμοποιήσετε απευθείας τη βιβλιοθήκη `nikic/php-parser`.
 
 
+Χειριστής τάξης .[#toc-class-manipulator]
+-----------------------------------------
+
+Η κλάση [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] παρέχει εργαλεία για το χειρισμό κλάσεων.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Η μέθοδος `inheritMethod()` αντιγράφει μια μέθοδο από μια γονική κλάση ή μια διεπαφή που έχει υλοποιηθεί στην κλάση σας. Αυτό σας επιτρέπει να υπερεκτελείτε τη μέθοδο ή να επεκτείνετε την υπογραφή της:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Η μέθοδος `inheritProperty()` αντιγράφει μια ιδιότητα από μια γονική κλάση στην κλάση σας. Αυτό είναι χρήσιμο όταν θέλετε να έχετε την ίδια ιδιότητα στην κλάση σας, αλλά ενδεχομένως με διαφορετική προεπιλεγμένη τιμή:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Η μέθοδος `implementInterface()` υλοποιεί αυτόματα όλες τις μεθόδους της δεδομένης διεπαφής στην κλάση σας:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Τώρα η κλάση σας υλοποιεί το SomeInterface και περιλαμβάνει όλες τις μεθόδους του
+```
+
+
 Μεταβλητές Dumper .[#toc-variables-dumper]
 ------------------------------------------
 
diff --git a/php-generator/en/@home.texy b/php-generator/en/@home.texy
index 97599942ed..ccd879bf4a 100644
--- a/php-generator/en/@home.texy
+++ b/php-generator/en/@home.texy
@@ -2,18 +2,19 @@ PHP Code Generator
 ******************
 
 <div class=perex>
-- Need to generate PHP code for classes, functions, PHP files, etc.?
-- Supports all the latest PHP features like enums, attributes, etc.
+Are you looking for a tool to generate PHP code for classes, functions, or complete files?
+
+- Supports all the latest PHP features (like enums, etc.)
 - Allows you to easily modify existing classes
-- PSR-12 / PER coding style compliant output
-- Highly mature, stable, and widely used library
+- Output compliant with PSR-12 / PER coding style
+- Mature, stable, and widely used library
 </div>
 
 
 Installation
 ------------
 
-Download and install the package using [Composer|best-practices:composer]:
+Download and install the library using the [Composer|best-practices:composer] tool:
 
 ```shell
 composer require nette/php-generator
@@ -25,7 +26,7 @@ For PHP compatibility, see the [table |#Compatibility Table].
 Classes
 -------
 
-Let's start with a straightforward example of generating class using [ClassType |api:Nette\PhpGenerator\ClassType]:
+Let's start with an example of creating a class using [ClassType |api:Nette\PhpGenerator\ClassType]:
 
 ```php
 $class = new Nette\PhpGenerator\ClassType('Demo');
@@ -34,18 +35,18 @@ $class
 	->setFinal()
 	->setExtends(ParentClass::class)
 	->addImplement(Countable::class)
-	->addComment("Description of class.\nSecond line\n")
+	->addComment("Class description.\nSecond line\n")
 	->addComment('@property-read Nette\Forms\Form $form');
 
-// to generate PHP code simply cast to string or use echo:
+// generate code simply by typecasting to string or using echo:
 echo $class;
 ```
 
-It will render this result:
+This will return:
 
 ```php
 /**
- * Description of class.
+ * Class description
  * Second line
  *
  * @property-read Nette\Forms\Form $form
@@ -55,18 +56,18 @@ final class Demo extends ParentClass implements Countable
 }
 ```
 
-We can also use a printer to generate the code, which, unlike `echo $class`, we will be able to [further configure |#Printers and PSR compliance]:
+To generate the code, you can also use a so-called printer, which, unlike `echo $class`, can be [further configured |#Printer and PSR compliance]:
 
 ```php
 $printer = new Nette\PhpGenerator\Printer;
 echo $printer->printClass($class);
 ```
 
-We can add constants (class [Constant |api:Nette\PhpGenerator\Constant]) and properties (class [Property |api:Nette\PhpGenerator\Property]):
+You can add constants (class [Constant |api:Nette\PhpGenerator\Constant]) and properties (class [Property |api:Nette\PhpGenerator\Property]):
 
 ```php
 $class->addConstant('ID', 123)
-	->setProtected() // constant visiblity
+	->setProtected() // constant visibility
 	->setType('int')
 	->setFinal();
 
@@ -77,10 +78,10 @@ $class->addProperty('items', [1, 2, 3])
 
 $class->addProperty('list')
 	->setType('?array')
-	->setInitialized(); // prints '= null'
+	->setInitialized(); // outputs '= null'
 ```
 
-It generates:
+This will generate:
 
 ```php
 final protected const int ID = 123;
@@ -91,14 +92,14 @@ private static $items = [1, 2, 3];
 public ?array $list = null;
 ```
 
-And we can add [methods|#Method and Function Signature]:
+And you can add [methods|#Method and function signatures]:
 
 ```php
 $method = $class->addMethod('count')
 	->addComment('Count it.')
 	->setFinal()
 	->setProtected()
-	->setReturnType('?int') // method return type
+	->setReturnType('?int') // return types for methods
 	->setBody('return count($items ?: $this->items);');
 
 $method->addParameter('items', []) // $items = []
@@ -106,7 +107,7 @@ $method->addParameter('items', []) // $items = []
 	->setType('array');        // array &$items = []
 ```
 
-It results in:
+The result is:
 
 ```php
 /**
@@ -118,7 +119,7 @@ final protected function count(array &$items = []): ?int
 }
 ```
 
-Promoted parameters introduced by PHP 8.0 can be passed to the constructor:
+Promoted parameters introduced in PHP 8.0 can be passed to the constructor:
 
 ```php
 $method = $class->addMethod('__construct');
@@ -127,7 +128,7 @@ $method->addPromotedParameter('args', [])
 	->setPrivate();
 ```
 
-It results in:
+The result is:
 
 ```php
 public function __construct(
@@ -137,15 +138,15 @@ public function __construct(
 }
 ```
 
-Readonly properties and classes can be marked via `setReadOnly()`.
+Readonly properties and classes be marked using the `setReadOnly()` function.
 
 ------
 
-If the added property, constant, method or parameter already exist, it throws exception.
+If an added property, constant, method, or parameter already exists, an exception is thrown.
 
-Members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()` or `removeParameter()`.
+Class members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()`, or `removeParameter()`.
 
-You can also add existing `Method`, `Property` or `Constant` objects to the class:
+You can also add existing `Method`, `Property`, or `Constant` objects to the class:
 
 ```php
 $method = new Nette\PhpGenerator\Method('getHandle');
@@ -158,7 +159,7 @@ $class = (new Nette\PhpGenerator\ClassType('Demo'))
 	->addMember($const);
 ```
 
-You can clone existing methods, properties and constants with a different name using `cloneWithName()`:
+You can also clone existing methods, properties, and constants under a different name using `cloneWithName()`:
 
 ```php
 $methodCount = $class->getMethod('count');
@@ -167,8 +168,8 @@ $class->addMember($methodRecount);
 ```
 
 
-Interface or Trait
-------------------
+Interfaces or Traits
+--------------------
 
 You can create interfaces and traits (classes [InterfaceType |api:Nette\PhpGenerator\InterfaceType] and [TraitType |api:Nette\PhpGenerator\TraitType]):
 
@@ -177,7 +178,7 @@ $interface = new Nette\PhpGenerator\InterfaceType('MyInterface');
 $trait = new Nette\PhpGenerator\TraitType('MyTrait');
 ```
 
-Using traits:
+Using a trait:
 
 ```php
 $class = new Nette\PhpGenerator\ClassType('Demo');
@@ -188,7 +189,7 @@ $class->addTrait('MyTrait')
 echo $class;
 ```
 
-Result:
+The result is:
 
 ```php
 class Demo
@@ -205,7 +206,7 @@ class Demo
 Enums
 -----
 
-You can easily create the enums that PHP 8.1 brings (class [EnumType |api:Nette\PhpGenerator\EnumType]):
+You can easily create enums introduced in PHP 8.1 like this (class [EnumType |api:Nette\PhpGenerator\EnumType]):
 
 ```php
 $enum = new Nette\PhpGenerator\EnumType('Suit');
@@ -217,7 +218,7 @@ $enum->addCase('Spades');
 echo $enum;
 ```
 
-Result:
+The result is:
 
 ```php
 enum Suit
@@ -229,20 +230,20 @@ enum Suit
 }
 ```
 
-You can also define scalar equivalents for cases to create a backed enum:
+You can also define scalar equivalents and create a "backed" enum:
 
 ```php
 $enum->addCase('Clubs', '♣');
 $enum->addCase('Diamonds', '♦');
 ```
 
-It is possible to add a comment or [#attributes] to each case using `addComment()` or `addAttribute()`.
+For each *case*, you can add a comment or [#attributes] using `addComment()` or `addAttribute()`.
 
 
-Anonymous Class
----------------
+Anonymous Classes
+-----------------
 
-Give `null` as the name and you have an anonymous class:
+Pass `null` as the name, and you have an anonymous class:
 
 ```php
 $class = new Nette\PhpGenerator\ClassType(null);
@@ -252,7 +253,7 @@ $class->addMethod('__construct')
 echo '$obj = new class ($val) ' . $class . ';';
 ```
 
-Result:
+The result is:
 
 ```php
 $obj = new class ($val) {
@@ -264,10 +265,10 @@ $obj = new class ($val) {
 ```
 
 
-Global Function
----------------
+Global Functions
+----------------
 
-Code of functions will generate class [GlobalFunction |api:Nette\PhpGenerator\GlobalFunction]:
+The code for functions is generated by the class [GlobalFunction |api:Nette\PhpGenerator\GlobalFunction]:
 
 ```php
 $function = new Nette\PhpGenerator\GlobalFunction('foo');
@@ -276,11 +277,11 @@ $function->addParameter('a');
 $function->addParameter('b');
 echo $function;
 
-// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER
+// or use the PsrPrinter for output compliant with PSR-2 / PSR-12 / PER
 // echo (new Nette\PhpGenerator\PsrPrinter)->printFunction($function);
 ```
 
-Result:
+The result is:
 
 ```php
 function foo($a, $b)
@@ -290,10 +291,10 @@ function foo($a, $b)
 ```
 
 
-Closure
--------
+Anonymous Functions
+-------------------
 
-Code of closures will generate class [Closure |api:Nette\PhpGenerator\Closure]:
+The code for anonymous functions is generated by the class [Closure |api:Nette\PhpGenerator\Closure]:
 
 ```php
 $closure = new Nette\PhpGenerator\Closure;
@@ -304,11 +305,11 @@ $closure->addUse('c')
 	->setReference();
 echo $closure;
 
-// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER
+// or use the PsrPrinter for output compliant with PSR-2 / PSR-12 / PER
 // echo (new Nette\PhpGenerator\PsrPrinter)->printClosure($closure);
 ```
 
-Result:
+The result is:
 
 ```php
 function ($a, $b) use (&$c) {
@@ -317,10 +318,10 @@ function ($a, $b) use (&$c) {
 ```
 
 
-Arrow Function
---------------
+Short Arrow Functions
+---------------------
 
-You can also print closure as arrow function using printer:
+You can also output a short anonymous function using the printer:
 
 ```php
 $closure = new Nette\PhpGenerator\Closure;
@@ -331,17 +332,17 @@ $closure->addParameter('b');
 echo (new Nette\PhpGenerator\Printer)->printArrowFunction($closure);
 ```
 
-Result:
+The result is:
 
 ```php
 fn($a, $b) => $a + $b
 ```
 
 
-Method and Function Signature
------------------------------
+Method and Function Signatures
+------------------------------
 
-Methods are represented by the class [Method |api:Nette\PhpGenerator\Method]. You can set visibility, return value, add comments, [attributes|#Attributes] etc:
+Methods are represented by the class [Method |api:Nette\PhpGenerator\Method]. You can set visibility, return value, add comments, [attributes|#Attributes], etc.:
 
 ```php
 $method = $class->addMethod('count')
@@ -351,25 +352,25 @@ $method = $class->addMethod('count')
 	->setReturnType('?int');
 ```
 
-Each parameter is represented by a class [Parameter |api:Nette\PhpGenerator\Parameter]. Again, you can set every conceivable property:
+Individual parameters are represented by the class [Parameter |api:Nette\PhpGenerator\Parameter]. Again, you can set all conceivable properties:
 
 ```php
 $method->addParameter('items', []) // $items = []
-	->setReference() // &$items = []
-	->setType('array'); // array &$items = []
+	->setReference()           // &$items = []
+	->setType('array');        // array &$items = []
 
 // function count(&$items = [])
 ```
 
-To define the so-called variadics parameters (or also the splat, spread, ellipsis, unpacking or three dots operator), use `setVariadics()`:
+To define the so-called variadics parameters (or also the splat, spread, ellipsis, unpacking or three dots operator), use `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
-Generates:
+This generates:
 
 ```php
 function count(...$items)
@@ -378,10 +379,10 @@ function count(...$items)
 ```
 
 
-Method and Function Body
-------------------------
+Method and Function Bodies
+--------------------------
 
-The body can be passed to the `setBody()` method at once or sequentially (line by line) by repeatedly calling `addBody()`:
+The body can be passed all at once to the `setBody()` method or gradually (line by line) by repeatedly calling `addBody()`:
 
 ```php
 $function = new Nette\PhpGenerator\GlobalFunction('foo');
@@ -390,7 +391,7 @@ $function->addBody('return $a;');
 echo $function;
 ```
 
-Result
+The result is:
 
 ```php
 function foo()
@@ -400,7 +401,7 @@ function foo()
 }
 ```
 
-You can use special placeholders for handy way to inject variables.
+You can use special placeholders for easy variable insertion.
 
 Simple placeholders `?`
 
@@ -412,7 +413,7 @@ $function->addBody('return substr(?, ?);', [$str, $num]);
 echo $function;
 ```
 
-Result:
+The result is:
 
 ```php
 function foo()
@@ -421,7 +422,7 @@ function foo()
 }
 ```
 
-Variadic placeholder `...?`
+Placeholder for variadic `...?`
 
 ```php
 $items = [1, 2, 3];
@@ -430,7 +431,7 @@ $function->setBody('myfunc(...?);', [$items]);
 echo $function;
 ```
 
-Result:
+The result is:
 
 ```php
 function foo()
@@ -439,7 +440,7 @@ function foo()
 }
 ```
 
-You can also use PHP 8 named parameters using placeholder `...?:`
+You can also use named parameters for PHP 8 with `...?:`
 
 ```php
 $items = ['foo' => 1, 'bar' => true];
@@ -448,7 +449,7 @@ $function->setBody('myfunc(...?:);', [$items]);
 // myfunc(foo: 1, bar: true);
 ```
 
-Escape placeholder using slash `\?`
+The placeholder is escaped with a backslash `\?`
 
 ```php
 $num = 3;
@@ -458,7 +459,7 @@ $function->addBody('return $a \? 10 : ?;', [$num]);
 echo $function;
 ```
 
-Result:
+The result is:
 
 ```php
 function foo($a)
@@ -468,10 +469,10 @@ function foo($a)
 ```
 
 
-Printers and PSR Compliance
----------------------------
+Printer and PSR Compliance
+--------------------------
 
-The [Printer |api:Nette\PhpGenerator\Printer] class is used to generate PHP code:
+The [Printer |api:Nette\PhpGenerator\Printer] class is used for generating PHP code:
 
 ```php
 $class = new Nette\PhpGenerator\ClassType('Demo');
@@ -481,16 +482,16 @@ $printer = new Nette\PhpGenerator\Printer;
 echo $printer->printClass($class); // same as: echo $class
 ```
 
-It can generate code for all other elements, offering methods such as `printFunction()`, `printNamespace()`, etc.
+It can generate code for all other elements, offering methods like `printFunction()`, `printNamespace()`, etc.
 
-Additionally, the `PsrPrinter` class is available, whose output is in compliance with the PSR-2 / PSR-12 / PER coding style:
+There's also the `PsrPrinter` class, which outputs in accordance with PSR-2 / PSR-12 / PER coding style:
 
 ```php
 $printer = new Nette\PhpGenerator\PsrPrinter;
 echo $printer->printClass($class);
 ```
 
-Need to fine-tune behavior to your needs? Create your own printer by inheriting from the `Printer` class. You can reconfigure these variables:
+Need custom behavior? Create your own version by inheriting the `Printer` class. You can reconfigure these variables:
 
 ```php
 class MyPrinter extends Nette\PhpGenerator\Printer
@@ -503,45 +504,48 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public int $linesBetweenProperties = 0;
 	// number of blank lines between methods
 	public int $linesBetweenMethods = 2;
-	// number of blank lines between groups of use statements for classes, functions, and constants
+	// number of blank lines between 'use statements' groups for classes, functions, and constants
 	public int $linesBetweenUseTypes = 0;
-	// position of the opening brace for functions and methods
+	// position of the opening curly brace for functions and methods
 	public bool $bracesOnNextLine = true;
-	// place one parameter in one line, even if it has an attribute or is promoted
+	// place one parameter on one line, even if it has an attribute or is supported
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// separator between the right parenthesis and return type of functions and methods
 	public string $returnTypeColon = ': ';
 }
 ```
 
-How and why exactly does the standard `Printer` and `PsrPrinter` differ? Why isn't there just one printer, the `PsrPrinter`, in the package?
+How and why does the standard `Printer` differ from `PsrPrinter`? Why isn't there just one printer, the `PsrPrinter`, in the package?
 
-The standard `Printer` formats the code as we do it in all of Nette. Since Nette was created much earlier than PSR, and also because PSR for many years did not deliver standards in time, but sometimes even with several years of delay from the introduction of a new feature in PHP, this resulted in a few minor differences in the [coding standard |contributing:coding-standard].
-The bigger difference is just the use of tabs instead of spaces. We know that by using tabs in our projects we allow for width adjustment, which is [essential for people with visual impairments |contributing:coding-standard#Tabs Instead of Spaces].
-An example of a minor difference is the placement of the curly brace on a separate line for functions and methods and always. We see the PSR recommendation as illogical and [leading to a decrease in code clarity |contributing:coding-standard#Wrapping and Braces].
+The standard `Printer` formats the code as we do throughout Nette. Since Nette was established much earlier than PSR, and also because PSR took years to deliver standards on time, sometimes even several years after introducing a new feature in PHP, it resulted in a [coding standard |contributing:coding-standard] that differs in a few minor aspects.
+The major difference is the use of tabs instead of spaces. We know that by using tabs in our projects, we allow for width customization, which is essential for [people with visual impairments |contributing:coding-standard#tabs-instead-of-spaces].
+An example of a minor difference is placing the curly brace on a separate line for functions and methods, always. The PSR recommendation seems illogical to us and leads to [reduced code clarity |contributing:coding-standard#Wrapping and Braces].
 
 
 Types
 -----
 
-Each type or union/intersection type can be passed as a string, you can also use predefined constants for native types:
+Every type or union/intersection type can be passed as a string; you can also use predefined constants for native types:
 
 ```php
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // or Type::Array;
-$member->setType('array|string'); // or Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class)
-$member->setType(null); // removes type
+$member->setType(null); // removes the type
 ```
 
-The same applies to the method `setReturnType()`.
+The same applies to the `setReturnType()` method.
 
 
 Literals
 --------
 
-With `Literal` you can pass arbitrary PHP code to, for example, default property or parameter values etc:
+Using `Literal`, you can pass any PHP code, for example, for default property values or parameters, etc:
 
 ```php
 use Nette\PhpGenerator\Literal;
@@ -569,25 +573,25 @@ class Demo
 }
 ```
 
-You can also pass parameters to `Literal` and have it formatted into valid PHP code using [special placeholders|#method-and-function-body-generator]:
+You can also pass parameters to `Literal` and have them formatted into valid PHP code using [placeholders|#Method and function bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
-// generates, for example: substr('hello', 5);
+// generates for example: substr('hello', 5);
 ```
 
-The literal representing the creation of a new object is easily generated by the `new` method:
+A literal representing the creation of a new object can easily be generated using the `new` method:
 
 ```php
 Literal::new(Demo::class, [$a, 'foo' => $b]);
-// generates, for example: new Demo(10, foo: 20)
+// generates for example: new Demo(10, foo: 20)
 ```
 
 
 Attributes
 ----------
 
-You can add PHP 8 attributes to all classes, methods, properties, constants, enum cases, functions, closures and parameters. [#Literals] can also be used as parameter values.
+With PHP 8, you can add attributes to all classes, methods, properties, constants, enum cases, functions, closures, and parameters. You can also use [#literals] as parameter values.
 
 ```php
 $class = new Nette\PhpGenerator\ClassType('Demo');
@@ -633,7 +637,7 @@ class Demo
 Namespace
 ---------
 
-Classes, traits, interfaces and enums (hereinafter classes) can be grouped into namespaces ([PhpNamespace |api:Nette\PhpGenerator\PhpNamespace]):
+Classes, traits, interfaces, and enums (hereafter referred to as classes) can be grouped into namespaces represented by the [PhpNamespace |api:Nette\PhpGenerator\PhpNamespace] class:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -648,9 +652,9 @@ $class = new Nette\PhpGenerator\ClassType('Task');
 $namespace->add($class);
 ```
 
-If the class already exists, it throws exception.
+If the class already exists, an exception is thrown.
 
-You can define use-statements:
+You can define use clauses:
 
 ```php
 // use Http\Request;
@@ -661,14 +665,14 @@ $namespace->addUse(Http\Request::class, 'HttpReq');
 $namespace->addUseFunction('iter\range');
 ```
 
-To simplify a fully qualified class, function or constant name according to the defined aliases, use the `simplifyName` method:
+To simplify a fully qualified class, function, or constant name based on defined aliases, use the `simplifyName` method:
 
 ```php
-echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is current namespace
-echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', because of the defined use-statement
+echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is the current namespace
+echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', due to the defined use-statement
 ```
 
-Conversely, you can convert a simplified class, function or constant name to a fully qualified one using the `resolveName` method:
+Conversely, you can convert a simplified class, function, or constant name back to a fully qualified name using the `resolveName` method:
 
 ```php
 echo $namespace->resolveName('Bar'); // 'Foo\Bar'
@@ -679,26 +683,25 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Class Names Resolving
 ---------------------
 
-**When the class is part of the namespace, it is rendered slightly differently**: all types (ie. type hints, return types, parent class name,
-implemented interfaces, used traits and attributes) are automatically *resolved* (unless you turn it off, see below).
-It means that you have to **use full class names** in definitions and they will be replaced with aliases (according to the use-statements) or fully qualified names in the resulting code:
+**When a class is part of a namespace, it's rendered slightly differently:** all types (e.g., type hints, return types, parent class name, implemented interfaces, used traits, and attributes) are automatically *resolved* (unless you turn it off, see below).
+This means you must use **fully qualified class names** in definitions, and they will be replaced with aliases (based on use clauses) or fully qualified names in the resulting code:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
 $namespace->addUse('Bar\AliasedClass');
 
 $class = $namespace->addClass('Demo');
-$class->addImplement('Foo\A') // it will simplify to A
-	->addTrait('Bar\AliasedClass'); // it will simplify to AliasedClass
+$class->addImplement('Foo\A') // will be simplified to A
+	->addTrait('Bar\AliasedClass'); // will be simplified to AliasedClass
 
 $method = $class->addMethod('method');
-$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // in comments simplify manually
+$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // we manually simplify in comments
 $method->addParameter('arg')
-	->setType('Bar\OtherClass'); // it will resolve to \Bar\OtherClass
+	->setType('Bar\OtherClass'); // will be translated to \Bar\OtherClass
 
 echo $namespace;
 
-// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER
+// or use the PsrPrinter for output in accordance with PSR-2 / PSR-12 / PER
 // echo (new Nette\PhpGenerator\PsrPrinter)->printNamespace($namespace);
 ```
 
@@ -734,7 +737,7 @@ echo $printer->printNamespace($namespace);
 PHP Files
 ---------
 
-Classes, functions and namespaces can be grouped into PHP files represented by the class [PhpFile|api:Nette\PhpGenerator\PhpFile]:
+Classes, functions, and namespaces can be grouped into PHP files represented by the [PhpFile|api:Nette\PhpGenerator\PhpFile] class:
 
 ```php
 $file = new Nette\PhpGenerator\PhpFile;
@@ -751,7 +754,7 @@ $function = $file->addFunction('Foo\foo');
 
 echo $file;
 
-// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER
+// or use the PsrPrinter for output in accordance with PSR-2 / PSR-12 / PER
 // echo (new Nette\PhpGenerator\PsrPrinter)->printFile($file);
 ```
 
@@ -777,9 +780,11 @@ function foo()
 }
 ```
 
+**Please note:** No additional code can be added to the files outside of functions and classes.
 
-Generating According to Existing Ones
--------------------------------------
+
+Generating from Existing Ones
+-----------------------------
 
 In addition to being able to model classes and functions using the API described above, you can also have them automatically generated using existing ones:
 
@@ -787,17 +792,17 @@ In addition to being able to model classes and functions using the API described
 // creates a class identical to the PDO class
 $class = Nette\PhpGenerator\ClassType::from(PDO::class);
 
-// creates a function identical to trim()
+// creates a function identical to the trim() function
 $function = Nette\PhpGenerator\GlobalFunction::from('trim');
 
-// creates a closure as specified
+// creates a closure based on the provided one
 $closure = Nette\PhpGenerator\Closure::from(
 	function (stdClass $a, $b = null) {},
 );
 ```
 
-Function and method bodies are empty by default. If you want to load them as well, use this way
-(it requires `nikic/php-parser` to be installed):
+By default, function and method bodies are empty. If you also want to load them, use this method
+(requires the `nikic/php-parser` package to be installed):
 
 ```php
 $class = Nette\PhpGenerator\ClassType::from(Foo::class, withBodies: true);
@@ -806,10 +811,10 @@ $function = Nette\PhpGenerator\GlobalFunction::from('foo', withBody: true);
 ```
 
 
-Loading from PHP File
----------------------
+Loading from PHP Files
+----------------------
 
-You can also load functions, classes, interfaces and enums directly from a string of PHP code. For example, we create `ClassType` object this way:
+You can also load functions, classes, interfaces, and enums directly from a string containing PHP code. For example, to create a `ClassType` object:
 
 ```php
 $class = Nette\PhpGenerator\ClassType::fromCode(<<<XX
@@ -822,39 +827,71 @@ $class = Nette\PhpGenerator\ClassType::fromCode(<<<XX
 	XX);
 ```
 
-When loading classes from PHP code, single line comments outside of method bodies are ignored (e.g. for properties, etc.) because this library does not have an API to work with them.
+When loading classes from PHP code, single-line comments outside method bodies are ignored (e.g., for properties, etc.), as this library doesn't have an API to work with them.
 
-You can also load the entire PHP file directly, which can contain any number of classes, functions or even multiple namespaces:
+You can also directly load an entire PHP file, which can contain any number of classes, functions, or even namespaces:
 
 ```php
 $file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
 ```
 
-The initial file comment and the `strict_types` declaration are also loaded. On the other hand, all other global code is ignored.
+The file's initial comment and `strict_types` declaration are also loaded. However, all other global code is ignored.
 
-This requires `nikic/php-parser` to be installed.
+It requires `nikic/php-parser` to be installed.
 
 .[note]
-If you need to manipulate global code in files or individual statements in method bodies, it is better to use the `nikic/php-parser` library directly.
+If you need to manipulate global code in files or individual statements in method bodies, it's better to use the `nikic/php-parser` library directly.
+
+
+Class Manipulator
+-----------------
+
+The [ClassManipulator|api:Nette\PhpGenerator\ClassManipulator] class provides tools for manipulating classes.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+The `inheritMethod()` method copies a method from a parent class or implemented interface into your class. This allows you to override the method or extend its signature:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+The `inheritProperty()` method copies a property from a parent class into your class. This is useful when you want to have the same property in your class, but possibly with a different default value:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+The `implementInterface()` method automatically implements all methods from the given interface in your class:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Now your class implements SomeInterface and includes all its methods
+```
 
 
-Variables Dumper
+Variable Dumping
 ----------------
 
-The Dumper returns a parsable PHP string representation of a variable. Provides better and clearer output that native function `var_export()`.
+The `Dumper` class converts a variable into parseable PHP code. It provides a better and clearer output than the standard `var_export()` function.
 
 ```php
 $dumper = new Nette\PhpGenerator\Dumper;
 
 $var = ['a', 'b', 123];
 
-echo $dumper->dump($var); // prints ['a', 'b', 123]
+echo $dumper->dump($var); // outputs ['a', 'b', 123]
 ```
 
 
 Compatibility Table
 -------------------
 
-PhpGenerator 4.0 and 4.1 are compatible with PHP 8.0 to 8.3
+PhpGenerator 4.0 and 4.1 are compatible with PHP 8.0 to 8.3.
 
 {{leftbar: nette:@menu-topics}}
diff --git a/php-generator/es/@home.texy b/php-generator/es/@home.texy
index e26cb1a50a..0ee0eb3d70 100644
--- a/php-generator/es/@home.texy
+++ b/php-generator/es/@home.texy
@@ -2,11 +2,12 @@ Generador de código PHP
 ***********************
 
 <div class=perex>
-- ¿Necesita generar código PHP para clases, funciones, archivos PHP, etc.?
-- Soporta todas las últimas características de PHP como enums, atributos, etc.
+¿Está buscando una herramienta para generar código PHP para clases, funciones o archivos completos?
+
+- Soporta todas las últimas características de PHP (como enums, etc.)
 - Le permite modificar fácilmente las clases existentes
-- Salida compatible con PSR-12 / PER coding style
-- Librería altamente madura, estable y ampliamente utilizada
+- Salida conforme con el estilo de codificación PSR-12 / PER
+- Biblioteca madura, estable y ampliamente utilizada
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Para definir los llamados parámetros variádicos (o también el operador splat, spread, ellipsis, unpacking o tres puntos), utilice `setVariadics()`:
+Para definir los llamados parámetros variádicos (o también el operador splat, spread, ellipsis, unpacking o tres puntos), utilice `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Método y cuerpo de la función .[#toc-method-and-function-body]
---------------------------------------------------------------
+Método y cuerpo de la función .[#toc-method-and-function-bodies]
+----------------------------------------------------------------
 
 El cuerpo puede pasarse al método `setBody()` de una vez o secuencialmente (línea por línea) llamando repetidamente a `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// colocar un parámetro en una línea, incluso si tiene un atributo o es promocionado
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// separador entre el paréntesis derecho y el tipo de retorno de funciones y métodos
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Cada tipo o tipo de unión/intersección puede pasarse como una cadena, también
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // o Type::Array;
-$member->setType('array|string'); // o Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // o Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // elimina el tipo
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-También puede pasar parámetros a `Literal` y hacer que se formatee en código PHP válido utilizando [marcadores de posición especiales |#method-and-function-body-generator]:
+También puede pasar parámetros a `Literal` y hacer que se formatee en código PHP válido utilizando [marcadores de posición especiales |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Resolución de nombres de clase .[#toc-class-names-resolving]
 ------------------------------------------------------------
 
-**Cuando la clase es parte del espacio de nombres, se renderiza de forma ligeramente diferente**: todos los tipos (ie. type hints, return types, parent class name,
-interfaces implementadas, rasgos y atributos usados) se *resuelven* automáticamente (a menos que lo desactives, ver más abajo).
-Esto significa que tienes que **usar nombres de clase completos** en las definiciones y serán reemplazados por alias (de acuerdo con las declaraciones de uso) o nombres completamente cualificados en el código resultante:
+**Cuando una clase es parte de un espacio de nombres, se renderiza de forma ligeramente diferente:** todos los tipos (por ejemplo, sugerencias de tipo, tipos de retorno, nombre de la clase padre, interfaces implementadas, rasgos usados y atributos) se *resuelven* automáticamente (a menos que lo desactives, ver más abajo).
+Esto significa que debes usar **nombres de clase completamente cualificados** en las definiciones, y serán reemplazados por alias (basados en cláusulas de uso) o nombres completamente cualificados en el código resultante:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Por favor, tenga en cuenta:** No se puede añadir código adicional a los archivos fuera de las funciones y clases.
+
 
 Generar en función de los existentes .[#toc-generating-according-to-existing-ones]
 ----------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Esto requiere que `nikic/php-parser` esté instalado.
 Si necesita manipular código global en archivos o sentencias individuales en cuerpos de métodos, es mejor utilizar directamente la biblioteca `nikic/php-parser`.
 
 
+Manipulador de clases .[#toc-class-manipulator]
+-----------------------------------------------
+
+La clase [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] proporciona herramientas para manipular clases.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+El método `inheritMethod()` copia un método de una clase padre o de una interfaz implementada en su clase. Esto le permite sobrescribir el método o extender su firma:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+El método `inheritProperty()` copia una propiedad de una clase padre en tu clase. Esto es útil cuando se desea tener la misma propiedad en su clase, pero posiblemente con un valor predeterminado diferente:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+El método `implementInterface()` implementa automáticamente todos los métodos de la interfaz dada en su clase:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Ahora tu clase implementa CiertaInterfaz e incluye todos sus métodos
+```
+
+
 Volquete de variables .[#toc-variables-dumper]
 ----------------------------------------------
 
diff --git a/php-generator/fr/@home.texy b/php-generator/fr/@home.texy
index c5daf74780..d0279a6c3a 100644
--- a/php-generator/fr/@home.texy
+++ b/php-generator/fr/@home.texy
@@ -2,11 +2,12 @@ Générateur de code PHP
 **********************
 
 <div class=perex>
-- Vous avez besoin de générer du code PHP pour des classes, des fonctions, des fichiers PHP, etc.
-- Supporte toutes les dernières fonctionnalités de PHP comme les enums, les attributs, etc.
+Vous cherchez un outil pour générer du code PHP pour des classes, des fonctions ou des fichiers complets ?
+
+- Supporte toutes les dernières fonctionnalités de PHP (comme les enums, etc.)
 - Vous permet de modifier facilement les classes existantes
-- Sortie conforme à PSR-12 / PER coding style
-- Bibliothèque très mature, stable et largement utilisée.
+- Sortie conforme au style de codage PSR-12 / PER
+- Bibliothèque mature, stable et largement utilisée
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Pour définir les paramètres dits variadiques (ou également l'opérateur splat, spread, ellipsis, unpacking ou trois points), utilisez `setVariadics()`:
+Pour définir les paramètres dits variadiques (ou également l'opérateur splat, spread, ellipsis, unpacking ou trois points), utilisez `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Méthode et corps de fonction .[#toc-method-and-function-body]
--------------------------------------------------------------
+Méthode et corps de fonction .[#toc-method-and-function-bodies]
+---------------------------------------------------------------
 
 Le corps peut être transmis à la méthode `setBody()` en une seule fois ou de manière séquentielle (ligne par ligne) en appelant à plusieurs reprises `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// placer un seul paramètre sur une seule ligne, même s'il possède un attribut ou est promu
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// séparateur entre la parenthèse droite et le type de retour des fonctions et méthodes
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Chaque type ou type d'union/intersection peut être passé comme une chaîne de
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // ou Type::Array;
-$member->setType('array|string'); // ou Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // ou Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // supprime le type
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Vous pouvez également passer des paramètres à `Literal` et les faire formater en code PHP valide à l'aide de [caractères de remplacement spéciaux |#method-and-function-body-generator]:
+Vous pouvez également passer des paramètres à `Literal` et les faire formater en code PHP valide à l'aide de [caractères de remplacement spéciaux |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Résolution des noms de classe .[#toc-class-names-resolving]
 -----------------------------------------------------------
 
-**Lorsque la classe fait partie de l'espace de nom, elle est rendue de manière légèrement différente** : tous les types (c'est-à-dire les indications de type, les types de retour, le nom de la classe parente,
-interfaces implémentées, traits et attributs utilisés) sont automatiquement *résolus* (sauf si vous le désactivez, voir ci-dessous).
-Cela signifie que vous devez **utiliser les noms de classe complets** dans les définitions et qu'ils seront remplacés par des alias (selon les déclarations d'utilisation) ou des noms pleinement qualifiés dans le code résultant :
+**Lorsqu'une classe fait partie d'un espace de noms, son rendu est légèrement différent:** tous les types (par exemple, les indications de type, les types de retour, le nom de la classe mère, les interfaces implémentées, les traits utilisés et les attributs) sont automatiquement *résolus* (sauf si vous le désactivez, voir ci-dessous).
+Cela signifie que vous devez utiliser des **noms de classe pleinement qualifiés** dans les définitions, et qu'ils seront remplacés par des alias (basés sur des clauses d'utilisation) ou des noms pleinement qualifiés dans le code résultant :
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Remarque : aucun code supplémentaire ne peut être ajouté aux fichiers en dehors des fonctions et des classes.
+
 
 Générer en fonction de ceux qui existent déjà .[#toc-generating-according-to-existing-ones]
 -------------------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Cela nécessite l'installation de `nikic/php-parser`.
 Si vous devez manipuler du code global dans des fichiers ou des instructions individuelles dans des corps de méthodes, il est préférable d'utiliser directement la bibliothèque `nikic/php-parser`.
 
 
+Manipulateur de classe .[#toc-class-manipulator]
+------------------------------------------------
+
+La classe [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] fournit des outils pour manipuler les classes.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+La méthode `inheritMethod()` copie une méthode d'une classe parente ou d'une interface implémentée dans votre classe. Cela vous permet de remplacer la méthode ou d'étendre sa signature :
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+La méthode `inheritProperty()` copie une propriété d'une classe parente dans votre classe. Cette méthode est utile lorsque vous souhaitez avoir la même propriété dans votre classe, mais éventuellement avec une valeur par défaut différente :
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+La méthode `implementInterface()` implémente automatiquement toutes les méthodes de l'interface donnée dans votre classe :
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Maintenant, votre classe implémente SomeInterface et inclut toutes ses méthodes
+```
+
+
 Dumper de variables .[#toc-variables-dumper]
 --------------------------------------------
 
diff --git a/php-generator/hu/@home.texy b/php-generator/hu/@home.texy
index 8afbccb2e6..cd1cc89d34 100644
--- a/php-generator/hu/@home.texy
+++ b/php-generator/hu/@home.texy
@@ -2,11 +2,12 @@ PHP kód generátor
 *****************
 
 <div class=perex>
-- PHP kódot szeretne generálni osztályokhoz, függvényekhez, PHP fájlokhoz stb.?
-- Támogatja az összes legújabb PHP funkciót, mint például az enumokat, attribútumokat stb.
+Olyan eszközt keres, amellyel PHP kódot generálhat osztályokhoz, függvényekhez vagy teljes fájlokhoz?
+
+- Támogatja az összes legújabb PHP-funkciót (például enums stb.)
 - Lehetővé teszi a meglévő osztályok egyszerű módosítását
-- PSR-12 / PER coding style szabványnak megfelelő kimenet
-- Rendkívül kiforrott, stabil és széles körben használt könyvtár
+- PSR-12 / PER kódolási stílusnak megfelelő kimenet
+- Kiforrott, stabil és széles körben használt könyvtár
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Az úgynevezett variadics paraméterek (vagy akár a splat, spread, ellipszis, kipakolás vagy a három pont operátor) definiálásához használja a `setVariadics()`:
+Az úgynevezett variadics paraméterek (vagy akár a splat, spread, ellipszis, kipakolás vagy a három pont operátor) definiálásához használja a `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Módszer és funkciótest .[#toc-method-and-function-body]
--------------------------------------------------------
+Módszer és funkciótest .[#toc-method-and-function-bodies]
+---------------------------------------------------------
 
 A test átadható a `setBody()` metódusnak egyszerre vagy szekvenciálisan (soronként) a `addBody()` ismételt hívásával:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// egy paramétert egy sorba helyezünk, még akkor is, ha attribútummal rendelkezik vagy előléptetve van.
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// elválasztó a függvények és metódusok jobb oldali zárójel és a visszatérési típus között.
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Minden típus vagy union/intersection típus átadható stringként, a natív t
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // vagy Type::Array;
-$member->setType('array|string'); // vagy Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // vagy Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // eltávolítja a típust
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-A `Literal` oldalnak paramétereket is átadhat, és azt [speciális helyőrzőket |#method-and-function-body-generator] használva érvényes PHP-kóddá formázhatja:
+A `Literal` oldalnak paramétereket is átadhat, és azt [speciális helyőrzőket |#method-and-function-bodies] használva érvényes PHP-kóddá formázhatja:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Osztálynevek feloldása .[#toc-class-names-resolving]
 ----------------------------------------------------
 
-**Ha az osztály a névtér része, akkor kissé másképp jelenik meg**: minden típus (azaz a típushivatkozások, a visszatérési típusok, a szülő osztály neve,
-implementált interfészek, használt tulajdonságok és attribútumok) automatikusan *feloldódnak* (hacsak ki nem kapcsolod, lásd alább).
-Ez azt jelenti, hogy a definíciókban **teljes osztályneveket** kell használnod, és ezek a keletkező kódban aliasokkal (a use-statementsnek megfelelően) vagy teljesen minősített nevekkel lesznek helyettesítve:
+**Ha egy osztály egy névtér része, akkor kissé másképp jelenik meg:** minden típus (pl. a típushivatkozások, visszatérési típusok, szülőosztály neve, implementált interfészek, használt tulajdonságok és attribútumok) automatikusan *feloldódik* (hacsak ki nem kapcsolod, lásd alább).
+Ez azt jelenti, hogy a definíciókban **teljesen minősített osztályneveket** kell használnia, és ezek helyébe aliasok (a használati záradékok alapján) vagy teljesen minősített nevek lépnek az eredményül kapott kódban:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Figyelem:** A függvényeken és osztályokon kívül nem lehet további kódot hozzáadni a fájlokhoz.
+
 
 A meglévők szerint generálva .[#toc-generating-according-to-existing-ones]
 --------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Ehhez telepíteni kell a `nikic/php-parser` oldalt.
 Ha fájlokban lévő globális kódot vagy a metódusok testében lévő egyes utasításokat kell manipulálnia, jobb, ha közvetlenül a `nikic/php-parser` könyvtárat használja.
 
 
+Osztály Manipulátor .[#toc-class-manipulator]
+---------------------------------------------
+
+A [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] osztály eszközöket biztosít az osztályok manipulálásához.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+A `inheritMethod()` metódus egy metódust másol át egy szülő osztályból vagy egy implementált interfészből az osztályodba. Ez lehetővé teszi a metódus felülírását vagy a szignatúrájának kiterjesztését:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+A `inheritProperty()` metódus egy tulajdonságot másol át egy szülő osztályból az Ön osztályába. Ez akkor hasznos, ha ugyanazt a tulajdonságot szeretné az osztályában, de esetleg más alapértelmezett értékkel:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+A `implementInterface()` metódus automatikusan megvalósítja az adott interfész összes metódusát az osztályodban:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Most az osztályod megvalósítja a SomeInterface-t és tartalmazza annak összes metódusát.
+```
+
+
 Változók Dumper .[#toc-variables-dumper]
 ----------------------------------------
 
diff --git a/php-generator/it/@home.texy b/php-generator/it/@home.texy
index a4e86164e0..5d3c701cc1 100644
--- a/php-generator/it/@home.texy
+++ b/php-generator/it/@home.texy
@@ -2,11 +2,12 @@ Generatore di codice PHP
 ************************
 
 <div class=perex>
-- Avete bisogno di generare codice PHP per classi, funzioni, file PHP e così via?
-- Supporta tutte le più recenti caratteristiche di PHP, come enum, attributi, ecc.
+State cercando uno strumento per generare codice PHP per classi, funzioni o file completi?
+
+- Supporta tutte le più recenti caratteristiche di PHP (come gli enum, ecc.)
 - Permette di modificare facilmente le classi esistenti
-- Output conforme a PSR-12 / PER coding style
-- Libreria altamente matura, stabile e ampiamente utilizzata
+- Uscita conforme allo stile di codifica PSR-12 / PER
+- Libreria matura, stabile e ampiamente utilizzata
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Per definire i cosiddetti parametri variadici (o anche gli operatori splat, spread, ellipsis, unpacking o tre punti), utilizzare `setVariadics()`:
+Per definire i cosiddetti parametri variadici (o anche gli operatori splat, spread, ellipsis, unpacking o tre punti), utilizzare `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Metodo e corpo della funzione .[#toc-method-and-function-body]
---------------------------------------------------------------
+Metodo e corpo della funzione .[#toc-method-and-function-bodies]
+----------------------------------------------------------------
 
 Il corpo può essere passato al metodo `setBody()` in una sola volta o in sequenza (riga per riga) chiamando ripetutamente `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// inserire un parametro in una sola riga, anche se ha un attributo o è promosso
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// separatore tra la parentesi destra e il tipo di ritorno di funzioni e metodi
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Ogni tipo o tipo di unione/intersezione può essere passato come stringa; si pos
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // o Type::Array;
-$member->setType('array|string'); // o Type::union('array', 'stringa')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // o Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // rimuove il tipo
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-È anche possibile passare dei parametri a `Literal` e farli formattare in codice PHP valido, utilizzando [speciali segnaposto |#method-and-function-body-generator]:
+È anche possibile passare dei parametri a `Literal` e farli formattare in codice PHP valido, utilizzando [speciali segnaposto |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Risoluzione dei nomi di classe .[#toc-class-names-resolving]
 ------------------------------------------------------------
 
-**Quando la classe fa parte dello spazio dei nomi, viene resa in modo leggermente diverso**: tutti i tipi (cioè i suggerimenti sui tipi, i tipi di ritorno, il nome della classe genitore,
-interfacce implementate, tratti e attributi utilizzati) sono automaticamente *risolti* (a meno che non lo si disattivi, vedere sotto).
-Ciò significa che bisogna **usare i nomi completi delle classi** nelle definizioni, che saranno sostituiti da alias (secondo le dichiarazioni d'uso) o da nomi pienamente qualificati nel codice risultante:
+**Quando una classe fa parte di uno spazio dei nomi, viene resa in modo leggermente diverso: tutti i tipi (ad esempio, i suggerimenti sui tipi, i tipi di ritorno, il nome della classe madre, le interfacce implementate, i tratti utilizzati e gli attributi) vengono automaticamente *risolti* (a meno che non si disattivi, vedere sotto).
+Ciò significa che è necessario usare nomi di classe **completamente qualificati** nelle definizioni, che verranno sostituiti con alias (basati su clausole di utilizzo) o nomi pienamente qualificati nel codice risultante:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Nota: ** Non è possibile aggiungere altro codice ai file al di fuori delle funzioni e delle classi.
+
 
 Generare in base a quelli esistenti .[#toc-generating-according-to-existing-ones]
 ---------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Questo richiede l'installazione di `nikic/php-parser`.
 Se è necessario manipolare il codice globale nei file o le singole dichiarazioni nei corpi dei metodi, è meglio usare direttamente la libreria `nikic/php-parser`.
 
 
+Manipolatore di classe .[#toc-class-manipulator]
+------------------------------------------------
+
+La classe [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] fornisce strumenti per la manipolazione delle classi.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Il metodo `inheritMethod()` copia un metodo da una classe padre o da un'interfaccia implementata nella propria classe. Ciò consente di sovrascrivere il metodo o di estenderne la firma:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Il metodo `inheritProperty()` copia una proprietà da una classe padre nella vostra classe. È utile quando si vuole avere la stessa proprietà nella propria classe, ma eventualmente con un valore predefinito diverso:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Il metodo `implementInterface()` implementa automaticamente tutti i metodi dell'interfaccia data nella vostra classe:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Ora la classe implementa SomeInterface e include tutti i suoi metodi
+```
+
+
 Dumper di variabili .[#toc-variables-dumper]
 --------------------------------------------
 
diff --git a/php-generator/ja/@home.texy b/php-generator/ja/@home.texy
index 126581589a..8468614408 100644
--- a/php-generator/ja/@home.texy
+++ b/php-generator/ja/@home.texy
@@ -2,11 +2,12 @@ PHP コードジェネレータ
 *************
 
 <div class=perex>
-- クラス、関数、PHPファイルなどのPHPコードを生成する必要がありますか?
-- enum、属性など、最新のPHP機能をすべてサポートしています。
+クラスや関数、ファイル全体のPHPコードを生成するツールをお探しですか?
+
+- 最新の PHP 機能 (enum など) をすべてサポートしています。
 - 既存のクラスを簡単に修正することが可能
-- PSR-12に準拠した出力
-- 非常に成熟した、安定した、広く使われているライブラリです。
+- PSR-12 / PERコーディングスタイルに準拠した出力
+- 成熟し、安定し、広く使用されているライブラリ
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-いわゆる variadics パラメータ(あるいは splat, spread, ellipsis, unpacking, three dots オペレータ)を定義するには、`setVariadics()` を使用します。
+いわゆる variadics パラメータ(あるいは splat, spread, ellipsis, unpacking, three dots オペレータ)を定義するには、`setVariadic()` を使用します。
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-メソッドと関数本体 .[#toc-method-and-function-body]
-------------------------------------------
+メソッドと関数本体 .[#toc-method-and-function-bodies]
+--------------------------------------------
 
 本体は、`setBody()` メソッドに一度に渡すこともできますし、`addBody()` を繰り返し呼び出すことで順次(一行ずつ)渡すこともできます。
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// パラメータが属性を持っていたり、昇格していても、1つのパラメータを1行に配置する。
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// メソッドの右括弧と戻り値の関数との間の区切り文字
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // or Type::Array;
-$member->setType('array|string'); // or Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // removes type
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-`Literal` にパラメータを渡すと、[特別なプレースホルダーを使って |#method-and-function-body-generator]有効な PHP コードにフォーマットさせることもできます。
+`Literal` にパラメータを渡すと、[特別なプレースホルダーを使って |#method-and-function-bodies]有効な PHP コードにフォーマットさせることもできます。
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 クラス名の解決 .[#toc-class-names-resolving]
 -------------------------------------
 
-**クラスが名前空間の一部である場合、わずかに異なる方法でレンダリングされます**:すべてのタイプ(すなわち、タイプヒント、戻り値タイプ、親クラス名、
-実装されたインターフェース、使用された特性や属性)は自動的に*解決*されます(オフにしない限り、以下を参照)。
-つまり、定義では完全なクラス名**を使用しなければならず、結果のコードではエイリアス(use-statementに従う)または完全修飾名に置き換えられます:
+**すべての型(例:型ヒント、戻り値型、親クラス名、実装されたインターフェイス、使用された特性、属性)は自動的に *解決* されます(オフにしない限り。)
+つまり、**完全に修飾されたクラス名** を定義に使用する必要があり、結果のコードではエイリアス(use句に基づく)または完全に修飾された名前に置き換えられます:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**注意:*** 関数やクラス以外のコードをファイルに追加することはできません。
+
 
 既存のものに合わせて生成する .[#toc-generating-according-to-existing-ones]
 ------------------------------------------------------------
@@ -838,6 +843,38 @@ $file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
 ファイル内のグローバルコードやメソッド本体内の個々のステートメントを操作する必要がある場合は、 `nikic/php-parser` ライブラリを直接使用するのがよい。
 
 
+クラス・マニピュレーター.[#toc-class-manipulator]
+-------------------------------------
+
+[ClassManipulator |api:Nette\PhpGenerator\ClassManipulator]クラスは、クラスを操作するためのツールを提供します。
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+`inheritMethod()` メソッドは、親クラスまたは実装されたインターフェイスのメソッドをあなたのクラスにコピーします。これにより、メソッドをオーバーライドしたり、シグネチャを拡張したりできます:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+`inheritProperty()` メソッドは、親クラスからあなたのクラスにプロパティをコピーします。これは、同じプロパティを自分のクラスにも持たせたいが、デフォルト値が異なる可能性がある場合に便利です:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+`implementInterface()` メソッドは、指定されたインターフェイスのすべてのメソッドを自動的にクラスに実装します:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// これで、あなたのクラスは SomeInterface を実装し、そのすべてのメソッドを含むようになった。
+```
+
+
 変数ダンパ .[#toc-variables-dumper]
 ------------------------------
 
diff --git a/php-generator/pl/@home.texy b/php-generator/pl/@home.texy
index d8c4c85ac0..3f68976960 100644
--- a/php-generator/pl/@home.texy
+++ b/php-generator/pl/@home.texy
@@ -2,11 +2,12 @@ Generator kodu PHP
 ******************
 
 <div class=perex>
-- Potrzebujesz wygenerować kod PHP dla klas, funkcji, plików PHP, itp.
-- Obsługuje wszystkie najnowsze funkcje PHP, takie jak enumy, atrybuty, itp.
+Szukasz narzędzia do generowania kodu PHP dla klas, funkcji lub całych plików?
+
+- Obsługuje wszystkie najnowsze funkcje PHP (takie jak wyliczenia itp.)
 - Pozwala na łatwą modyfikację istniejących klas
-- Wyjście zgodne z PSR-12 / PER coding style
-- Wysoce dojrzała, stabilna i szeroko stosowana biblioteka
+- Wyjście zgodne ze stylem kodowania PSR-12 / PER
+- Dojrzała, stabilna i szeroko stosowana biblioteka
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Aby zdefiniować tzw. parametry variadics (lub również operator splat, spread, elipsa, rozpakowywanie czy trzy kropki), należy użyć `setVariadics()`:
+Aby zdefiniować tzw. parametry variadics (lub również operator splat, spread, elipsa, rozpakowywanie czy trzy kropki), należy użyć `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Metoda i ciało funkcji .[#toc-method-and-function-body]
--------------------------------------------------------
+Metoda i ciało funkcji .[#toc-method-and-function-bodies]
+---------------------------------------------------------
 
 Ciało może być przekazane do metody `setBody()` jednorazowo lub sekwencyjnie (linia po linii) poprzez wielokrotne wywołanie `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// umieszczenie jednego parametru w jednej linii, nawet jeśli ma atrybut lub jest promowany
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// separator między prawym nawiasem a typem zwracanej funkcji i metody
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Każdy typ lub typ unii / przecięcia może być przekazany jako ciąg, możesz
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // lub Type::Array;
-$member->setType('array|string'); // lub Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // lub Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // usuwa typ
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Możesz również przekazać parametry do `Literal` i mieć je sformatowane w poprawny kod PHP za pomocą [specjalnych placeholderów |#method-and-function-body-generator]:
+Możesz również przekazać parametry do `Literal` i mieć je sformatowane w poprawny kod PHP za pomocą [specjalnych placeholderów |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Class Names Resolving (rozwiązywanie nazw klas) .[#toc-class-names-resolving]
 -----------------------------------------------------------------------------
 
-**Kiedy klasa jest częścią przestrzeni nazw, jest renderowana nieco inaczej**: wszystkie typy (tj. podpowiedzi typów, typy zwracane, nazwa klasy nadrzędnej,
-zaimplementowane interfejsy, użyte cechy i atrybuty) są automatycznie *rozwiązywane* (chyba że wyłączysz tę funkcję, patrz poniżej).
-Oznacza to, że musisz **używać pełnych nazw klas** w definicjach, a zostaną one zastąpione aliasami (zgodnie z deklaracjami użycia) lub w pełni kwalifikowanymi nazwami w wynikowym kodzie:
+**Gdy klasa jest częścią przestrzeni nazw, jest renderowana nieco inaczej:** wszystkie typy (np. podpowiedzi typów, typy zwracane, nazwa klasy nadrzędnej, zaimplementowane interfejsy, używane cechy i atrybuty) są automatycznie *rozwiązywane* (chyba że to wyłączysz, patrz poniżej).
+Oznacza to, że musisz używać **w pełni kwalifikowanych nazw klas** w definicjach, a zostaną one zastąpione aliasami (opartymi na klauzulach użycia) lub w pełni kwalifikowanymi nazwami w wynikowym kodzie:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Uwaga:** Do plików nie można dodawać żadnego dodatkowego kodu poza funkcjami i klasami.
+
 
 Generowanie według istniejących .[#toc-generating-according-to-existing-ones]
 -----------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Wymaga to zainstalowania `nikic/php-parser`.
 Jeśli musisz manipulować globalnym kodem w plikach lub pojedynczymi stwierdzeniami w ciałach metod, lepiej jest użyć bezpośrednio biblioteki `nikic/php-parser`.
 
 
+Class Manipulator .[#toc-class-manipulator]
+-------------------------------------------
+
+Klasa [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] zapewnia narzędzia do manipulowania klasami.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Metoda `inheritMethod()` kopiuje metodę z klasy nadrzędnej lub zaimplementowanego interfejsu do klasy użytkownika. Pozwala to na nadpisanie metody lub rozszerzenie jej sygnatury:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Metoda `inheritProperty()` kopiuje właściwość z klasy nadrzędnej do klasy użytkownika. Jest to przydatne, gdy chcesz mieć tę samą właściwość w swojej klasie, ale prawdopodobnie z inną wartością domyślną:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Metoda `implementInterface()` automatycznie implementuje wszystkie metody z danego interfejsu w klasie:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Teraz twoja klasa implementuje interfejs SomeInterface i zawiera wszystkie jego metody
+```
+
+
 Zrzutka zmiennych .[#toc-variables-dumper]
 ------------------------------------------
 
diff --git a/php-generator/pt/@home.texy b/php-generator/pt/@home.texy
index 9e49068c2c..3e797093a6 100644
--- a/php-generator/pt/@home.texy
+++ b/php-generator/pt/@home.texy
@@ -2,11 +2,12 @@ Gerador de código PHP
 *********************
 
 <div class=perex>
-- Necessidade de gerar código PHP para classes, funções, arquivos PHP, etc.?
-- Suporta todas as últimas características do PHP, como enumeração, atributos, etc.
+Você está procurando uma ferramenta para gerar código PHP para classes, funções ou arquivos completos?
+
+- Oferece suporte a todos os recursos mais recentes do PHP (como enums, etc.)
 - Permite modificar facilmente as classes existentes
-- Saída compatível com PSR-12 / PER coding style
-- Biblioteca altamente madura, estável e amplamente utilizada
+- Saída compatível com o estilo de codificação PSR-12 / PER
+- Biblioteca madura, estável e amplamente utilizada
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Para definir os chamados parâmetros de variação (ou também o splat, spread, elipse, desempacotamento ou operador de três pontos), use `setVariadics()`:
+Para definir os chamados parâmetros de variação (ou também o splat, spread, elipse, desempacotamento ou operador de três pontos), use `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Método e Função Corpo .[#toc-method-and-function-body]
-------------------------------------------------------
+Método e Função Corpo .[#toc-method-and-function-bodies]
+--------------------------------------------------------
 
 O corpo pode ser passado para o método `setBody()` de uma vez ou sequencialmente (linha por linha), ligando repetidamente para `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// colocar um parâmetro em uma linha, mesmo que ele tenha um atributo ou seja promovido
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// separador entre o parêntese direito e o tipo de retorno de funções e métodos
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Cada tipo ou tipo de união/intersecção pode ser passado como uma corda, você
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // or Type::Array;
-$member->setType('array|string'); // or Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // removes type
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Você também pode passar os parâmetros para `Literal` e formatá-lo em código PHP válido usando [marcadores de lugar especiais |#method-and-function-body-generator]:
+Você também pode passar os parâmetros para `Literal` e formatá-lo em código PHP válido usando [marcadores de lugar especiais |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Resolução de Nomes de Classe .[#toc-class-names-resolving]
 ----------------------------------------------------------
 
-** Quando a classe faz parte do namespace, ela é renderizada de forma ligeiramente diferente**: todos os tipos (ou seja, dicas de tipo, tipos de retorno, nome da classe pai,
-interfaces implementadas, características e atributos utilizados) são automaticamente *resolvidos* (a menos que você o desligue, veja abaixo).
-Isso significa que você tem que **utilizar nomes completos de classe** em definições e eles serão substituídos por apelidos (de acordo com as declarações de uso) ou nomes totalmente qualificados no código resultante:
+**Quando uma classe faz parte de um namespace, ela é renderizada de forma um pouco diferente:** todos os tipos (por exemplo, dicas de tipo, tipos de retorno, nome da classe pai, interfaces implementadas, características usadas e atributos) são automaticamente *resolvidos* (a menos que você desative essa opção, veja abaixo).
+Isso significa que você deve usar **nomes de classe totalmente qualificados** nas definições, e eles serão substituídos por aliases (com base em cláusulas de uso) ou nomes totalmente qualificados no código resultante:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Observação:** Nenhum código adicional pode ser adicionado aos arquivos fora das funções e classes.
+
 
 Gerando de acordo com os já existentes .[#toc-generating-according-to-existing-ones]
 ------------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Isto requer que `nikic/php-parser` seja instalado.
 Se você precisar manipular o código global em arquivos ou declarações individuais em corpos de métodos, é melhor usar a biblioteca `nikic/php-parser` diretamente.
 
 
+Manipulador de classe .[#toc-class-manipulator]
+-----------------------------------------------
+
+A classe [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] fornece ferramentas para a manipulação de classes.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+O método `inheritMethod()` copia um método de uma classe pai ou de uma interface implementada em sua classe. Isso permite que você substitua o método ou estenda sua assinatura:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+O método `inheritProperty()` copia uma propriedade de uma classe principal para a sua classe. Isso é útil quando você deseja ter a mesma propriedade em sua classe, mas possivelmente com um valor padrão diferente:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+O método `implementInterface()` implementa automaticamente todos os métodos da interface fornecida em sua classe:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Agora sua classe implementa SomeInterface e inclui todos os seus métodos
+```
+
+
 Variáveis Dumper .[#toc-variables-dumper]
 -----------------------------------------
 
diff --git a/php-generator/ro/@home.texy b/php-generator/ro/@home.texy
index d64f15e758..edc02152f3 100644
--- a/php-generator/ro/@home.texy
+++ b/php-generator/ro/@home.texy
@@ -2,11 +2,12 @@ Generator de coduri PHP
 ***********************
 
 <div class=perex>
-- Aveți nevoie să generați cod PHP pentru clase, funcții, fișiere PHP, etc.?
-- Suportă toate cele mai recente caracteristici PHP, cum ar fi enums, atribute, etc.
+Sunteți în căutarea unui instrument pentru a genera cod PHP pentru clase, funcții sau fișiere complete?
+
+- Suportă toate cele mai recente caracteristici PHP (cum ar fi enums etc.)
 - Vă permite să modificați cu ușurință clasele existente
-- Ieșire conformă cu PSR-12 / PER coding style
-- Bibliotecă extrem de matură, stabilă și utilizată pe scară largă
+- Ieșire conformă cu stilul de codare PSR-12 / PER
+- Bibliotecă matură, stabilă și utilizată pe scară largă
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Pentru a defini așa-numiții parametri variadici (sau, de asemenea, operatorul splat, spread, elipsis, unpacking sau trei puncte), utilizați `setVariadics()`:
+Pentru a defini așa-numiții parametri variadici (sau, de asemenea, operatorul splat, spread, elipsis, unpacking sau trei puncte), utilizați `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Metoda și corpul funcției .[#toc-method-and-function-body]
-----------------------------------------------------------
+Metoda și corpul funcției .[#toc-method-and-function-bodies]
+------------------------------------------------------------
 
 Corpul poate fi transmis metodei `setBody()` o dată sau secvențial (linie cu linie) prin apelarea repetată a metodei `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// plasează un parametru pe o singură linie, chiar dacă are un atribut sau este promovat
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// separator între paranteza dreaptă și tipul return al funcțiilor și metodelor
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Fiecare tip sau tip de uniune/intersecție poate fi transmis ca un șir de carac
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // sau Type::Array;
-$member->setType('array|string'); // sau Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // sau Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // elimină tipul
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Puteți, de asemenea, să transmiteți parametri la `Literal` și să formatați codul PHP valid folosind [caractere de poziție speciale |#method-and-function-body-generator]:
+Puteți, de asemenea, să transmiteți parametri la `Literal` și să formatați codul PHP valid folosind [caractere de poziție speciale |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Rezolvarea numelor de clase .[#toc-class-names-resolving]
 ---------------------------------------------------------
 
-**Când clasa face parte din spațiul de nume, este redată puțin diferit**: toate tipurile (adică indicii de tip, tipuri de returnare, numele clasei părinte,
-interfețele implementate, trăsăturile și atributele utilizate) sunt automat *rezolvate* (cu excepția cazului în care dezactivați această funcție, a se vedea mai jos).
-Aceasta înseamnă că trebuie să **utilizați nume de clasă complete** în definiții și că acestea vor fi înlocuite cu alias-uri (în conformitate cu declarațiile de utilizare) sau cu nume complet calificate în codul rezultat:
+**Când o clasă face parte dintr-un spațiu de nume, aceasta este redată în mod ușor diferit:** toate tipurile (de exemplu, indicii de tip, tipuri de returnare, numele clasei părinte, interfețe implementate, trăsături utilizate și atribute) sunt automat *rezolvate* (dacă nu le dezactivați, a se vedea mai jos).
+Acest lucru înseamnă că trebuie să utilizați **nume de clasă complet calificate** în definiții, iar acestea vor fi înlocuite cu pseudonime (pe baza clauzelor de utilizare) sau cu nume complet calificate în codul rezultat:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Atenție:** Nu se poate adăuga niciun cod suplimentar la fișiere în afara funcțiilor și claselor.
+
 
 Generarea în funcție de cele existente .[#toc-generating-according-to-existing-ones]
 ------------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Acest lucru necesită instalarea `nikic/php-parser`.
 Dacă aveți nevoie să manipulați codul global din fișiere sau declarațiile individuale din corpurile metodelor, este mai bine să utilizați direct biblioteca `nikic/php-parser`.
 
 
+Manipulator de clasă .[#toc-class-manipulator]
+----------------------------------------------
+
+Clasa [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] oferă instrumente pentru manipularea claselor.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Metoda `inheritMethod()` copiază o metodă dintr-o clasă părinte sau dintr-o interfață implementată în clasa dumneavoastră. Acest lucru vă permite să suprascrieți metoda sau să-i extindeți semnătura:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Metoda `inheritProperty()` copiază o proprietate dintr-o clasă părinte în clasa dumneavoastră. Acest lucru este util atunci când doriți să aveți aceeași proprietate în clasa dvs., dar eventual cu o valoare implicită diferită:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Metoda `implementInterface()` implementează automat toate metodele interfeței date în clasa dumneavoastră:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Acum clasa dvs. implementează SomeInterface și include toate metodele acesteia
+```
+
+
 Descărcător de variabile .[#toc-variables-dumper]
 -------------------------------------------------
 
diff --git a/php-generator/ru/@home.texy b/php-generator/ru/@home.texy
index bd7d7f6417..dc328ce15a 100644
--- a/php-generator/ru/@home.texy
+++ b/php-generator/ru/@home.texy
@@ -2,11 +2,12 @@
 ******************
 
 <div class=perex>
-- Вам нужно сгенерировать PHP-код для классов, функций, PHP-файлов и т.д.?
-- Поддерживает все новейшие возможности PHP, такие как перечисления, атрибуты и т.д.
+Вы ищете инструмент для генерации PHP-кода для классов, функций или целых файлов?
+
+- Поддерживает все новейшие возможности PHP (такие как перечисления и т.д.)
 - Позволяет легко модифицировать существующие классы
-- Выходные данные соответствуют стандарту PSR-12 / PER coding style
-- Высокоразвитая, стабильная и широко используемая библиотека
+- Выходные данные соответствуют стилю кодирования PSR-12 / PER
+- Зрелая, стабильная и широко используемая библиотека
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Для определения так называемых вариативных параметров (а также операторов splat, spread, ellipsis, unpacking или three dots) используйте `setVariadics()`:
+Для определения так называемых вариативных параметров (а также операторов splat, spread, ellipsis, unpacking или three dots) используйте `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Метод и тело функции .[#toc-method-and-function-body]
------------------------------------------------------
+Метод и тело функции .[#toc-method-and-function-bodies]
+-------------------------------------------------------
 
 Содержимое функции или метода может быть передано методу `setBody()` сразу или последовательно (строка за строкой) путем многократного вызова `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// размещение одного параметра в одной строке, даже если у него есть атрибут или он продвигается
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// разделитель между правой круглой скобкой и возвращаемым типом функций и методов
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // или Type::Array;
-$member->setType('array|string'); // или Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // или Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // удаляет тип
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Вы также можете передавать параметры в `Literal` и форматировать их в правильный PHP-код с помощью [специальных заполнителей |#method-and-function-body-generator]:
+Вы также можете передавать параметры в `Literal` и форматировать их в правильный PHP-код с помощью [специальных заполнителей |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Разрешение имён классов .[#toc-class-names-resolving]
 -----------------------------------------------------
 
-**Когда класс является частью пространства имен, он отображается несколько иначе**: все типы (т.е. подсказки типов, возвращаемые типы, имя родительского класса,
-реализованные интерфейсы, используемые черты и атрибуты) автоматически *разрешаются* (если вы не отключите эту функцию, см. ниже).
-Это означает, что вы должны **использовать полные имена классов** в определениях, и они будут заменены псевдонимами (в соответствии с условиями использования) или полностью квалифицированными именами в результирующем коде:
+**Когда класс является частью пространства имен, он отображается несколько иначе:** все типы (например, подсказки типов, возвращаемые типы, имя родительского класса, реализованные интерфейсы, используемые трейты и атрибуты) автоматически *разрешаются* (если это не отключено, см. ниже).
+Это означает, что в определениях необходимо использовать **полностью квалифицированные имена классов**, и в результирующем коде они будут заменены псевдонимами (основанными на положениях use) или полностью квалифицированными именами:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Примечание:** В файлы не может быть добавлен дополнительный код за пределами функций и классов.
+
 
 Генерация с использованием Reflection .[#toc-generating-according-to-existing-ones]
 -----------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ $file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
 Если вам нужно манипулировать глобальным кодом в файлах или отдельными утверждениями в телах методов, лучше использовать непосредственно библиотеку `nikic/php-parser`.
 
 
+Манипулятор класса .[#toc-class-manipulator]
+--------------------------------------------
+
+Класс [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] предоставляет инструменты для манипулирования классами.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Метод `inheritMethod()` копирует метод из родительского класса или реализованного интерфейса в ваш класс. Это позволяет переопределить метод или расширить его сигнатуру:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Метод `inheritProperty()` копирует свойство из родительского класса в ваш класс. Это полезно, когда вы хотите иметь то же свойство в своем классе, но, возможно, с другим значением по умолчанию:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Метод `implementInterface()` автоматически реализует в вашем классе все методы из заданного интерфейса:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Теперь ваш класс реализует SomeInterface и включает все его методы
+```
+
+
 Дампинг переменных .[#toc-variables-dumper]
 -------------------------------------------
 
diff --git a/php-generator/sl/@home.texy b/php-generator/sl/@home.texy
index 0b2e86b50c..015e74f7bd 100644
--- a/php-generator/sl/@home.texy
+++ b/php-generator/sl/@home.texy
@@ -2,11 +2,12 @@ Generator kode PHP
 ******************
 
 <div class=perex>
-- Potrebujete kodo PHP za razrede, funkcije, datoteke PHP itd.?
-- Podpira vse najnovejše funkcije PHP, kot so enumi, atributi itd.
+Iščete orodje za ustvarjanje kode PHP za razrede, funkcije ali celotne datoteke?
+
+- Podpira vse najnovejše funkcije PHP (kot so enumi itd.)
 - Omogoča enostavno spreminjanje obstoječih razredov
-- Izpis v skladu s standardom PSR-12 / PER coding style
-- Zelo zrela, stabilna in pogosto uporabljena knjižnica
+- Izhod je skladen s slogom kodiranja PSR-12 / PER
+- Zrela, stabilna in široko uporabljena knjižnica
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Za določitev tako imenovanih parametrov variadics (ali tudi operatorjev splat, spread, elipsis, unpacking ali tri pike) uporabite `setVariadics()`:
+Za določitev tako imenovanih parametrov variadics (ali tudi operatorjev splat, spread, elipsis, unpacking ali tri pike) uporabite `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Metoda in telo funkcije .[#toc-method-and-function-body]
---------------------------------------------------------
+Metoda in telo funkcije .[#toc-method-and-function-bodies]
+----------------------------------------------------------
 
 Telo lahko metodi `setBody()` posredujete naenkrat ali zaporedno (vrstico za vrstico) z večkratnim klicem `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// postavi en parameter v eno vrstico, tudi če ima atribut ali je povišan
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// ločilo med desnim oklepajem in tipom vrnitve funkcij in metod
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Vsak tip ali tip zveze/intersekcije je mogoče posredovati kot niz, uporabite la
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // ali Type::Array;
-$member->setType('array|string'); // ali Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // ali Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // odstrani tip
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Rezultat: Na naslov `Literal` lahko posredujete tudi parametre, ki se s [posebnimi nadomestki |#method-and-function-body-generator] oblikujejo v veljavno PHP kodo:
+Rezultat: Na naslov `Literal` lahko posredujete tudi parametre, ki se s [posebnimi nadomestki |#method-and-function-bodies] oblikujejo v veljavno PHP kodo:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Razreševanje imen razredov .[#toc-class-names-resolving]
 --------------------------------------------------------
 
-**Ko je razred del imenskega prostora, se prikaže nekoliko drugače**: vse vrste (tj. namigi na vrsto, vrnitvene vrste, ime nadrejenega razreda,
-implementirani vmesniki, uporabljene lastnosti in atributi) se samodejno *razrešijo* (razen če to izklopite, glejte spodaj).
-To pomeni, da morate v definicijah **uporabiti polna imena razredov**, ki bodo v dobljeni kodi nadomeščena s približki (glede na izjave o uporabi) ali polno kvalificiranimi imeni:
+**Ko je razred del imenskega prostora, se prikaže nekoliko drugače:** vsi tipi (npr. namigi na tip, tipi vrnitve, ime nadrejenega razreda, implementirani vmesniki, uporabljene lastnosti in atributi) se samodejno *razrešijo* (razen če to izklopite, glejte spodaj).
+To pomeni, da morate v definicijah uporabljati **polno kvalificirana imena razredov**, ki bodo v dobljeni kodi nadomeščena s približki (na podlagi klavzul use) ali polno kvalificiranimi imeni:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Upoštevajte:** V datoteke ni mogoče dodajati dodatne kode zunaj funkcij in razredov.
+
 
 Ustvarjanje glede na obstoječe .[#toc-generating-according-to-existing-ones]
 ----------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Za to je treba namestiti `nikic/php-parser`.
 Če morate upravljati globalno kodo v datotekah ali posamezne stavke v telesih metod, je bolje, da neposredno uporabite knjižnico `nikic/php-parser`.
 
 
+Manipulator razreda .[#toc-class-manipulator]
+---------------------------------------------
+
+Razred [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] ponuja orodja za manipulacijo z razredi.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Metoda `inheritMethod()` kopira metodo iz nadrejenega razreda ali implementiranega vmesnika v vaš razred. To vam omogoča, da metodo prekrijete ali razširite njen podpis:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Metoda `inheritProperty()` kopira lastnost iz nadrejenega razreda v vaš razred. To je uporabno, kadar želite imeti isto lastnost v svojem razredu, vendar po možnosti z drugo privzeto vrednostjo:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Metoda `implementInterface()` samodejno implementira vse metode iz danega vmesnika v vaš razred:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Zdaj vaš razred implementira SomeInterface in vključuje vse njegove metode
+```
+
+
 Zbiralnik spremenljivk .[#toc-variables-dumper]
 -----------------------------------------------
 
diff --git a/php-generator/tr/@home.texy b/php-generator/tr/@home.texy
index e0683b5911..6d27983caf 100644
--- a/php-generator/tr/@home.texy
+++ b/php-generator/tr/@home.texy
@@ -2,11 +2,12 @@ PHP Kod Oluşturucu
 ******************
 
 <div class=perex>
-- Sınıflar, fonksiyonlar, PHP dosyaları vb. için PHP kodu oluşturmanız mı gerekiyor?
-- Enumlar, nitelikler vb. gibi en son PHP özelliklerini destekler.
+Sınıflar, fonksiyonlar veya tüm dosyalar için PHP kodu üretecek bir araç mı arıyorsunuz?
+
+- En son PHP özelliklerini destekler (enumlar vb. gibi)
 - Mevcut sınıfları kolayca değiştirmenizi sağlar
-- PSR-12 / PER coding style uyumlu çıkış
-- Son derece olgun, istikrarlı ve yaygın olarak kullanılan kütüphane
+- PSR-12 / PER kodlama stili ile uyumlu çıkış
+- Olgun, kararlı ve yaygın olarak kullanılan kütüphane
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Variadics parametrelerini (veya splat, spread, ellipsis, unpacking veya three dots operatörlerini) tanımlamak için `setVariadics()` adresini kullanın:
+Variadics parametrelerini (veya splat, spread, ellipsis, unpacking veya three dots operatörlerini) tanımlamak için `setVariadic()` adresini kullanın:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Yöntem ve İşlev Gövde .[#toc-method-and-function-body]
-------------------------------------------------------
+Yöntem ve İşlev Gövde .[#toc-method-and-function-bodies]
+--------------------------------------------------------
 
 Gövde `setBody()` yöntemine bir kerede veya `addBody()` adresini tekrar tekrar çağırarak sırayla (satır satır) aktarılabilir:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// bir özniteliğe sahip olsa veya terfi ettirilse bile bir parametreyi tek bir satıra yerleştirir
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// sağ parantez ile fonksiyon ve metotların dönüş tipi arasında ayırıcı
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ Her tür veya birlik/kesişim türü bir dize olarak geçirilebilir, ayrıca yer
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // veya Type::Array;
-$member->setType('array|string'); // veya Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // veya Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // türü kaldırır
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Ayrıca `Literal` adresine parametre aktarabilir ve [özel yer tutucular |#method-and-function-body-generator] kullanarak geçerli PHP kodu olarak biçimlendirilmesini sağlayabilirsiniz:
+Ayrıca `Literal` adresine parametre aktarabilir ve [özel yer tutucular |#method-and-function-bodies] kullanarak geçerli PHP kodu olarak biçimlendirilmesini sağlayabilirsiniz:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Sınıf Adları Çözülüyor .[#toc-class-names-resolving]
 ----------------------------------------------------
 
-**Sınıf isim alanının bir parçası olduğunda, biraz farklı şekilde işlenir**: tüm tipler (yani tip ipuçları, dönüş tipleri, ana sınıf adı,
-uygulanan arayüzler, kullanılan özellikler ve nitelikler) otomatik olarak *çözülür* (kapatmadığınız sürece, aşağıya bakın).
-Bu, tanımlarda **tam sınıf adlarını** kullanmanız gerektiği ve sonuçta ortaya çıkan kodda bunların takma adlarla (kullanım ifadelerine göre) veya tam nitelikli adlarla değiştirileceği anlamına gelir:
+**Bir sınıf bir isim alanının parçası olduğunda, biraz farklı şekilde işlenir:** tüm tipler (örneğin, tip ipuçları, dönüş tipleri, ana sınıf adı, uygulanan arayüzler, kullanılan özellikler ve nitelikler) otomatik olarak *çözülür* (kapatmadığınız sürece, aşağıya bakın).
+Bu, tanımlarda **tam nitelikli sınıf adları** kullanmanız gerektiği anlamına gelir ve bunlar sonuçta ortaya çıkan kodda takma adlarla (use cümlelerine dayalı olarak) veya tam nitelikli adlarla değiştirilecektir:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Lütfen dikkat:** Dosyalara fonksiyonlar ve sınıflar dışında hiçbir ek kod eklenemez.
+
 
 Mevcut Olanlara Göre Üretme .[#toc-generating-according-to-existing-ones]
 -------------------------------------------------------------------------
@@ -838,6 +843,38 @@ Bunun için `nikic/php-parser` adresinin yüklenmesi gerekir.
 Dosyalardaki genel kodu veya yöntem gövdelerindeki tek tek ifadeleri değiştirmeniz gerekiyorsa, `nikic/php-parser` kütüphanesini doğrudan kullanmak daha iyidir.
 
 
+Sınıf Manipülatörü .[#toc-class-manipulator]
+--------------------------------------------
+
+ [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] sınıfı, sınıfları [manipüle |api:Nette\PhpGenerator\ClassManipulator] etmek için araçlar sağlar.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+ `inheritMethod()` yöntemi, bir üst sınıftaki veya uygulanan arayüzdeki bir yöntemi sınıfınıza kopyalar. Bu, yöntemi geçersiz kılmanıza veya imzasını genişletmenize olanak tanır:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+ `inheritProperty()` yöntemi, bir özelliği bir üst sınıftan sınıfınıza kopyalar. Bu, sınıfınızda aynı özelliğe sahip olmak, ancak muhtemelen farklı bir varsayılan değere sahip olmak istediğinizde kullanışlıdır:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+ `implementInterface()` yöntemi, sınıfınızda verilen arayüzdeki tüm yöntemleri otomatik olarak uygular:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Şimdi sınıfınız SomeInterface'i uyguluyor ve tüm yöntemlerini içeriyor
+```
+
+
 Değişkenler Damperi .[#toc-variables-dumper]
 --------------------------------------------
 
diff --git a/php-generator/uk/@home.texy b/php-generator/uk/@home.texy
index 757f00ce49..3a6c88f616 100644
--- a/php-generator/uk/@home.texy
+++ b/php-generator/uk/@home.texy
@@ -2,11 +2,12 @@
 ******************
 
 <div class=perex>
-- Потрібно згенерувати PHP-код для класів, функцій, PHP-файлів тощо?
-- Підтримує всі найновіші можливості PHP, такі як перерахування, атрибути тощо.
+Ви шукаєте інструмент для генерації PHP-коду для класів, функцій або цілих файлів?
+
+- Підтримує всі найновіші можливості PHP (наприклад, перерахування тощо).
 - Дозволяє легко модифікувати існуючі класи
-- Вихідні дані, сумісні з PSR-12 / PER coding style
-- Досконала, стабільна та широко використовувана бібліотека
+- Вихід, сумісний зі стилем кодування PSR-12 / PER
+- Зріла, стабільна та широко використовувана бібліотека
 </div>
 
 
@@ -361,11 +362,11 @@ $method->addParameter('items', []) // $items = []
 // function count(&$items = [])
 ```
 
-Для визначення так званих варіадичних параметрів (або також операторів splat, spread, еліпсис, розпакування або три крапки) використовуйте `setVariadics()`:
+Для визначення так званих варіадичних параметрів (або також операторів splat, spread, еліпсис, розпакування або три крапки) використовуйте `setVariadic()`:
 
 ```php
 $method = $class->addMethod('count');
-$method->setVariadics(true);
+$method->setVariadic(true);
 $method->addParameter('items');
 ```
 
@@ -378,8 +379,8 @@ function count(...$items)
 ```
 
 
-Метод і тіло функції .[#toc-method-and-function-body]
------------------------------------------------------
+Метод і тіло функції .[#toc-method-and-function-bodies]
+-------------------------------------------------------
 
 Тіло можна передати в метод `setBody()` одразу або послідовно (рядок за рядком) шляхом багаторазового виклику `addBody()`:
 
@@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 	public bool $bracesOnNextLine = true;
 	// розміщувати один параметр в одному рядку, навіть якщо він має атрибут або є розкрученим
 	public bool $singleParameterOnOneLine = false;
+	// omits namespaces that do not contain any class or function
+	public bool $omitEmptyNamespaces = true;
 	// роздільник між правою круглою дужкою та типом повернення функцій та методів
 	public string $returnTypeColon = ': ';
 }
@@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer
 use Nette\PhpGenerator\Type;
 
 $member->setType('array'); // або Type::Array;
-$member->setType('array|string'); // або Type::union('array', 'string')
+$member->setType('?array'); // or Type::nullable(Type::Array);
+$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
 $member->setType('Foo&Bar'); // або Type::intersection(Foo::class, Bar::class)
 $member->setType(null); // видаляє тип
 ```
@@ -569,7 +573,7 @@ class Demo
 }
 ```
 
-Ви також можете передати параметри на адресу `Literal` і відформатувати їх у коректний PHP-код за допомогою [спеціальних заповнювачів |#method-and-function-body-generator]:
+Ви також можете передати параметри на адресу `Literal` і відформатувати їх у коректний PHP-код за допомогою [спеціальних заповнювачів |#method-and-function-bodies]:
 
 ```php
 new Literal('substr(?, ?)', [$a, $b]);
@@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
 Приведення імен класів .[#toc-class-names-resolving]
 ----------------------------------------------------
 
-**Коли клас є частиною простору імен, він відображається дещо інакше**: всі типи (тобто підказки типів, типи, що повертаються, ім'я батьківського класу,
-реалізовані інтерфейси, використані риси та атрибути) автоматично *розв'язуються* (якщо ви не вимкнете цю функцію, див. нижче).
-Це означає, що ви повинні **використовувати повні імена класів** у визначеннях, а в результуючому коді вони будуть замінені на псевдоніми (відповідно до операторів використання) або повністю кваліфіковані імена:
+**Коли клас є частиною простору імен, він відображається дещо інакше:** всі типи (наприклад, підказки типів, типи повернення, ім'я батьківського класу, реалізовані інтерфейси, використані риси та атрибути) автоматично *розв'язуються* (якщо ви не вимкнете цю опцію, див. нижче).
+Це означає, що ви повинні використовувати **повні імена класів** у визначеннях, і вони будуть замінені псевдонімами (на основі клаузул використання) або повними іменами у результуючому коді:
 
 ```php
 $namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
@@ -777,6 +780,8 @@ function foo()
 }
 ```
 
+**Зверніть увагу:** До файлів не можна додавати додатковий код за межами функцій та класів.
+
 
 Генерувати відповідно до існуючого .[#toc-generating-according-to-existing-ones]
 --------------------------------------------------------------------------------
@@ -838,6 +843,38 @@ $file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
 Якщо вам потрібно маніпулювати глобальним кодом у файлах або окремими операторами в тілах методів, краще використовувати безпосередньо бібліотеку `nikic/php-parser`.
 
 
+Клас Маніпулятор .[#toc-class-manipulator]
+------------------------------------------
+
+Клас [ClassManipulator |api:Nette\PhpGenerator\ClassManipulator] надає інструменти для маніпулювання класами.
+
+```php
+$class = new Nette\PhpGenerator\ClassType('Demo');
+$manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+```
+
+Метод `inheritMethod()` копіює метод з батьківського класу або реалізованого інтерфейсу у ваш клас. Це дозволяє перевизначити метод або розширити його сигнатуру:
+
+```php
+$method = $manipulator->inheritMethod('bar');
+$method->setBody('...');
+```
+
+Метод `inheritProperty()` копіює властивість з батьківського класу у ваш клас. Це корисно, коли ви хочете мати таку саму властивість у своєму класі, але, можливо, з іншим значенням за замовчуванням:
+
+```php
+$property = $manipulator->inheritProperty('foo');
+$property->setValue('new value');
+```
+
+Метод `implementInterface()` автоматично реалізує всі методи з даного інтерфейсу у вашому класі:
+
+```php
+$manipulator->implementInterface(SomeInterface::class);
+// Тепер ваш клас реалізує SomeInterface і включає всі його методи
+```
+
+
 Дампер змінних .[#toc-variables-dumper]
 ---------------------------------------
 
diff --git a/quickstart/bg/@home.texy b/quickstart/bg/@home.texy
index 3f9c74c040..f7bec3d2ea 100644
--- a/quickstart/bg/@home.texy
+++ b/quickstart/bg/@home.texy
@@ -7,7 +7,7 @@
 След първите две глави ще имате свой собствен работещ блог и ще сте готови да публикувате страхотни публикации, въпреки че функциите ще бъдат доста ограничени след приключването на тези две глави. За да направите нещата по-приятни за вашите потребители, трябва да прочетете и следващите глави и да продължите да подобрявате приложението си.
 
 .[tip]
-Този урок предполага, че сте завършили документа [Инсталиране |nette:installation] и успешно сте настроили инструментите си.
+Този урок предполага, че сте завършили документа [Инсталиране |nette:installation] и успешно сте настроили инструментите си. Предполага се също, че разбирате [обектно-ориентираното програмиране в PHP |nette:introduction-to-object-oriented-programming].
 
 Моля, използвайте PHP 8.1 или по-нова версия. Можете да намерите пълното приложение [в GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ http://localhost/nette-blog/www/
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← каталог приложения
-│   ├── <b>Presenters/</b>   ← классы презентеров
-│   │   └── <b>templates/</b>← шаблоны
-│   ├── <b>Router/</b>       ← конфигурация адресов URL
+│   ├── <b>Core/</b>         ← основни необходими класове
+│   ├── <b>UI/</b>           ← презентатори, шаблони и др.
+│   │   └── <b>Home/</b>     ← Каталог на водещите
 │   └── <b>Bootstrap.php</b> ← загрузочный класс Bootstrap
 ├── <b>bin/</b>              ← скрипты для командной строки
 ├── <b>config/</b>           ← конфигурационные файлы
@@ -67,7 +67,7 @@ http://localhost/nette-blog/www/
 Почистване .[#toc-cleanup]
 ==========================
 
-Уеб проектът съдържа начална страница, която можем да премахнем - не се колебайте да замените съдържанието на файла `app/Presenters/templates/Home/default.latte` с текста `Hello world!`.
+Уеб проектът съдържа начална страница, която можем да премахнем - не се колебайте да замените съдържанието на файла `app/UI/Home/default.latte` с текста `Hello world!`.
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ http://localhost/nette-blog/www/
 Tracy (дебъгер) .[#toc-tracy-debugger]
 ======================================
 
-Изключително важен инструмент за разработка е [дебъгер, наречен Tracy. |tracy:] Опитайте се да направите някои грешки във вашия файл `app/Presenters/HomePresenter.php` (например да премахнете къдравата скоба от дефиницията на класа HomePresenter) и вижте какво ще се случи. Ще се появи страница с червен екран и разбираемо описание на грешката.
+Изключително важен инструмент за разработка е [дебъгер, наречен Tracy. |tracy:] Опитайте се да направите някои грешки във вашия файл `app/UI/Home/HomePresenter.php` (например да премахнете къдравата скоба от дефиницията на класа HomePresenter) и вижте какво ще се случи. Ще се появи страница с червен екран и разбираемо описание на грешката.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Трейси ще ви помогне значително да откриете грешките. Обърнете внимание и на плаващата лента Tracy Bar в долния десен ъгъл, която ви информира за важни данни по време на работа.
 
@@ -88,8 +88,7 @@ Tracy (дебъгер) .[#toc-tracy-debugger]
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/bg/authentication.texy b/quickstart/bg/authentication.texy
index 4950637a2b..81d340662e 100644
--- a/quickstart/bg/authentication.texy
+++ b/quickstart/bg/authentication.texy
@@ -28,9 +28,9 @@ Nette автоматично ще създаде услуга в контейн
 
 Нека започнем с формата за вход. Вече знаете как работят формулярите в програмата Presenter. Създайте `SignPresenter` и метод `createComponentSignInForm`. Това трябва да изглежда по следния начин:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -60,9 +60,9 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 Шаблон .[#toc-template]
 -----------------------
 
-Формулярът ще бъде показан в шаблона `app/Presenters/templates/Sign/in.latte`.
+Формулярът ще бъде показан в шаблона `app/UI/Sign/in.latte`.
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Войти</h1>
 
@@ -77,7 +77,7 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 
 Обслужващият модул просто взема потребителското име и паролата, които потребителят е въвел, и ги предава на удостоверителя. След като влезете в системата, ще ви пренасочим към началната страница:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ private function signInFormSucceeded(Form $form, \stdClass $data): void
 
 Ще създадем метод `startup()`, който се изпълнява веднага в началото на [жизнения цикъл на презентатора |application:presenters#Life-Cycle-of-Presenter]. Това пренасочва нерегистрираните потребители към формата за вход.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Скриване на връзки .[#toc-hide-links]
 -------------------------------------
 
-Неоторизиран потребител вече не може да вижда страниците за създаване и редактиране, но все още може да вижда връзките, които сочат към тях. Нека скрием и тях. Една такава връзка се намира на адрес `app/Presenters/templates/Home/default.latte`, като тя трябва да бъде видима само ако потребителят е влязъл в системата.
+Неоторизиран потребител вече не може да вижда страниците за създаване и редактиране, но все още може да вижда връзките, които сочат към тях. Нека скрием и тях. Една такава връзка се намира на адрес `app/UI/Home/default.latte`, като тя трябва да бъде видима само ако потребителят е влязъл в системата.
 
 Можем да го скрием, като използваме *n:атрибута*, наречен `n:if`. Ако изявлението в него е `false`, тогава целият таг `<a>` и съдържанието му няма да бъде показано:
 
@@ -131,15 +131,15 @@ public function startup(): void
 {if $user->isLoggedIn()}<a n:href="Edit:create">Создать пост</a>{/if}
 ```
 
-По същия начин скрийте връзката за редактиране, намираща се на адрес `app/Presenters/templates/Post/show.latte`.
+По същия начин скрийте връзката за редактиране, намираща се на адрес `app/UI/Post/show.latte`.
 
 
 Връзка към формуляра за влизане .[#toc-login-form-link]
 =======================================================
 
-Здравейте, но как да стигнем до страницата за вход? Няма връзка, която да сочи към него. Нека да го добавим към файла с шаблона `app/Presenters/templates/@layout.latte`. Опитайте се да намерите добро място, може да е всяко място, което ви харесва най-много.
+Здравейте, но как да стигнем до страницата за вход? Няма връзка, която да сочи към него. Нека да го добавим към файла с шаблона `app/UI/@layout.latte`. Опитайте се да намерите добро място, може да е всяко място, което ви харесва най-много.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Главная</a></li>
@@ -156,7 +156,7 @@ public function startup(): void
 
 Действието за излизане от системата изглежда по следния начин и тъй като пренасочваме потребителя веднага, няма нужда от шаблон на изгледа:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/bg/comments.texy b/quickstart/bg/comments.texy
index be67b39c24..e8925ef9d7 100644
--- a/quickstart/bg/comments.texy
+++ b/quickstart/bg/comments.texy
@@ -44,7 +44,7 @@ CREATE TABLE `comments` (
 
 Nette има понятие за *компоненти*. **Компонент** е клас или част от кода за многократна употреба, който може да бъде прикрепен към друг компонент. Дори водещият е компонент. Всеки компонент се създава с помощта на фабрика за компоненти. И така, нека дефинираме фабриката за формуляри за коментари в `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // означава Nette\Application\UI\Form
@@ -65,9 +65,9 @@ protected function createComponentCommentForm(): Form
 
 Нека да го обясним малко. Първият ред създава нова инстанция на компонента `Form`. Методите по-долу поставят HTML елементите *input* във формуляра. `->addText` ще се покаже като `<input type=text name=name>`, с `<label>Ваше имя:</label>`. Както вече сте се досетили, `->addTextArea` прикрепя `<textarea>`, а `->addSubmit` добавя `<input type=submit>`. Има и други подобни методи, но това е всичко, което трябва да знаете сега. Можете да [намерите повече информация в документацията |forms:].
 
-След като компонентът на формуляра е дефиниран в презентатора, можем да го визуализираме в шаблона. За да направите това, поставете тага `{control}` в края на шаблона за подробна информация за публикацията в `app/Presenters/templates/Post/show.latte`. Тъй като името на компонента е `commentForm` (то идва от името на метода `createComponentCommentForm`), тагът ще изглежда по следния начин
+След като компонентът на формуляра е дефиниран в презентатора, можем да го визуализираме в шаблона. За да направите това, поставете тага `{control}` в края на шаблона за подробна информация за публикацията в `app/UI/Post/show.latte`. Тъй като името на компонента е `commentForm` (то идва от името на метода `createComponentCommentForm`), тагът ще изглежда по следния начин
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Оставить комментарий</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Това означава "след успешно изпращане на формуляра извикайте метода `commentFormSucceeded` на текущия презентатор". Този метод все още не съществува, затова нека го създадем.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ private function commentFormSucceeded(\stdClass $data): void
 
 Необходимо е да се обяснят още две извиквания на методи. `$this->redirect('this')` буквално пренасочва към текущата страница. Трябва да правите това всеки път, когато формулярът е изпратен, валиден и операцията за обратно извикване е изпълнила това, което е трябвало да направи. Освен това, когато пренасочите страницата след изпращане на формуляра, няма да видите добре познатото съобщение `Вы хотите отправить данные сообщения снова?`, което понякога се вижда в браузъра. (По принцип след изпращане на формуляр чрез метода `POST` винаги трябва да пренасочвате потребителя към действието `GET`).
 
-`$this->flashMessage` има за цел да информира потребителя за резултата от дадена операция. Тъй като пренасочваме, съобщението не може да бъде директно предадено на шаблона и показано. Ето защо има метод за запазване и предоставяне на достъп до него при следващото зареждане на страницата. Съобщенията на Flash се показват в стандартния файл `app/Presenters/templates/@layout.latte` и изглеждат по следния начин
+`$this->flashMessage` има за цел да информира потребителя за резултата от дадена операция. Тъй като пренасочваме, съобщението не може да бъде директно предадено на шаблона и показано. Ето защо има метод за запазване и предоставяне на достъп до него при следващото зареждане на страницата. Съобщенията на Flash се показват в стандартния файл `app/UI/@layout.latte` и изглеждат по следния начин
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer използва чужди ключове, за да о
 
 Както си спомняте, предадохме променливата `$post` на шаблона в `PostPresenter::renderShow()` и сега искаме да изброим всички коментари, които имат колона `post_id`, равна на нашата `$post->id`. Можете да направите това, като се обадите на `$post->related('comments')`. Всичко е толкова просто. Разгледайте получения код.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 В шаблона:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Комментарии</h2>
 
diff --git a/quickstart/bg/creating-posts.texy b/quickstart/bg/creating-posts.texy
index 540c927979..a65eb4f1bd 100644
--- a/quickstart/bg/creating-posts.texy
+++ b/quickstart/bg/creating-posts.texy
@@ -20,11 +20,11 @@
 Нов водещ .[#toc-new-presenter]
 ===============================
 
-Дайте име на новия презентатор `EditPresenter` и го запишете на `app/Presenters/EditPresenter.php`. Той също така трябва да се свърже с базата данни, така че тук отново ще напишем конструктор, който ще изисква свързване с базата данни:
+Дайте име на новия презентатор `EditPresenter` и го запишете на `app/UI/Edit/`. Той също така трябва да се свърже с базата данни, така че тук отново ще напишем конструктор, който ще изисква свързване с базата данни:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ final class EditPresenter extends Nette\Application\UI\Presenter
 
 Сега добавете този метод в `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ protected function createComponentPostForm(): Form
 
 Нека да добавим метод за обработка:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -86,9 +86,9 @@ private function postFormSucceeded(array $data): void
 Страница за създаване на нова публикация .[#toc-page-for-creating-a-new-post]
 =============================================================================
 
-Нека просто създадем шаблон (`app/Presenters/templates/Edit/create.latte`):
+Нека просто създадем шаблон (`app/UI/Edit/create.latte`):
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>Новый пост</h1>
 
@@ -105,7 +105,7 @@ private function postFormSucceeded(array $data): void
 
 Вероятно вече знаете как да добавите връзка към `EditPresenter` и нейното действие `create`. Опитайте.
 
-Просто добавете към файла `app/Presenters/templates/Home/default.latte`:
+Просто добавете към файла `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Создать пост</a>
@@ -119,12 +119,12 @@ private function postFormSucceeded(array $data): void
 
 Ще добавим нова страница `edit` към `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Пост не найден');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 И създайте шаблон `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Редактирование поста</h1>
 
@@ -146,15 +146,15 @@ public function renderEdit(int $postId): void
 
 И актуализирайте метода `postFormSucceeded`, който ще може да добавя нова публикация (както сега) или да редактира съществуващите:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Ако е посочен `postId`, това означава, че публикацията се редактира. В този случай ще проверим дали публикацията действително съществува и ако е така, ще я актуализираме в базата данни. Ако не е посочен `postId`, това означава, че ще бъде добавена нова публикация.
+Ако е посочен `id`, това означава, че публикацията се редактира. В този случай ще проверим дали публикацията действително съществува и ако е така, ще я актуализираме в базата данни. Ако не е посочен `id`, това означава, че ще бъде добавена нова публикация.
 
-Но откъде идва `postId`? Това е параметърът, който се предава на метода `renderEdit`.
+Но откъде идва `id`? Това е параметърът, който се предава на метода `renderEdit`.
 
-Сега можете да добавите връзка за промяна на публикацията в шаблона `app/Presenters/templates/Post/show.latte`:
+Сега можете да добавите връзка за промяна на публикацията в шаблона `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Изменить пост</a>
diff --git a/quickstart/bg/home-page.texy b/quickstart/bg/home-page.texy
index fcb701ca5b..afb31b3289 100644
--- a/quickstart/bg/home-page.texy
+++ b/quickstart/bg/home-page.texy
@@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
 
 Сега, след като базата данни е създадена и в нея има няколко публикации, е време да ги покажем на нашата нова блестяща страница.
 
-Първо, трябва да укажем на приложението коя база данни да използва. Конфигурацията на връзката с базата данни се съхранява във файла `config/local.neon`. Създайте връзка DSN((Име на източника на данни)) и вашите пълномощия. Това трябва да изглежда по следния начин:
+Първо, трябва да укажем на приложението коя база данни да използва. Конфигурацията на връзката с базата данни се съхранява във файла `config/common.neon`. Създайте връзка DSN((Име на източника на данни)) и вашите пълномощия. Това трябва да изглежда по следния начин:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *укажите здесь имя пользователя*
@@ -78,20 +78,17 @@ database:
 .[note]
 Не забравяйте да правите отстъпи, когато редактирате този файл. [Форматът NEON |neon:format] приема както интервали, така и табулации, но не и двете заедно! В конфигурационния файл в уеб проекта по подразбиране се използва таблично представяне.
 
-Цялата конфигурация се съхранява в `config/` във файловете `common.neon` и `local.neon`. Файлът `common.neon` съдържа глобалната конфигурация на приложението, докато `local.neon` съдържа само специфични за средата параметри (например разликата между сървъра за разработка и производствения сървър).
-
 
 Осъществяване на връзката с базата данни .[#toc-injecting-the-database-connection]
 ==================================================================================
 
-Презентаторът (намиращ се на адрес `app/Presenters/HomePresenter.php`), който ще изписва статиите, трябва да се свърже с базата данни. За да направите това, модифицирайте конструктора по следния начин:
+Презентаторът (намиращ се на адрес `app/UI/Home/HomePresenter.php`), който ще изписва статиите, трябва да се свърже с базата данни. За да направите това, модифицирайте конструктора по следния начин:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ final class HomePresenter extends Nette\Application\UI\Presenter
 
 Нека сега да извлечем публикациите от базата данни и да ги подадем към шаблона, който след това ще визуализира HTML кода. За това е предназначен така нареченият метод *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Сега презентаторът има един метод за визуализация `renderDefault()`, който предава данните на изглед, наречен `default`. Шаблоните Preenter могат да бъдат намерени в `app/Presenters/templates/{PresenterName}/{viewName}.latte`, така че в този случай шаблонът ще се намира в `app/Presenters/templates/Home/default.latte`. В шаблона вече е налична променливата `$posts`, която съдържа публикациите от базата данни.
+Сега презентаторът има един метод за визуализация `renderDefault()`, който предава данните на изглед, наречен `default`. Шаблоните Preenter могат да бъдат намерени в `app/UI/{PresenterName}/{viewName}.latte`, така че в този случай шаблонът ще се намира в `app/UI/Home/default.latte`. В шаблона вече е налична променливата `$posts`, която съдържа публикациите от базата данни.
 
 
 Шаблон .[#toc-template]
@@ -128,17 +125,17 @@ public function renderDefault(): void
 
 Има общ шаблон за цялата страница (наречен *layout*, със заглавие, стилове, колонтитул и т.н.), както и специфични шаблони за всеки изглед (например за показване на списък със записи в блога), които могат да отменят някои части от шаблона за оформление.
 
-По подразбиране шаблонът за оформление се намира във файла `app/Presenters/templates/@layout.latte`, който съдържа:
+По подразбиране шаблонът за оформление се намира във файла `app/UI/@layout.latte`, който съдържа:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
 ```
 
-`{include content}` вмъква блок с име `content` в главния шаблон. Можете да го определите в шаблоните на всеки изглед. В нашия случай ще редактираме файла `app/Presenters/templates/Home/default.latte` по следния начин
+`{include content}` вмъква блок с име `content` в главния шаблон. Можете да го определите в шаблоните на всеки изглед. В нашия случай ще редактираме файла `app/UI/Home/default.latte` по следния начин
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Привет, мир!
 {/block}
@@ -148,7 +145,7 @@ public function renderDefault(): void
 
 Нека покажем записите в блога - за целта редактираме шаблона по следния начин:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1 n:block="title">Мой блог</h1>
 
@@ -166,7 +163,7 @@ public function renderDefault(): void
 
 Ако опресните браузъра си, ще видите списък със записите в блога си. Списъкът не е много изискан или цветен, така че не се колебайте да добавите някой [блестящ CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] към `www/css/style.css`, а след това да поставите връзка към този файл в оформлението (файл `@layout.latte`):
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ public function renderDefault(): void
 
 И още нещо. Можем да направим кода малко по-кратък и следователно по-прост. Можем да заменим *tags Latte* с *n:attributes* по следния начин:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/bg/model.texy b/quickstart/bg/model.texy
index 00e8a1f6b2..f8ede56696 100644
--- a/quickstart/bg/model.texy
+++ b/quickstart/bg/model.texy
@@ -36,9 +36,9 @@ final class PostFacade
 
 Нека отидем във файла `HomePresenter.php`, който ще редактираме, за да се отървем от зависимостта от `Nette\Database\Explorer`, като я заменим с новата зависимост на създадения от нас клас.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/bg/single-post.texy b/quickstart/bg/single-post.texy
index 745d846943..4a35ac958d 100644
--- a/quickstart/bg/single-post.texy
+++ b/quickstart/bg/single-post.texy
@@ -5,13 +5,13 @@
 Нека да добавим още една страница към нашия блог, за да покажем съдържанието на един конкретен запис в блога.
 
 
-Трябва да създадем нов метод за визуализация, който да вземе един конкретен запис в блога и да го предаде на шаблона. Това визуализиране в `HomePresenter` не е много приятно, защото става дума за запис в блог, а не за начална страница. Така че нека създадем нов клас `PostPresenter` и да го поставим в `app/Presenters`. Тя ще се нуждае от връзка с база данни, така че поставете отново кода за инжектиране на зависимости* там.
+Трябва да създадем нов метод за визуализация, който да вземе един конкретен запис в блога и да го предаде на шаблона. Това визуализиране в `HomePresenter` не е много приятно, защото става дума за запис в блог, а не за начална страница. Така че нека създадем нов клас `PostPresenter` и да го поставим в `app/UI/Post/`. Тя ще се нуждае от връзка с база данни, така че поставете отново кода за инжектиране на зависимости* там.
 
 `PostPresenter` трябва да изглежда по следния начин:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Трябва да зададем правилното пространство от имена `App\Presenters` за нашия презентатор. Това зависи от [картографирането на водещия |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Трябва да зададем правилното пространство от имена `App\UI\Post` за нашия презентатор. Това зависи от [картографирането на водещия |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Методът `renderShow` изисква един аргумент - ID на публикацията на водещия. След това той зарежда тази публикация от базата данни и предава резултата на шаблона.
 
 В шаблона `Home/default.latte` добавяме връзка към действието `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 Можем да напишем същото накратко, като използваме n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -59,11 +59,11 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 
 
-Шаблонът за действието `Post:show` все още не съществува. Можем да отворим връзка към тази публикация. [Tracy |tracy:] ще покаже грешка, че `app/Presenters/templates/Post/show.latte` не съществува. Ако видите друг отчет за грешка, вероятно трябва да активирате mod_rewrite на уеб сървъра си.
+Шаблонът за действието `Post:show` все още не съществува. Можем да отворим връзка към тази публикация. [Tracy |tracy:] ще покаже грешка, че `app/UI/Post/show.latte` не съществува. Ако видите друг отчет за грешка, вероятно трябва да активирате mod_rewrite на уеб сървъра си.
 
 Затова ще създадем `Post/show.latte` с това съдържание:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← вернуться к списку постов</a></p>
@@ -89,7 +89,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Просто казано, той *заменя* блок, наречен `title`. Блокът е дефиниран в *шаблона за оформление* (`/app/Presenters/templates/@layout.latte:11`) и, както в случая на пренаписване на ООП, се пренаписва тук. Следователно `<title>` страници ще съдържа заглавието на показаната публикация. Премахнахме заглавието на страницата и всичко, от което се нуждаехме, беше `n:block="title"`. Чудесно, нали?
+Просто казано, той *заменя* блок, наречен `title`. Блокът е дефиниран в *шаблона за оформление* (`/app/UI/@layout.latte:11`) и, както в случая на пренаписване на ООП, се пренаписва тук. Следователно `<title>` страници ще съдържа заглавието на показаната публикация. Премахнахме заглавието на страницата и всичко, от което се нуждаехме, беше `n:block="title"`. Чудесно, нали?
 
 Петият и последен ред на шаблона показва пълното съдържание на публикацията ви.
 
@@ -97,14 +97,14 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 Проверка на ID на публикацията .[#toc-checking-post-id]
 =======================================================
 
-Какво ще стане, ако някой промени URL адреса и вмъкне несъществуващ `postId`? Трябва да предоставим на потребителя хубава страница за грешка "Страницата не е намерена". Нека да актуализираме метода `render` във файла `PostPresenter.php`:
+Какво ще стане, ако някой промени URL адреса и вмъкне несъществуващ `id`? Трябва да предоставим на потребителя хубава страница за грешка "Страницата не е намерена". Нека да актуализираме метода `render` във файла `PostPresenter.php`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Страница не найдена!');
 	}
diff --git a/quickstart/cs/@home.texy b/quickstart/cs/@home.texy
index 6cf314d7eb..83220197bc 100644
--- a/quickstart/cs/@home.texy
+++ b/quickstart/cs/@home.texy
@@ -7,7 +7,7 @@ Poznejme spolu Nette Framework, při vytváření jednoduchého blogu s komentá
 Již po prvních dvou kapitolách budeme mít svůj vlastní funkční blog a budeme moci publikovat své skvělé příspěvky, i když funkce budou zatím do značné míry omezeny. Měli byste si přečíst také následující kapitoly, kde si naprogramujeme přidávání komentářů, editování článků a na závěr blog zabezpečíme.
 
 .[tip]
-Tento návod předpokládá, že jste přečetli stránku [Instalace |nette:installation] a úspěšně si připravili potřebné nástroje.
+Tento návod předpokládá, že jste přečetli stránku [Instalace |nette:installation] a úspěšně si připravili potřebné nástroje. Také předpokládá, že rozumíte [objektově orientovanému programování v PHP |nette:introduction-to-object-oriented-programming].
 
 Používejte prosím PHP 8.1 nebo novější. Kompletní aplikaci najdete [na GitHubu |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Web Project má následující strukturu:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← adresář s aplikací
-│   ├── <b>Presenters/</b>   ← třídy presenterů
-│   │   └── <b>templates/</b>← šablony
-│   ├── <b>Router/</b>       ← konfigurace URL adres
+│   ├── <b>Core/</b>         ← základní třídy nutné pro chod
+│   ├── <b>UI/</b>           ← presentery, šablony & spol.
+│   │   └── <b>Home/</b>     ← adresář presenteru Home
 │   └── <b>Bootstrap.php</b> ← zaváděcí třída Bootstrap
 ├── <b>bin/</b>              ← skripty spouštěné z příkazové řádky
 ├── <b>config/</b>           ← konfigurační soubory
@@ -67,7 +67,7 @@ Nejdůležitější složka je pro nás `app/`. Zde nalezneme soubor `Bootstrap.
 Úklid
 =====
 
-Web Project obsahuje úvodní stránku, kterou smažeme předtím, než začneme něco programovat. Bez obav tedy nahradíme obsah souboru `app/Presenters/templates/Home/default.latte` za "Hello world!".
+Web Project obsahuje úvodní stránku, kterou smažeme předtím, než začneme něco programovat. Bez obav tedy nahradíme obsah souboru `app/UI/Home/default.latte` za "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Web Project obsahuje úvodní stránku, kterou smažeme předtím, než začneme
 Tracy (debugger)
 ================
 
-Extrémně důležitý nástroj pro vývoj je [ladicí nástroj Tracy |tracy:]. Vyzkoušejte si vyvolání nějaké chyby v souboru `app/Presenters/HomePresenter.php` (např. odstraněním složené závorky v definici třídy HomePresenter) a podívejte se, co se stane. Vyskočí oznamovací stránka, která chybu srozumitelně popisuje.
+Extrémně důležitý nástroj pro vývoj je [ladicí nástroj Tracy |tracy:]. Vyzkoušejte si vyvolání nějaké chyby v souboru `app/UI/Home/HomePresenter.php` (např. odstraněním složené závorky v definici třídy HomePresenter) a podívejte se, co se stane. Vyskočí oznamovací stránka, která chybu srozumitelně popisuje.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy nám ohromně pomůže, až budeme hledat chyby v aplikaci. Také si všimněte plovoucího Tracy Baru v pravém dolním rohu obrazovky, který obsahuje informace z běhu aplikace.
 
@@ -88,8 +88,7 @@ V produkčním módu je Tracy samozřejmě vypnuta a nezobrazuje žádné citliv
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/cs/authentication.texy b/quickstart/cs/authentication.texy
index 82dd6e5861..b9c05d618b 100644
--- a/quickstart/cs/authentication.texy
+++ b/quickstart/cs/authentication.texy
@@ -28,9 +28,9 @@ Nyní máme autentifikaci připravenu a musíme připravit uživatelské rozhran
 
 Začneme s přihlašovacím formulářem. Již víme, jak formuláře v presenterech fungují. Vytvoříme si tedy presenter `SignPresenter` a zapíšeme metodu `createComponentSignInForm`. Měl by vypadat nějak takto:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Jsou zde políčka pro uživatelské jméno a heslo.
 
 Formulář se bude vykreslovat v šabloně `in.latte`:
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Přihlášení</h1>
 
@@ -77,7 +77,7 @@ Dále doplníme callback pro přihlášení uživatele, který bude volán hned
 
 Callback pouze převezme uživatelské jméno a heslo, které uživatel vyplnil a předá je authenticatoru. Po přihlášení přesměrujeme na úvodní stránku.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Zabezpečíme formulář pro přidávání a editování příspěvků. Ten je d
 
 Vytvoříme metodu `startup()`, která se spouští ihned na začátku [životního cyklu presenteru|application:presenters#zivotni-cyklus-presenteru]. Ta přesměruje nepřihlášené uživatele na formulář s přihlášením.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Skrytí odkazů
 -------------
 
-Neautorizovaný uživatel už nemůže vidět stránku *create* ani *edit*, ale stále na ně může vidět odkazy. Ty bychom měli také schovat. Jeden takový odkaz je v šabloně `app/Presenters/templates/Home/default.latte` a měli by jej vidět pouze přihlášení uživatelé.
+Neautorizovaný uživatel už nemůže vidět stránku *create* ani *edit*, ale stále na ně může vidět odkazy. Ty bychom měli také schovat. Jeden takový odkaz je v šabloně `app/UI/Home/default.latte` a měli by jej vidět pouze přihlášení uživatelé.
 
 Můžeme jej schovat využitím *n:atributu* jménem `n:if`. Pokud je tato podmínka `false`, celý tag `<a>`, včetně obsahu, zůstane skrytý.
 
@@ -131,7 +131,7 @@ což je zkratka následujícího zápisu (neplést s `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Vytvořit příspěvek</a>{/if}
 ```
 
-Stejným způsobem skryjeme také odkaz v šabloně `app/Presenters/templates/Post/show.latte`.
+Stejným způsobem skryjeme také odkaz v šabloně `app/UI/Post/show.latte`.
 
 
 Odkaz na přihlášení
@@ -139,7 +139,7 @@ Odkaz na přihlášení
 
 Jak se vlastně dostaneme na přihlašovací stránku? Není zde žádný odkaz, který by na ni vedl. Tak si ho tedy přidáme do šablony `@layout.latte`. Pokuste se najít vhodné místo - může to být téměř kdekoliv.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Články</a></li>
@@ -156,7 +156,7 @@ Pokud není uživatel přihlášen, zobrazí se odkaz "Přihlásit". V opačném
 
 Jelikož uživatele po odhlášení okamžitě přesměrujeme, není potřeba žádná šablona. Odhlášení vypadá takto:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/cs/comments.texy b/quickstart/cs/comments.texy
index c84329e242..1792588cd8 100644
--- a/quickstart/cs/comments.texy
+++ b/quickstart/cs/comments.texy
@@ -44,7 +44,7 @@ Prvně musíme vytvořit formulář, který umožní uživatelům příspěvky k
 
 Nette Framework využívá koncept *komponent*. **Komponenta** je znovupoužitelná třída, nebo část kódu, který může být přiložen k jiné komponentě. Dokonce i presenter je komponenta. Každá komponenta je vytvořena prostřednictvím továrny. Vytvoříme si tedy továrnu pro formulář na komentáře v presenteru `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // means Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Pojďme si to zase trochu vysvětlit. První řádka vytvoří novou instanci ko
 
 Pokud je již formulář definován v presenteru, můžeme ho vykreslit (zobrazit) v šabloně. To uděláme umístěním značky `{control}` na konec šablony, která vykresluje jeden konkrétní příspěvek, do `Post/show.latte`. Protože se komponenta jmenuje `commentForm` (název je odvozen od názvu metody `createComponentCommentForm`), značka bude vypadat takto:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Vložte nový příspěvek</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Předchozí zápis znamená "po úspěšném odeslání formuláře zavolej metodu `commentFormSucceeded` ze současného presenteru". Tato metoda však ještě neexistuje. Pojďme ji tedy vytvořit:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Tato nová metoda má jeden argument, což je instance formuláře, který byl o
 
 Ještě jsou zde další dvě metody, které si zaslouží vysvětlit. Redirect metoda doslova přesměrovává zpět na aktuální stránku. Toto je vhodné udělat po každém odeslání formuláře, pokud obsahoval validní data a callback provedl operaci tak jak měl. A taky pokud přesměrujeme stránku po odeslání formuláře, neuvidíme dobře známou hlášku `Chcete odeslat data z formuláře znovu?`, kterou občas můžeme v prohlížeči spatřit. (Obecně platí, že po odeslání formuláře metodou `POST` by mělo následovat vždy přesměrování na `GET` akci.)
 
-Metoda `flashMessage` je pro informování uživatele o výsledku nějaké operace. Protože přesměrováváme, zpráva nemůže být jednoduše předána šabloně a vykreslena. Proto je zde tato metoda, která si tuto zprávu uloží a zpřístupní ji při dalším načtení stránky. Flash zprávy jsou vykreslovány v hlavní šabloně `app/Presenters/templates/@layout.latte` a vypadá to takto:
+Metoda `flashMessage` je pro informování uživatele o výsledku nějaké operace. Protože přesměrováváme, zpráva nemůže být jednoduše předána šabloně a vykreslena. Proto je zde tato metoda, která si tuto zprávu uloží a zpřístupní ji při dalším načtení stránky. Flash zprávy jsou vykreslovány v hlavní šabloně `app/UI/@layout.latte` a vypadá to takto:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer používá cizí klíče pro vyřešení vzájemného vz
 
 Jak si jistě pamatujete, do šablony jsme předali proměnnou `$post` pomocí metody `PostPresenter::renderShow()` a nyní chceme iterovat přes všechny komentáře, které mají hodnotu sloupce `post_id` shodnou s `$post->id`. Toho můžeme docílit voláním `$post->related('comments')`. Ano, takhle jednoduše. Podívejme se na výsledný kód:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 A šablonu:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Komentáře</h2>
 
diff --git a/quickstart/cs/creating-posts.texy b/quickstart/cs/creating-posts.texy
index a0d2071fac..649e1c8674 100644
--- a/quickstart/cs/creating-posts.texy
+++ b/quickstart/cs/creating-posts.texy
@@ -20,11 +20,11 @@ Později také přidáme přihlašování a přidávání příspěvků umožní
 Nový presenter
 ==============
 
-Nový presenter nazveme `EditPresenter` a uložíme do `app/Presenters/EditPresenter.php`. Také se potřebuje připojit k databázi, takže zde opět napíšeme konstruktor, který bude vyžadovat databázové připojení:
+Nový presenter nazveme `EditPresenter` a uložíme do `app/UI/Edit/`. Také se potřebuje připojit k databázi, takže zde opět napíšeme konstruktor, který bude vyžadovat databázové připojení:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Formuláře a komponenty jsme si již vysvětlili při vytváření komentářů
 
 Nyní přidejme tuto metodu do presenteru `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Ukládání nového příspěvku z formuláře
 
 Pokračujeme přidáním metody, která zpracuje data z formuláře:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Stránka pro vytvoření nového příspěvku
 
 Vytvořme nyní šablonu `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>Nový příspěvek</h1>
 
@@ -105,7 +105,7 @@ Odkaz na vytváření příspěvků
 
 Pravděpodobně již víte jak přidat odkaz na `EditPresenter` a jeho akci `create`. Vyzkoušejte si to.
 
-Stačí do souboru `app/Presenters/templates/Home/default.latte` přidat:
+Stačí do souboru `app/UI/Home/default.latte` přidat:
 
 ```latte
 <a n:href="Edit:create">Napsat nový příspěvek</a>
@@ -119,12 +119,12 @@ Nyní přidáme také možnost editace příspěvku. Bude to velmi jednoduché.
 
 Přidáme novou stránku `edit` do presenteru `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 A vytvoříme další šablonu `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Upravit příspěvek</h1>
 
@@ -146,15 +146,15 @@ A vytvoříme další šablonu `Edit/edit.latte`:
 
 A upravíme metodu `postFormSucceeded`, která bude schopna jednak přidat nový článek (tak jako to dělá teď) a také již existující článek editovat:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Pokud je k dispozici parametr `postId`, znamená to, že budeme upravovat příspěvek. V tom případě ověříme, že požadovaný příspěvek opravdu existuje a pokud ano, aktualizujeme jej v databázi. Pokud parametr `postId` není k dispozici, pak to znamená, že by měl být nový příspěvek přidán.
+Pokud je k dispozici parametr `id`, znamená to, že budeme upravovat příspěvek. V tom případě ověříme, že požadovaný příspěvek opravdu existuje a pokud ano, aktualizujeme jej v databázi. Pokud parametr `id` není k dispozici, pak to znamená, že by měl být nový příspěvek přidán.
 
-Kde se však onen parametr `postId` vezme? Jedná se o parametr, který byl vložen do metody `renderEdit`.
+Kde se však onen parametr `id` vezme? Jedná se o parametr, který byl vložen do metody `renderEdit`.
 
-Nyní můžeme přidat odkaz do šablony `app/Presenters/templates/Post/show.latte`:
+Nyní můžeme přidat odkaz do šablony `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Upravit příspěvek</a>
diff --git a/quickstart/cs/home-page.texy b/quickstart/cs/home-page.texy
index b1c620ae4e..93f9154592 100644
--- a/quickstart/cs/home-page.texy
+++ b/quickstart/cs/home-page.texy
@@ -66,9 +66,9 @@ Připojení k databázi
 
 Nyní, když je již databáze vytvořena a máme v ní uloženo pár článků, je ten správný čas zobrazit je na naší krásné nové stránce.
 
-Prvně musíme aplikaci říct, jakou databázi má použít. Připojení k databázi nastavíme v souboru `config/local.neon` pomocí DSN((Data Source Name)) a přihlašovacích údajů. Mělo by to vypadat nějak takto:
+Prvně musíme aplikaci říct, jakou databázi má použít. Připojení k databázi nastavíme v souboru `config/common.neon` pomocí DSN((Data Source Name)) a přihlašovacích údajů. Mělo by to vypadat nějak takto:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *zde vložte jméno uživatele*
@@ -78,20 +78,17 @@ database:
 .[note]
 Při editování tohoto souboru dávejte pozor na odsazení řádků. Formát [NEON |neon:format] akceptuje jak odsazení pomocí mezer, tak odsazení pomocí tabulátorů, ale ne obojí zároveň. Výchozí konfigurační soubor ve Web Projectu využívá tabulátory.
 
-Veškerá konfigurace, včetně konfigurace databáze, je uložena v adresáři `/config/` v souborech `common.neon` a `local.neon`. Soubor `common.neon` obsahuje globální nastavení aplikace a `local.neon` pouze ty parametry, které jsou specifické pro aktuální prostředí (rozdíl mezi vývojovým a produkčním serverem apod.).
-
 
 Předání databázového spojení
 ============================
 
 Presenter `HomePresenter`, který se bude starat o výpis článků, potřebuje připojení k databázi. Pro jeho získání využijeme konstruktor, který bude vypadat takto:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Načítání příspěvků z databáze
 
 Nyní načteme příspěvky z databáze a pošleme je do šablony, která je následně vykreslí jako HTML kód. Pro tohle je určena takzvaná *render* metoda:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Presenter nyní obsahuje jednu renderovací metodu `renderDefault()`, která předává data z databáze do šablony (View). Šablony jsou umístěny v `app/Presenters/templates/{PresenterName}/{viewName}.latte`, takže v tomto případě je šablona umístěna v `app/Presenters/templates/Home/default.latte`. V šabloně nyní bude k dispozici proměnná `$posts`, ve které jsou příspěvky získané z databáze.
+Presenter nyní obsahuje jednu renderovací metodu `renderDefault()`, která předává data z databáze do šablony (View). Šablony jsou umístěny v `app/UI/{PresenterName}/{viewName}.latte`, takže v tomto případě je šablona umístěna v `app/UI/Home/default.latte`. V šabloně nyní bude k dispozici proměnná `$posts`, ve které jsou příspěvky získané z databáze.
 
 
 Šablona
@@ -128,9 +125,9 @@ Presenter nyní obsahuje jednu renderovací metodu `renderDefault()`, která př
 
 Pro celou webovou stránku máme k dispozici hlavní šablonu (která se jmenuje *layout*, obsahuje hlavičku, styly, patičku,...) a dále konkrétní šablony pro každý pohled (View) (např. pro zobrazení příspěvků na blogu), které mohou přepsat některé části hlavní šablony.
 
-Ve výchozím stavu je layout šablona umístěna v `app/Presenters/templates/@layout.latte` a obsahuje:
+Ve výchozím stavu je layout šablona umístěna v `app/UI/@layout.latte` a obsahuje:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Ve výchozím stavu je layout šablona umístěna v `app/Presenters/templates/@l
 
 Zápis `{include content}` vkládá do hlavní šablony blok s názvem `content`. Ten budeme definovat v šablonách jednotlivých pohledů (View). V našem případě soubor `Home/default.latte` upravíme následovně:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Tímto jsme nadefinovali [blok |latte:tags#block] *content*, který bude vložen
 
 Pojďme zobrazit příspěvky z blogu - šablonu upravíme následovně:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>Můj blog</h1>
 
@@ -166,7 +163,7 @@ Pojďme zobrazit příspěvky z blogu - šablonu upravíme následovně:
 
 Pokud obnovíme prohlížeč, uvidíme výpis všech příspěvků. Výpis zatím není moc hezký, ani barevný, proto můžeme do souboru `www/css/style.css` přidat pár [CSS stylů |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a zalinkovat jej v layoutu:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Zápisu `|date:` říkáme filtr. Filtry jsou určeny k formátování výstupu.
 
 Ještě jedna věc. Předchozí kód můžeme zkrátit a zjednodušit. Toho docílíme záměnou *Latte tagů* za *n:atributy*:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>Můj blog</h1>
 
diff --git a/quickstart/cs/model.texy b/quickstart/cs/model.texy
index 21dacab887..e4a335d0d6 100644
--- a/quickstart/cs/model.texy
+++ b/quickstart/cs/model.texy
@@ -36,9 +36,9 @@ Ve třídě si pomocí konstruktoru necháme předat databázový Explorer:[api:
 
 Přepneme se na `HomePresenter`, který upravíme tak, že se zbavíme závislosti na `Nette\Database\Explorer` a nahradíme za novou závislost na naší nové třídě.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/cs/single-post.texy b/quickstart/cs/single-post.texy
index d0edcb0654..9ff3f3dcd2 100644
--- a/quickstart/cs/single-post.texy
+++ b/quickstart/cs/single-post.texy
@@ -5,13 +5,13 @@ Stránka s příspěvkem
 Nyní si vytvoříme další stránku blogu, která bude zobrazovat jeden konkrétní příspěvek.
 
 
-Musíme si vytvořit novou render metodu, která získá jeden konkrétní článek a předá jej do šablony. Mít tuto metodu v `HomePresenter` není moc hezké, protože se bavíme o článku a ne úvodní stránce. Vytvořme si tedy `PostPresenter` v `app/Presenters`. Tento presenter se také potřebuje připojit k databázi, takže zde opět napíšeme konstruktor, který bude vyžadovat databázové připojení.
+Musíme si vytvořit novou render metodu, která získá jeden konkrétní článek a předá jej do šablony. Mít tuto metodu v `HomePresenter` není moc hezké, protože se bavíme o článku a ne úvodní stránce. Vytvořme si tedy `PostPresenter` v `app/UI/Post/`. Tento presenter se také potřebuje připojit k databázi, takže zde opět napíšeme konstruktor, který bude vyžadovat databázové připojení.
 
 `PostPresenter` by mohl tedy vypadat takto:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Nesmíme zapomenout uvést správný namespace `App\Presenters`, který podléhá nastavení [mapování presenterů |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Nesmíme zapomenout uvést správný namespace `App\UI\Post`, který podléhá nastavení [mapování presenterů |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Metoda `renderShow` vyžaduje jeden argument - ID jednoho konkrétního článku, který má být zobrazen. Poté tento článek načte z databáze a předá ho do šablony.
 
 Do šablony `Home/default.latte` vložíme odkaz na akci `Post:show`.
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Značka `{link}` generuje URL adresu, která směřuje na akci `Post:show`. Tak
 
 Totéž můžeme zapsat zkráceně pomocí n:atributu:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Pro akci `Post:show` však ještě neexistuje šablona. Můžeme si vyzkoušet o
 
 Vytvoříme tedy šablonu `Post/show.latte` s tímto obsahem:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← zpět na výpis příspěvků</a></p>
@@ -89,7 +89,7 @@ Třetí řádka formátuje výpis data pomocí filtru, který už známe.
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Jednoduše řečeno, tento blok předefinovává blok s názvem `title`. Tento blok je již definován v hlavní *layout* šabloně (`/app/Presenters/templates/@layout.latte:11`) a tak jako u překrývání metod v OOP, úplně stejně se tento blok v hlavní šabloně překryje. Takže `<title>` stránky nyní obsahuje titulek zobrazeného příspěvku a stačilo nám k tomu použít pouze jednoho jednoduchého atributu `n:block="title"`. Skvělé, že?
+Jednoduše řečeno, tento blok předefinovává blok s názvem `title`. Tento blok je již definován v hlavní *layout* šabloně (`/app/UI/@layout.latte:11`) a tak jako u překrývání metod v OOP, úplně stejně se tento blok v hlavní šabloně překryje. Takže `<title>` stránky nyní obsahuje titulek zobrazeného příspěvku a stačilo nám k tomu použít pouze jednoho jednoduchého atributu `n:block="title"`. Skvělé, že?
 
 Pátá a poslední řádka šablony zobrazuje celý obsah jednoho konkrétního příspěvku.
 
@@ -97,14 +97,14 @@ Pátá a poslední řádka šablony zobrazuje celý obsah jednoho konkrétního
 Kontrola ID příspěvku
 =====================
 
-Co se stane, když někdo změní ID v URL a vloží nějaké neexistující `postId`? Měli bychom uživateli nabídnout pěknou chybu typu "stránka nebyla nalezena". Pozměníme tedy trošku render metodu v `PostPresenter`:
+Co se stane, když někdo změní ID v URL a vloží nějaké neexistující `id`? Měli bychom uživateli nabídnout pěknou chybu typu "stránka nebyla nalezena". Pozměníme tedy trošku render metodu v `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Stránka nebyla nalezena');
 	}
diff --git a/quickstart/de/@home.texy b/quickstart/de/@home.texy
index e9d1289a19..61c7f0bea2 100644
--- a/quickstart/de/@home.texy
+++ b/quickstart/de/@home.texy
@@ -7,7 +7,7 @@ Lernen Sie das Nette Framework kennen, indem Sie einen einfachen Blog mit Kommen
 Nach den ersten beiden Kapiteln haben Sie Ihren eigenen funktionierenden Blog und können Ihre tollen Beiträge veröffentlichen, auch wenn der Funktionsumfang nach Abschluss dieser beiden Kapitel ziemlich eingeschränkt ist. Um die Dinge für Ihre Nutzer schöner zu machen, sollten Sie auch die folgenden Kapitel lesen und Ihre Anwendung weiter verbessern.
 
 .[tip]
-In diesem Tutorial wird davon ausgegangen, dass Sie das Dokument [Installation |nette:installation] abgeschlossen und Ihr Tooling erfolgreich eingerichtet haben.
+Dieses Tutorial setzt voraus, dass Sie das Dokument [Installation |nette:installation] abgeschlossen und Ihr Tooling erfolgreich eingerichtet haben. Außerdem wird vorausgesetzt, dass Sie mit der [objektorientierten Programmierung in PHP |nette:introduction-to-object-oriented-programming] vertraut sind.
 
 Bitte verwenden Sie PHP 8.1 oder höher. Sie finden die vollständige Anwendung [auf GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Web Project hat die folgende Struktur:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← Anwendungsverzeichnis
-│   ├── <b>Presenters/</b>   ← Presenter-Klassen
-│   │   └── <b>templates/</b>← Vorlagen
-│   ├── <b>Router/</b>       ← Konfiguration von URL-Adressen
+│   ├── <b>Core/</b>         ← grundlegende notwendige Klassen
+│   ├── <b>UI/</b>           ← Presenter, Vorlagen & Co.
+│   │   └── <b>Home/</b>     ← Home Presenter Verzeichnis
 │   └── <b>Bootstrap.php</b> ← bootende Klasse Bootstrap
 ├── <b>bin/</b>              ← Skripte für die Kommandozeile
 ├── <b>config/</b>           ← Konfigurationsdateien
@@ -67,7 +67,7 @@ Das wichtigste Verzeichnis für Sie ist `app/`. Dort finden Sie die Datei `Boots
 Aufräumen .[#toc-cleanup]
 =========================
 
-Das Webprojekt enthält eine Willkommensseite, die wir entfernen können - löschen Sie die Datei `app/Presenters/templates/Home/default.latte` und ersetzen Sie sie durch den Text "Hello world!".
+Das Webprojekt enthält eine Willkommensseite, die wir entfernen können - löschen Sie die Datei `app/UI/Home/default.latte` und ersetzen Sie sie durch den Text "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Das Webprojekt enthält eine Willkommensseite, die wir entfernen können - lösc
 Tracy (Debugger) .[#toc-tracy-debugger]
 =======================================
 
-Ein äußerst wichtiges Werkzeug für die Entwicklung ist [ein Debugger namens Tracy |tracy:]. Versuchen Sie, einige Fehler in Ihrer `app/Presenters/HomePresenter.php` Datei zu machen (z.B. entfernen Sie eine geschweifte Klammer aus der Definition der Klasse HomePresenter) und sehen Sie, was passiert. Es wird eine rote Bildschirmseite mit einer verständlichen Fehlerbeschreibung erscheinen.
+Ein äußerst wichtiges Werkzeug für die Entwicklung ist [ein Debugger namens Tracy |tracy:]. Versuchen Sie, einige Fehler in Ihrer `app/UI/Home/HomePresenter.php` Datei zu machen (z.B. entfernen Sie eine geschweifte Klammer aus der Definition der Klasse HomePresenter) und sehen Sie, was passiert. Es wird eine rote Bildschirmseite mit einer verständlichen Fehlerbeschreibung erscheinen.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy wird Ihnen bei der Fehlersuche sehr helfen. Beachten Sie auch die schwebende Tracy-Leiste in der unteren rechten Ecke, die Sie über wichtige Laufzeitdaten informiert.
 
@@ -88,8 +88,7 @@ Im Produktionsmodus ist Tracy natürlich deaktiviert und gibt keine sensiblen In
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/de/authentication.texy b/quickstart/de/authentication.texy
index 5b93e2e9d4..78d22b837f 100644
--- a/quickstart/de/authentication.texy
+++ b/quickstart/de/authentication.texy
@@ -28,9 +28,9 @@ Wir haben nun den Backend-Teil der Authentifizierung fertig und müssen eine Ben
 
 Lassen Sie uns mit dem Anmeldeformular beginnen. Sie wissen bereits, wie Formulare in einem Presenter funktionieren. Erstellen Sie die `SignPresenter` und die Methode `createComponentSignInForm`. Es sollte wie folgt aussehen:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Vorlage .[#toc-template]
 
 Das Formular wird in der Vorlage gerendert `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Wir fügen auch einen *Form Handler* für die Anmeldung des Benutzers hinzu, der
 
 Der Handler nimmt einfach den Benutzernamen und das Passwort, die der Benutzer eingegeben hat, und übergibt sie an den zuvor definierten Authentifikator. Nachdem sich der Benutzer angemeldet hat, leiten wir ihn auf die Homepage um.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Wir werden ein Formular zum Hinzufügen und Bearbeiten von Beiträgen sichern. E
 
 Wir erstellen eine Methode `startup()`, die sofort zu Beginn des [Lebenszyklus des Präsentators |application:presenters#life-cycle-of-presenter] gestartet wird. Diese leitet nicht eingeloggte Benutzer zum Anmeldeformular um.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Links ausblenden .[#toc-hide-links]
 -----------------------------------
 
-Ein nicht authentifizierter Benutzer kann weder die Seite *Erstellen* noch die Seite *Bearbeiten* sehen, aber er kann immer noch die Links sehen, die auf sie verweisen. Diese sollten wir ebenfalls ausblenden. Ein solcher Link befindet sich in `app/Presenters/templates/Home/default.latte`, und er sollte nur sichtbar sein, wenn der Benutzer angemeldet ist.
+Ein nicht authentifizierter Benutzer kann weder die Seite *Erstellen* noch die Seite *Bearbeiten* sehen, aber er kann immer noch die Links sehen, die auf sie verweisen. Diese sollten wir ebenfalls ausblenden. Ein solcher Link befindet sich in `app/UI/Home/default.latte`, und er sollte nur sichtbar sein, wenn der Benutzer angemeldet ist.
 
 Wir können ihn mit einem *n:Attribut* namens `n:if` ausblenden. Wenn die darin enthaltene Anweisung `false` lautet, werden der gesamte `<a>` Tag und sein Inhalt werden nicht angezeigt:
 
@@ -131,7 +131,7 @@ Dies ist eine Abkürzung für (nicht zu verwechseln mit `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Sie sollten den Bearbeitungslink unter `app/Presenters/templates/Post/show.latte` auf ähnliche Weise ausblenden.
+Sie sollten den Bearbeitungslink unter `app/UI/Post/show.latte` auf ähnliche Weise ausblenden.
 
 
 Link zum Anmeldeformular .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Link zum Anmeldeformular .[#toc-login-form-link]
 
 Hey, aber wie kommen wir auf die Anmeldeseite? Es gibt keinen Link, der auf sie verweist. Fügen wir einen in die `@layout.latte` Vorlagendatei ein. Versuchen Sie, einen schönen Platz zu finden, es kann überall sein, wo es Ihnen am besten gefällt.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Wenn der Benutzer noch nicht eingeloggt ist, wird der Link "Anmelden" angezeigt.
 
 Die Abmeldeaktion sieht wie folgt aus, und da wir den Benutzer sofort umleiten, ist keine Ansichtsvorlage erforderlich.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/de/comments.texy b/quickstart/de/comments.texy
index 94cc08d97e..73bd45886b 100644
--- a/quickstart/de/comments.texy
+++ b/quickstart/de/comments.texy
@@ -44,7 +44,7 @@ Zuerst müssen wir ein Formular erstellen, das es den Benutzern ermöglicht, auf
 
 Nette Framework hat ein Konzept von *Komponenten*. Eine **Komponente** ist eine wiederverwendbare Klasse oder ein Stück Code, das mit einer anderen Komponente verbunden werden kann. Auch ein Präsentator ist eine Komponente. Jede Komponente wird mit Hilfe der Komponentenfabrik erstellt. Definieren wir also die Kommentarformularfabrik in `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // bedeutet Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Erklären wir sie ein wenig. Die erste Zeile erzeugt eine neue Instanz der Kompo
 
 Sobald die Formularkomponente in einem Presenter definiert ist, können wir sie in einer Vorlage rendern (anzeigen). Dazu platzieren Sie das Tag `{control}` am Ende der Post-Detail-Vorlage in `Post/show.latte`. Da der Name der Komponente `commentForm` ist (er leitet sich vom Namen der Methode `createComponentCommentForm` ab), sieht das Tag wie folgt aus
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Sie bedeutet "nachdem das Formular erfolgreich abgeschickt wurde, rufe die Methode `commentFormSucceeded` des aktuellen Präsentators auf". Diese Methode existiert noch nicht, also erstellen wir sie.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Die neue Methode hat ein Argument, nämlich die Instanz des übermittelten Formu
 
 Es gibt noch zwei weitere Methodenaufrufe zu erklären. Der Redirect leitet buchstäblich zur aktuellen Seite um. Das sollten Sie jedes Mal tun, wenn das Formular übermittelt wurde, gültig ist und die Callback-Operation das getan hat, was sie hätte tun sollen. Wenn Sie die Seite nach dem Absenden des Formulars umleiten, wird auch nicht die bekannte Meldung `Would you like to submit the post data again?` angezeigt, die Sie manchmal im Browser sehen können. (Im Allgemeinen sollten Sie den Benutzer nach dem Absenden eines Formulars mit der Methode `POST` immer zu einer Aktion `GET` weiterleiten).
 
-Die `flashMessage` dient dazu, den Benutzer über das Ergebnis einer bestimmten Operation zu informieren. Da wir eine Routing vornehmen, kann die Nachricht nicht direkt an die Vorlage übergeben und gerendert werden. Deshalb gibt es diese Methode, die sie speichert und beim nächsten Laden der Seite zur Verfügung stellt. Die Flash-Nachrichten werden in der Standarddatei `app/Presenters/templates/@layout.latte` gerendert und sehen wie folgt aus:
+Die `flashMessage` dient dazu, den Benutzer über das Ergebnis einer bestimmten Operation zu informieren. Da wir eine Routing vornehmen, kann die Nachricht nicht direkt an die Vorlage übergeben und gerendert werden. Deshalb gibt es diese Methode, die sie speichert und beim nächsten Laden der Seite zur Verfügung stellt. Die Flash-Nachrichten werden in der Standarddatei `app/UI/@layout.latte` gerendert und sehen wie folgt aus:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Der Nette Database Explorer verwendet die Fremdschlüssel, um die Beziehungen zw
 
 Wie Sie sich vielleicht erinnern, haben wir die Variable `$post` an die Vorlage in `PostPresenter::renderShow()` übergeben, und jetzt wollen wir alle Kommentare durchgehen, deren Spalte `post_id` gleich unserer `$post->id` ist. Sie können dies tun, indem Sie `$post->related('comments')` aufrufen. So einfach ist das. Sehen Sie sich den resultierenden Code an.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 Und die Vorlage:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/de/creating-posts.texy b/quickstart/de/creating-posts.texy
index 3134c84ef6..2c3b1955f6 100644
--- a/quickstart/de/creating-posts.texy
+++ b/quickstart/de/creating-posts.texy
@@ -20,11 +20,11 @@ Später werden wir auch die Authentifizierung hinzufügen und nur angemeldeten B
 Neuer Präsentator .[#toc-new-presenter]
 =======================================
 
-Nennen Sie den neuen Presenter `EditPresenter` und speichern Sie ihn unter `app/Presenters/EditPresenter.php`. Er muss sich auch mit der Datenbank verbinden, also schreiben wir auch hier einen Konstruktor, der eine Datenbankverbindung benötigt:
+Nennen Sie den neuen Presenter `EditPresenter` und speichern Sie ihn unter `app/UI/Edit/`. Er muss sich auch mit der Datenbank verbinden, also schreiben wir auch hier einen Konstruktor, der eine Datenbankverbindung benötigt:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Formulare und Komponenten wurden bereits behandelt, als wir die Unterstützung f
 
 Fügen Sie nun diese Methode in die `EditPresenter` ein:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Speichern eines neuen Beitrags aus einem Formular .[#toc-saving-new-post-from-fo
 
 Fahren Sie fort, indem Sie eine Handler-Methode hinzufügen.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Seite zum Erstellen eines neuen Beitrags .[#toc-page-for-creating-a-new-post]
 
 Lassen Sie uns einfach die Vorlage `Edit/create.latte` erstellen:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Link zum Erstellen von Beiträgen .[#toc-link-for-creating-posts]
 
 Sie wissen wahrscheinlich schon, wie Sie einen Link zu `EditPresenter` und der Aktion `create` hinzufügen können. Probieren Sie es aus.
 
-Fügen Sie einfach die Datei `app/Presenters/templates/Home/default.latte` hinzu:
+Fügen Sie einfach die Datei `app/UI/Home/default.latte` hinzu:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Lassen Sie uns auch die Möglichkeit hinzufügen, bestehende Beiträge zu bearbe
 
 Wir fügen eine neue Seite `edit` zu `EditPresenter` hinzu:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 Und erstellen die Vorlage `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ Und erstellen die Vorlage `Edit/edit.latte`:
 
 Und aktualisieren Sie die Methode `postFormSucceeded`, mit der Sie entweder einen neuen Beitrag hinzufügen können (wie jetzt) oder bestehende Beiträge bearbeiten können:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Wenn der Parameter `postId` angegeben wird, bedeutet dies, dass ein Beitrag bearbeitet wird. In diesem Fall wird überprüft, ob der Beitrag wirklich existiert, und wenn ja, wird er in der Datenbank aktualisiert. Wenn der Parameter `postId` nicht angegeben wird, bedeutet dies, dass ein neuer Beitrag hinzugefügt wird.
+Wenn der Parameter `id` angegeben wird, bedeutet dies, dass ein Beitrag bearbeitet wird. In diesem Fall wird überprüft, ob der Beitrag wirklich existiert, und wenn ja, wird er in der Datenbank aktualisiert. Wenn der Parameter `id` nicht angegeben wird, bedeutet dies, dass ein neuer Beitrag hinzugefügt wird.
 
-Aber woher kommt die `postId`? Es ist der Parameter, der an die Methode `renderEdit` übergeben wird.
+Aber woher kommt die `id`? Es ist der Parameter, der an die Methode `renderEdit` übergeben wird.
 
-Sie können nun einen Link zur Vorlage `app/Presenters/templates/Post/show.latte` hinzufügen:
+Sie können nun einen Link zur Vorlage `app/UI/Post/show.latte` hinzufügen:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/de/home-page.texy b/quickstart/de/home-page.texy
index 2ab1c8db32..eed2b8dff6 100644
--- a/quickstart/de/home-page.texy
+++ b/quickstart/de/home-page.texy
@@ -66,9 +66,9 @@ Verbinden mit der Datenbank .[#toc-connecting-to-the-database]
 
 Jetzt, wo die Datenbank erstellt ist und wir einige Beiträge darin haben, ist es an der Zeit, sie auf unserer neuen glänzenden Seite anzuzeigen.
 
-Zuerst müssen wir unserer Anwendung mitteilen, welche Datenbank sie verwenden soll. Die Konfiguration der Datenbankverbindung wird in `config/local.neon` gespeichert. Legen Sie die Verbindung DSN((Data Source Name)) und Ihre Anmeldedaten fest. Es sollte so aussehen:
+Zuerst müssen wir unserer Anwendung mitteilen, welche Datenbank sie verwenden soll. Die Konfiguration der Datenbankverbindung wird in `config/common.neon` gespeichert. Legen Sie die Verbindung DSN((Data Source Name)) und Ihre Anmeldedaten fest. Es sollte so aussehen:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Achten Sie bei der Bearbeitung dieser Datei auf die Einrückung. Das [NEON-Format |neon:format] akzeptiert sowohl Leerzeichen als auch Tabulatoren, aber nicht beides zusammen! Die Konfigurationsdatei im Webprojekt verwendet standardmäßig Tabulatoren.
 
-Die gesamte Konfiguration ist in `config/` in den Dateien `common.neon` und `local.neon` gespeichert. Die Datei `common.neon` enthält die globale Konfiguration der Anwendung und `local.neon` enthält nur die Parameter, die für die Umgebung spezifisch sind (z. B. den Unterschied zwischen Entwicklungs- und Produktionsserver).
-
 
 Injizieren der Datenbankverbindung .[#toc-injecting-the-database-connection]
 ============================================================================
 
 Der Presenter `HomePresenter`, der die Artikel auflistet, benötigt eine Datenbankverbindung. Um sie zu erhalten, schreiben Sie einen Konstruktor wie diesen:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Laden von Beiträgen aus der Datenbank .[#toc-loading-posts-from-the-database]
 
 Holen wir nun die Beiträge aus der Datenbank und übergeben sie an die Vorlage, die dann den HTML-Code rendert. Dafür ist die sogenannte *render*-Methode gedacht:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Der Presenter hat jetzt eine Render-Methode `renderDefault()`, die Daten an eine Ansicht namens `default` weitergibt. Presenter-Vorlagen befinden sich in `app/Presenters/templates/{PresenterName}/{viewName}.latte`, in diesem Fall also in `app/Presenters/templates/Home/default.latte`. In der Vorlage ist nun eine Variable namens `$posts` verfügbar, die die Beiträge aus der Datenbank enthält.
+Der Presenter hat jetzt eine Render-Methode `renderDefault()`, die Daten an eine Ansicht namens `default` weitergibt. Presenter-Vorlagen befinden sich in `app/UI/{PresenterName}/{viewName}.latte`, in diesem Fall also in `app/UI/Home/default.latte`. In der Vorlage ist nun eine Variable namens `$posts` verfügbar, die die Beiträge aus der Datenbank enthält.
 
 
 Vorlage .[#toc-template]
@@ -128,9 +125,9 @@ Vorlage .[#toc-template]
 
 Es gibt eine allgemeine Vorlage für die gesamte Seite (genannt *Layout*, mit Kopfzeile, Stylesheets, Fußzeile, ...) und dann spezifische Vorlagen für jede Ansicht (z.B. für die Anzeige der Liste der Blogbeiträge), die einige Teile der Layout-Vorlage überschreiben können.
 
-Standardmäßig befindet sich die Layout-Vorlage im Verzeichnis `templates/@layout.latte`, das Folgendes enthält:
+Standardmäßig befindet sich die Layout-Vorlage im Verzeichnis `app/UI/@layout.latte`, das Folgendes enthält:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Standardmäßig befindet sich die Layout-Vorlage im Verzeichnis `templates/@layo
 
 `{include content}` fügt einen Block namens `content` in die Hauptvorlage ein. Sie können ihn in den Vorlagen der einzelnen Ansichten definieren. In diesem Fall werden wir die Datei `Home/default.latte` wie folgt bearbeiten:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Sie definiert den [Block |latte:tags#block]*Inhalt*, der in das Layout eingefüg
 
 Zeigen wir nun die Blogeinträge an - wir werden die Vorlage wie folgt bearbeiten:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Zeigen wir nun die Blogeinträge an - wir werden die Vorlage wie folgt bearbeite
 
 Wenn Sie Ihren Browser aktualisieren, sehen Sie die Liste Ihrer Blogeinträge. Die Liste ist nicht sehr schick oder bunt, also fügen Sie ruhig etwas [glänzendes CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] zu `www/css/style.css` hinzu und verknüpfen Sie es mit einem Layout:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Die Variable `|date` wird als Filter bezeichnet. Filter werden verwendet, um die
 
 Eine weitere Sache. Wir können den Code ein wenig kürzer und damit einfacher machen. Wir können *Latte Tags* durch *n:Attribute* wie folgt ersetzen:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/de/model.texy b/quickstart/de/model.texy
index 6a00704dfd..271194e571 100644
--- a/quickstart/de/model.texy
+++ b/quickstart/de/model.texy
@@ -36,9 +36,9 @@ In der Klasse übergeben wir die Datenbank Explorer:[api:Nette\Database\Explorer
 
 Wir werden zu `HomePresenter` wechseln, das wir so bearbeiten, dass wir die Abhängigkeit von `Nette\Database\Explorer` loswerden und durch eine neue Abhängigkeit von unserer neuen Klasse ersetzen.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/de/single-post.texy b/quickstart/de/single-post.texy
index 047f4cb235..1c6f019bfa 100644
--- a/quickstart/de/single-post.texy
+++ b/quickstart/de/single-post.texy
@@ -5,13 +5,13 @@ Einzelner Beitrag Seite
 Fügen wir unserem Blog eine weitere Seite hinzu, die den Inhalt eines bestimmten Blogbeitrags anzeigt.
 
 
-Wir müssen eine neue Render-Methode erstellen, die einen bestimmten Blogeintrag abruft und ihn an die Vorlage weitergibt. Diese Ansicht in `HomePresenter` zu haben, ist nicht schön, da es sich um einen Blogeintrag und nicht um die Homepage handelt. Also erstellen wir eine neue Klasse `PostPresenter` und platzieren sie in `app/Presenters`. Sie benötigt eine Datenbankverbindung, also fügen wir den *Datenbankinjektions*-Code dort wieder ein.
+Wir müssen eine neue Render-Methode erstellen, die einen bestimmten Blogeintrag abruft und ihn an die Vorlage weitergibt. Diese Ansicht in `HomePresenter` zu haben, ist nicht schön, da es sich um einen Blogeintrag und nicht um die Homepage handelt. Also erstellen wir eine neue Klasse `PostPresenter` und platzieren sie in `app/UI/Post/`. Sie benötigt eine Datenbankverbindung, also fügen wir den *Datenbankinjektions*-Code dort wieder ein.
 
 Die `PostPresenter` sollte so aussehen:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Wir müssen einen korrekten Namespace `App\Presenters` für unseren Präsentator festlegen. Dies hängt von der [Zuordnung der Präsentatoren |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] ab.
+Wir müssen einen korrekten Namespace `App\UI\Post` für unseren Präsentator festlegen. Dies hängt von der [Zuordnung der Präsentatoren |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] ab.
 
 Die Methode `renderShow` benötigt ein Argument - die ID des Beitrags, der angezeigt werden soll. Dann lädt sie den Beitrag aus der Datenbank und übergibt das Ergebnis an die Vorlage.
 
 In der Vorlage `Home/default.latte` fügen wir einen Link zur Aktion `Post:show` hinzu:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Das Tag `{link}` erzeugt eine URL-Adresse, die auf die Aktion `Post:show` verwei
 
 Das Gleiche können wir kurz mit n:attribute schreiben:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Die Vorlage für die Aktion `Post:show` existiert noch nicht. Wir können einen
 
 Wir werden also `Post/show.latte` mit diesem Inhalt erstellen:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ Die vierte Zeile zeigt den *Titel* des Blogbeitrags als `<h1>` Überschrift. Es
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-In einfachen Worten: Es *definiert* einen Block namens `title` neu. Der Block ist in der *Layout-Vorlage* (`/app/Presenters/templates/@layout.latte:11`) definiert und wird hier, wie bei OOP-Überschreibungen, überschrieben. Daher wird die Seite `<title>` den Titel des angezeigten Beitrags enthalten. Wir haben den Titel der Seite überschrieben, und alles, was wir brauchten, war `n:block="title"`. Großartig, nicht wahr?
+In einfachen Worten: Es *definiert* einen Block namens `title` neu. Der Block ist in der *Layout-Vorlage* (`/app/UI/@layout.latte:11`) definiert und wird hier, wie bei OOP-Überschreibungen, überschrieben. Daher wird die Seite `<title>` den Titel des angezeigten Beitrags enthalten. Wir haben den Titel der Seite überschrieben, und alles, was wir brauchten, war `n:block="title"`. Großartig, nicht wahr?
 
 In der fünften und letzten Zeile der Vorlage wird der gesamte Inhalt Ihres Beitrags angezeigt.
 
@@ -97,14 +97,14 @@ In der fünften und letzten Zeile der Vorlage wird der gesamte Inhalt Ihres Beit
 Überprüfen der Post-ID .[#toc-checking-post-id]
 ===============================================
 
-Was passiert, wenn jemand die URL ändert und `postId` einfügt, die nicht existiert? Wir sollten dem Benutzer eine schöne Fehlermeldung "Seite nicht gefunden" geben. Aktualisieren wir die Render-Methode in `PostPresenter`:
+Was passiert, wenn jemand die URL ändert und `id` einfügt, die nicht existiert? Wir sollten dem Benutzer eine schöne Fehlermeldung "Seite nicht gefunden" geben. Aktualisieren wir die Render-Methode in `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/el/@home.texy b/quickstart/el/@home.texy
index 7be876f93f..7261b6a7cc 100644
--- a/quickstart/el/@home.texy
+++ b/quickstart/el/@home.texy
@@ -7,7 +7,7 @@
 Μετά τα δύο πρώτα κεφάλαια, θα έχετε το δικό σας λειτουργικό ιστολόγιο και θα είστε έτοιμοι να δημοσιεύσετε τις φοβερές αναρτήσεις σας, αν και οι δυνατότητες θα είναι αρκετά περιορισμένες μετά την ολοκλήρωση αυτών των δύο κεφαλαίων. Για να κάνετε τα πράγματα πιο ευχάριστα για τους χρήστες σας, θα πρέπει επίσης να διαβάσετε τα επόμενα κεφάλαια και να συνεχίσετε να βελτιώνετε την εφαρμογή σας.
 
 .[tip]
-Αυτό το σεμινάριο προϋποθέτει ότι έχετε ολοκληρώσει το έγγραφο [Εγκατάσταση |nette:installation] και έχετε ρυθμίσει με επιτυχία τα εργαλεία σας.
+Αυτό το σεμινάριο προϋποθέτει ότι έχετε ολοκληρώσει το έγγραφο [Εγκατάσταση |nette:installation] και έχετε ρυθμίσει με επιτυχία τα εργαλεία σας. Προϋποθέτει επίσης ότι κατανοείτε τον [αντικειμενοστραφή προγραμματισμό στην PHP |nette:introduction-to-object-oriented-programming].
 
 Παρακαλούμε χρησιμοποιήστε PHP 8.1 ή νεότερη έκδοση. Μπορείτε να βρείτε την πλήρη εφαρμογή [στο GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ http://localhost/nette-blog/www/
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← βασικές αναγκαίες τάξεις
+│   ├── <b>UI/</b>           ← παρουσιαστές, πρότυπα και λοιπά.
+│   │   └── <b>Home/</b>     ← Αρχικός κατάλογος παρουσιαστών
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ http://localhost/nette-blog/www/
 Καθαρισμός .[#toc-cleanup]
 ==========================
 
-Το Web Project περιέχει μια σελίδα καλωσορίσματος, την οποία μπορούμε να αφαιρέσουμε - μπορείτε να διαγράψετε το αρχείο `app/Presenters/templates/Home/default.latte` και να το αντικαταστήσετε με το κείμενο "Hello world!".
+Το Web Project περιέχει μια σελίδα καλωσορίσματος, την οποία μπορούμε να αφαιρέσουμε - μπορείτε να διαγράψετε το αρχείο `app/UI/Home/default.latte` και να το αντικαταστήσετε με το κείμενο "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ http://localhost/nette-blog/www/
 Tracy (αποσφαλματωτής) .[#toc-tracy-debugger]
 =============================================
 
-Ένα εξαιρετικά σημαντικό εργαλείο για την ανάπτυξη είναι [ένας αποσφαλματωτής που ονομάζεται Tracy |tracy:]. Δοκιμάστε να κάνετε κάποια λάθη στο αρχείο σας `app/Presenters/HomePresenter.php` (π.χ. αφαιρέστε μια καμπύλη αγκύλη από τον ορισμό της κλάσης HomePresenter) και δείτε τι θα συμβεί. Θα εμφανιστεί μια σελίδα με κόκκινη οθόνη και μια κατανοητή περιγραφή του σφάλματος.
+Ένα εξαιρετικά σημαντικό εργαλείο για την ανάπτυξη είναι [ένας αποσφαλματωτής που ονομάζεται Tracy |tracy:]. Δοκιμάστε να κάνετε κάποια λάθη στο αρχείο σας `app/UI/Home/HomePresenter.php` (π.χ. αφαιρέστε μια καμπύλη αγκύλη από τον ορισμό της κλάσης HomePresenter) και δείτε τι θα συμβεί. Θα εμφανιστεί μια σελίδα με κόκκινη οθόνη και μια κατανοητή περιγραφή του σφάλματος.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Το Tracy θα σας βοηθήσει σημαντικά κατά το κυνήγι των σφαλμάτων. Σημειώστε επίσης την αιωρούμενη μπάρα Tracy Bar στην κάτω δεξιά γωνία, η οποία σας ενημερώνει για σημαντικά δεδομένα εκτέλεσης.
 
@@ -88,8 +88,7 @@ Tracy (αποσφαλματωτής) .[#toc-tracy-debugger]
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/el/authentication.texy b/quickstart/el/authentication.texy
index 6825b2cb15..1f04d525d3 100644
--- a/quickstart/el/authentication.texy
+++ b/quickstart/el/authentication.texy
@@ -28,9 +28,9 @@ security:
 
 Ας ξεκινήσουμε με τη φόρμα σύνδεσης. Γνωρίζετε ήδη πώς λειτουργούν οι φόρμες σε έναν παρουσιαστή. Δημιουργήστε την `SignPresenter` και τη μέθοδο `createComponentSignInForm`. Θα πρέπει να μοιάζει με αυτό:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 
 Η φόρμα θα εμφανιστεί στο πρότυπο `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 
 Ο χειριστής θα λάβει απλώς το όνομα χρήστη και τον κωδικό πρόσβασης που εισήγαγε ο χρήστης και θα τα περάσει στον authenticator που ορίστηκε νωρίτερα. Αφού ο χρήστης συνδεθεί, θα τον ανακατευθύνουμε στην αρχική σελίδα.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ private function signInFormSucceeded(Form $form, \stdClass $data): void
 
 Δημιουργούμε μια μέθοδο `startup()` που ξεκινάει αμέσως στην αρχή του [κύκλου ζωής του παρουσιαστή |application:presenters#life-cycle-of-presenter]. Αυτή ανακατευθύνει τους μη συνδεδεμένους χρήστες στη φόρμα σύνδεσης.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Απόκρυψη συνδέσμων .[#toc-hide-links]
 -------------------------------------
 
-Ένας μη πιστοποιημένος χρήστης δεν μπορεί πλέον να δει τη σελίδα *δημιουργίας* ή *επεξεργασίας*, αλλά μπορεί ακόμα να δει τους συνδέσμους που οδηγούν σε αυτές. Ας αποκρύψουμε και αυτούς. Ένας τέτοιος σύνδεσμος βρίσκεται στη διεύθυνση `app/Presenters/templates/Home/default.latte`, και θα πρέπει να είναι ορατός μόνο αν ο χρήστης είναι συνδεδεμένος.
+Ένας μη πιστοποιημένος χρήστης δεν μπορεί πλέον να δει τη σελίδα *δημιουργίας* ή *επεξεργασίας*, αλλά μπορεί ακόμα να δει τους συνδέσμους που οδηγούν σε αυτές. Ας αποκρύψουμε και αυτούς. Ένας τέτοιος σύνδεσμος βρίσκεται στη διεύθυνση `app/UI/Home/default.latte`, και θα πρέπει να είναι ορατός μόνο αν ο χρήστης είναι συνδεδεμένος.
 
 Μπορούμε να τον αποκρύψουμε χρησιμοποιώντας το *n:attribute* που ονομάζεται `n:if`. Εάν η δήλωση μέσα σε αυτό είναι `false`, ολόκληρο το `<a>` ετικέτα και τα περιεχόμενά της δεν θα εμφανίζονται:
 
@@ -131,7 +131,7 @@ public function startup(): void
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Θα πρέπει να αποκρύψετε το σύνδεσμο επεξεργασίας που βρίσκεται στο `app/Presenters/templates/Post/show.latte` με παρόμοιο τρόπο.
+Θα πρέπει να αποκρύψετε το σύνδεσμο επεξεργασίας που βρίσκεται στο `app/UI/Post/show.latte` με παρόμοιο τρόπο.
 
 
 Σύνδεσμος φόρμας σύνδεσης .[#toc-login-form-link]
@@ -139,7 +139,7 @@ public function startup(): void
 
 Γεια σας, αλλά πώς μπορούμε να φτάσουμε στη σελίδα σύνδεσης; Δεν υπάρχει κανένας σύνδεσμος που να οδηγεί σε αυτήν. Ας προσθέσουμε έναν στο αρχείο προτύπου `@layout.latte`. Προσπαθήστε να βρείτε ένα ωραίο μέρος, μπορεί να είναι οπουδήποτε σας αρέσει περισσότερο.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ public function startup(): void
 
 Η ενέργεια αποσύνδεσης μοιάζει με αυτή, και επειδή ανακατευθύνουμε τον χρήστη αμέσως, δεν υπάρχει ανάγκη για ένα πρότυπο προβολής.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/el/comments.texy b/quickstart/el/comments.texy
index 3610be55fc..fd59190740 100644
--- a/quickstart/el/comments.texy
+++ b/quickstart/el/comments.texy
@@ -44,7 +44,7 @@ CREATE TABLE `comments` (
 
 Το Nette Framework διαθέτει την έννοια των *στοιχείων*. Ένα **συστατικό** είναι μια επαναχρησιμοποιήσιμη κλάση ή ένα κομμάτι κώδικα, το οποίο μπορεί να συνδεθεί με ένα άλλο συστατικό. Ακόμα και ένας παρουσιαστής είναι ένα συστατικό. Κάθε συστατικό δημιουργείται με τη χρήση του εργοστασίου συστατικών. Ας ορίσουμε λοιπόν το εργοστάσιο της φόρμας σχολίων στο `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // σημαίνει Nette\Application\UII\Form
@@ -67,7 +67,7 @@ protected function createComponentCommentForm(): Form
 
 Αφού οριστεί το συστατικό της φόρμας σε έναν παρουσιαστή, μπορούμε να το αποδώσουμε (εμφανίσουμε) σε ένα πρότυπο. Για να το κάνετε αυτό, τοποθετήστε την ετικέτα `{control}` στο τέλος του προτύπου λεπτομερειών δημοσίευσης, στο `Post/show.latte`. Επειδή το όνομα του συστατικού είναι `commentForm` (προέρχεται από το όνομα της μεθόδου `createComponentCommentForm`), η ετικέτα θα μοιάζει ως εξής
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Σημαίνει "μετά την επιτυχή υποβολή της φόρμας, καλέστε τη μέθοδο `commentFormSucceeded` του τρέχοντος παρουσιαστή". Αυτή η μέθοδος δεν υπάρχει ακόμα, οπότε ας τη δημιουργήσουμε.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ private function commentFormSucceeded(\stdClass $data): void
 
 Υπάρχουν δύο ακόμη κλήσεις μεθόδων που πρέπει να εξηγήσουμε. Η ανακατεύθυνση ανακατευθύνει κυριολεκτικά στην τρέχουσα σελίδα. Θα πρέπει να το κάνετε αυτό κάθε φορά που η φόρμα έχει υποβληθεί, είναι έγκυρη και η λειτουργία επανάκλησης έκανε αυτό που έπρεπε να κάνει. Επίσης, όταν ανακατευθύνετε τη σελίδα μετά την υποβολή της φόρμας, δεν θα βλέπετε το γνωστό μήνυμα `Would you like to submit the post data again?` που μερικές φορές μπορείτε να δείτε στο πρόγραμμα περιήγησης. (Γενικά, μετά την υποβολή μιας φόρμας με τη μέθοδο `POST`, θα πρέπει πάντα να ανακατευθύνετε τον χρήστη σε μια ενέργεια `GET` ).
 
-Το `flashMessage` είναι για την ενημέρωση του χρήστη σχετικά με το αποτέλεσμα κάποιας ενέργειας. Επειδή κάνουμε ανακατεύθυνση, το μήνυμα δεν μπορεί να περάσει απευθείας στο πρότυπο και να αποδοθεί. Έτσι υπάρχει αυτή η μέθοδος, που θα το αποθηκεύσει και θα το κάνει διαθέσιμο κατά την επόμενη φόρτωση της σελίδας. Τα μηνύματα flash αποδίδονται στο προεπιλεγμένο αρχείο `app/Presenters/templates/@layout.latte` και μοιάζει κάπως έτσι:
+Το `flashMessage` είναι για την ενημέρωση του χρήστη σχετικά με το αποτέλεσμα κάποιας ενέργειας. Επειδή κάνουμε ανακατεύθυνση, το μήνυμα δεν μπορεί να περάσει απευθείας στο πρότυπο και να αποδοθεί. Έτσι υπάρχει αυτή η μέθοδος, που θα το αποθηκεύσει και θα το κάνει διαθέσιμο κατά την επόμενη φόρτωση της σελίδας. Τα μηνύματα flash αποδίδονται στο προεπιλεγμένο αρχείο `app/UI/@layout.latte` και μοιάζει κάπως έτσι:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ private function commentFormSucceeded(\stdClass $data): void
 
 Όπως ίσως θυμάστε, έχουμε περάσει τη μεταβλητή `$post` στο πρότυπο στο `PostPresenter::renderShow()` και τώρα θέλουμε να επαναλάβουμε όλα τα σχόλια που έχουν τη στήλη `post_id` ίση με το `$post->id` μας . Μπορείτε να το κάνετε καλώντας το `$post->related('comments')`. Είναι τόσο απλό. Κοιτάξτε τον κώδικα που προκύπτει.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 Και το πρότυπο:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/el/creating-posts.texy b/quickstart/el/creating-posts.texy
index e4e9440bf6..59f6ce8e92 100644
--- a/quickstart/el/creating-posts.texy
+++ b/quickstart/el/creating-posts.texy
@@ -20,11 +20,11 @@
 Νέος παρουσιαστής .[#toc-new-presenter]
 =======================================
 
-Ονομάστε τον νέο παρουσιαστή `EditPresenter` και αποθηκεύστε τον στο `app/Presenters/EditPresenter.php`. Πρέπει επίσης να συνδεθεί με τη βάση δεδομένων, οπότε και εδώ γράφουμε έναν κατασκευαστή που θα απαιτεί σύνδεση με τη βάση δεδομένων:
+Ονομάστε τον νέο παρουσιαστή `EditPresenter` και αποθηκεύστε τον στο `app/UI/Edit/`. Πρέπει επίσης να συνδεθεί με τη βάση δεδομένων, οπότε και εδώ γράφουμε έναν κατασκευαστή που θα απαιτεί σύνδεση με τη βάση δεδομένων:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ final class EditPresenter extends Nette\Application\UI\Presenter
 
 Τώρα προσθέστε αυτή τη μέθοδο στο `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ protected function createComponentPostForm(): Form
 
 Συνεχίστε με την προσθήκη μιας μεθόδου χειρισμού.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ private function postFormSucceeded(array $data): void
 
 Ας δημιουργήσουμε απλά το πρότυπο `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ private function postFormSucceeded(array $data): void
 
 Πιθανώς γνωρίζετε ήδη πώς να προσθέσετε έναν σύνδεσμο στο `EditPresenter` και την ενέργεια `create`. Δοκιμάστε το.
 
-Απλά προσθέστε στο αρχείο `app/Presenters/templates/Home/default.latte`:
+Απλά προσθέστε στο αρχείο `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ private function postFormSucceeded(array $data): void
 
 Θα προσθέσουμε μια νέα σελίδα `edit` στο `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 Και θα δημιουργήσουμε το πρότυπο `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ public function renderEdit(int $postId): void
 
 Και ενημερώστε τη μέθοδο `postFormSucceeded`, η οποία θα μπορεί είτε να προσθέτει μια νέα ανάρτηση (όπως κάνει τώρα), είτε να επεξεργάζεται τις υπάρχουσες:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Όταν παρέχεται η παράμετρος `postId`, σημαίνει ότι γίνεται επεξεργασία μιας ανάρτησης. Σε μια τέτοια περίπτωση, θα ελέγξουμε ότι η ανάρτηση υπάρχει πραγματικά και αν ναι, θα την ενημερώσουμε στη βάση δεδομένων. Εάν δεν παρέχεται η παράμετρος `postId`, σημαίνει ότι θα προστεθεί μια νέα ανάρτηση.
+Όταν παρέχεται η παράμετρος `id`, σημαίνει ότι γίνεται επεξεργασία μιας ανάρτησης. Σε μια τέτοια περίπτωση, θα ελέγξουμε ότι η ανάρτηση υπάρχει πραγματικά και αν ναι, θα την ενημερώσουμε στη βάση δεδομένων. Εάν δεν παρέχεται η παράμετρος `id`, σημαίνει ότι θα προστεθεί μια νέα ανάρτηση.
 
-Αλλά από πού προέρχεται το `postId`; Είναι η παράμετρος που δίνεται στη μέθοδο `renderEdit`.
+Αλλά από πού προέρχεται το `id`; Είναι η παράμετρος που δίνεται στη μέθοδο `renderEdit`.
 
-Μπορείτε τώρα να προσθέσετε έναν σύνδεσμο στο πρότυπο `app/Presenters/templates/Post/show.latte`:
+Μπορείτε τώρα να προσθέσετε έναν σύνδεσμο στο πρότυπο `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/el/home-page.texy b/quickstart/el/home-page.texy
index 812b5ef745..397ff7bdd6 100644
--- a/quickstart/el/home-page.texy
+++ b/quickstart/el/home-page.texy
@@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
 
 Τώρα, όταν η βάση δεδομένων έχει δημιουργηθεί και έχουμε κάποιες αναρτήσεις σε αυτήν, είναι η κατάλληλη στιγμή να τις εμφανίσουμε στη νέα μας λαμπερή σελίδα.
 
-Πρώτα, πρέπει να πούμε στην εφαρμογή μας ποια βάση δεδομένων θα χρησιμοποιήσει. Η ρύθμιση της σύνδεσης με τη βάση δεδομένων αποθηκεύεται στο `config/local.neon`. Ορίστε τη σύνδεση DSN((Data Source Name)) και τα διαπιστευτήριά σας. Θα πρέπει να μοιάζει κάπως έτσι:
+Πρώτα, πρέπει να πούμε στην εφαρμογή μας ποια βάση δεδομένων θα χρησιμοποιήσει. Η ρύθμιση της σύνδεσης με τη βάση δεδομένων αποθηκεύεται στο `config/common.neon`. Ορίστε τη σύνδεση DSN((Data Source Name)) και τα διαπιστευτήριά σας. Θα πρέπει να μοιάζει κάπως έτσι:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Προσέξτε τις εσοχές κατά την επεξεργασία αυτού του αρχείου. Η [μορφή NEON |neon:format] δέχεται τόσο κενά όσο και ταμπέλες, αλλά όχι και τα δύο μαζί! Το αρχείο ρυθμίσεων στο Web Project χρησιμοποιεί τα tabs ως προεπιλογή.
 
-Ολόκληρη η διαμόρφωση αποθηκεύεται στο `config/` στα αρχεία `common.neon` και `local.neon`. Το αρχείο `common.neon` περιέχει τη γενική διαμόρφωση της εφαρμογής και το `local.neon` περιέχει μόνο τις παραμέτρους που αφορούν το περιβάλλον (π.χ. τη διαφορά μεταξύ του διακομιστή ανάπτυξης και του διακομιστή παραγωγής).
-
 
 Εισαγωγή της σύνδεσης της βάσης δεδομένων .[#toc-injecting-the-database-connection]
 ===================================================================================
 
 Ο παρουσιαστής `HomePresenter`, ο οποίος θα απαριθμεί τα άρθρα, χρειάζεται μια σύνδεση με τη βάση δεδομένων. Για να τη λάβει, γράψτε έναν κατασκευαστή όπως αυτός:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ final class HomePresenter extends Nette\Application\UI\Presenter
 
 Τώρα ας φέρουμε τις αναρτήσεις από τη βάση δεδομένων και ας τις περάσουμε στο πρότυπο, το οποίο στη συνέχεια θα αποδώσει τον κώδικα HTML. Γι' αυτό το σκοπό υπάρχει η λεγόμενη μέθοδος *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Ο παρουσιαστής έχει τώρα μια μέθοδο render `renderDefault()` που περνάει τα δεδομένα σε μια προβολή που ονομάζεται `default`. Τα πρότυπα του παρουσιαστή μπορούν να βρεθούν στο `app/Presenters/templates/{PresenterName}/{viewName}.latte`, οπότε σε αυτή την περίπτωση το πρότυπο θα βρίσκεται στο `app/Presenters/templates/Home/default.latte`. Στο πρότυπο, μια μεταβλητή με το όνομα `$posts` είναι τώρα διαθέσιμη, η οποία περιέχει τις δημοσιεύσεις από τη βάση δεδομένων.
+Ο παρουσιαστής έχει τώρα μια μέθοδο render `renderDefault()` που περνάει τα δεδομένα σε μια προβολή που ονομάζεται `default`. Τα πρότυπα του παρουσιαστή μπορούν να βρεθούν στο `app/UI/{PresenterName}/{viewName}.latte`, οπότε σε αυτή την περίπτωση το πρότυπο θα βρίσκεται στο `app/UI/Home/default.latte`. Στο πρότυπο, μια μεταβλητή με το όνομα `$posts` είναι τώρα διαθέσιμη, η οποία περιέχει τις δημοσιεύσεις από τη βάση δεδομένων.
 
 
 Πρότυπο .[#toc-template]
@@ -128,9 +125,9 @@ public function renderDefault(): void
 
 Υπάρχει ένα γενικό πρότυπο για ολόκληρη τη σελίδα (που ονομάζεται *layout*, με κεφαλίδα, φύλλα στυλ, υποσέλιδο, ...) και στη συνέχεια ειδικά πρότυπα για κάθε προβολή (π.χ. για την εμφάνιση της λίστας των αναρτήσεων του ιστολογίου), τα οποία μπορούν να παρακάμψουν ορισμένα τμήματα του προτύπου layout.
 
-Από προεπιλογή, το πρότυπο διάταξης βρίσκεται στο `templates/@layout.latte`, το οποίο περιέχει:
+Από προεπιλογή, το πρότυπο διάταξης βρίσκεται στο `app/UI/@layout.latte`, το οποίο περιέχει:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ public function renderDefault(): void
 
 `{include content}` εισάγει ένα μπλοκ με το όνομα `content` στο κύριο πρότυπο. Μπορείτε να το ορίσετε στα πρότυπα κάθε προβολής. Σε αυτή την περίπτωση, θα επεξεργαστούμε το αρχείο `Home/default.latte` ως εξής:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ public function renderDefault(): void
 
 Ας εμφανίσουμε τις αναρτήσεις του ιστολογίου - θα επεξεργαστούμε το πρότυπο ως εξής:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ public function renderDefault(): void
 
 Αν ανανεώσετε το πρόγραμμα περιήγησής σας, θα δείτε τη λίστα με τις αναρτήσεις του ιστολογίου σας. Η λίστα δεν είναι πολύ φανταχτερή ή πολύχρωμη, γι' αυτό μη διστάσετε να προσθέσετε κάποιο [λαμπερό CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] στο `www/css/style.css` και να το συνδέσετε σε μια διάταξη:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ public function renderDefault(): void
 
 Και κάτι ακόμα. Μπορούμε να κάνουμε τον κώδικα λίγο πιο σύντομο και συνεπώς πιο απλό. Μπορούμε να αντικαταστήσουμε τα *Latte tags* με *n:attributes* όπως παρακάτω:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/el/model.texy b/quickstart/el/model.texy
index 2f8aa72258..16741f27b8 100644
--- a/quickstart/el/model.texy
+++ b/quickstart/el/model.texy
@@ -36,9 +36,9 @@ final class PostFacade
 
 Θα μεταβούμε στο `HomePresenter` το οποίο θα επεξεργαστούμε έτσι ώστε να απαλλαγούμε από την εξάρτηση από το `Nette\Database\Explorer` αντικαθιστώντας την με μια νέα εξάρτηση από τη νέα μας κλάση.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/el/single-post.texy b/quickstart/el/single-post.texy
index dd6677c763..e5ebda580e 100644
--- a/quickstart/el/single-post.texy
+++ b/quickstart/el/single-post.texy
@@ -5,13 +5,13 @@
 Ας προσθέσουμε μια άλλη σελίδα στο ιστολόγιό μας, η οποία θα εμφανίζει το περιεχόμενο μιας συγκεκριμένης ανάρτησης ιστολογίου.
 
 
-Πρέπει να δημιουργήσουμε μια νέα μέθοδο render, η οποία θα αντλεί μια συγκεκριμένη ανάρτηση του ιστολογίου και θα την περνάει στο πρότυπο. Το να έχουμε αυτή την προβολή στη διεύθυνση `HomePresenter` δεν είναι ωραίο, επειδή πρόκειται για μια ανάρτηση ιστολογίου και όχι για την αρχική σελίδα. Έτσι, ας δημιουργήσουμε μια νέα κλάση `PostPresenter` και ας την τοποθετήσουμε στο `app/Presenters`. Θα χρειαστεί μια σύνδεση με τη βάση δεδομένων, οπότε βάλτε και πάλι εκεί τον κώδικα *database injection*.
+Πρέπει να δημιουργήσουμε μια νέα μέθοδο render, η οποία θα αντλεί μια συγκεκριμένη ανάρτηση του ιστολογίου και θα την περνάει στο πρότυπο. Το να έχουμε αυτή την προβολή στη διεύθυνση `HomePresenter` δεν είναι ωραίο, επειδή πρόκειται για μια ανάρτηση ιστολογίου και όχι για την αρχική σελίδα. Έτσι, ας δημιουργήσουμε μια νέα κλάση `PostPresenter` και ας την τοποθετήσουμε στο `app/UI/Post/`. Θα χρειαστεί μια σύνδεση με τη βάση δεδομένων, οπότε βάλτε και πάλι εκεί τον κώδικα *database injection*.
 
 Το `PostPresenter` θα πρέπει να μοιάζει με αυτό:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Πρέπει να ορίσουμε ένα σωστό namespaces `App\Presenters` για τον παρουσιαστή μας. Εξαρτάται από την [αντιστοίχιση του παρουσιαστή |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Πρέπει να ορίσουμε ένα σωστό namespaces `App\UI\Post` για τον παρουσιαστή μας. Εξαρτάται από την [αντιστοίχιση του παρουσιαστή |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Η μέθοδος `renderShow` απαιτεί ένα όρισμα - το ID της δημοσίευσης που θα εμφανιστεί. Στη συνέχεια, φορτώνει τη δημοσίευση από τη βάση δεδομένων και περνάει το αποτέλεσμα στο πρότυπο.
 
 Στο πρότυπο `Home/default.latte` προσθέτουμε έναν σύνδεσμο προς την ενέργεια `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 Το ίδιο μπορούμε να γράψουμε σύντομα χρησιμοποιώντας το n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 Έτσι θα δημιουργήσουμε το `Post/show.latte` με αυτό το περιεχόμενο:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Με απλά λόγια, * επαναπροσδιορίζει* ένα μπλοκ που ονομάζεται `title`. Το μπλοκ ορίζεται στο *πρότυπο διάταξης* (`/app/Presenters/templates/@layout.latte:11`) και όπως συμβαίνει με την παράκαμψη OOP, παρακάμπτεται εδώ. Επομένως, το αρχείο της σελίδας `<title>` θα περιέχει τον τίτλο της εμφανιζόμενης ανάρτησης. Έχουμε παρακάμψει τον τίτλο της σελίδας και το μόνο που χρειαζόμασταν ήταν το `n:block="title"`. Υπέροχα, ε;
+Με απλά λόγια, * επαναπροσδιορίζει* ένα μπλοκ που ονομάζεται `title`. Το μπλοκ ορίζεται στο *πρότυπο διάταξης* (`/app/UI/@layout.latte:11`) και όπως συμβαίνει με την παράκαμψη OOP, παρακάμπτεται εδώ. Επομένως, το αρχείο της σελίδας `<title>` θα περιέχει τον τίτλο της εμφανιζόμενης ανάρτησης. Έχουμε παρακάμψει τον τίτλο της σελίδας και το μόνο που χρειαζόμασταν ήταν το `n:block="title"`. Υπέροχα, ε;
 
 Η πέμπτη και τελευταία γραμμή του προτύπου εμφανίζει το πλήρες περιεχόμενο της ανάρτησής σας.
 
@@ -97,14 +97,14 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 Έλεγχος του αναγνωριστικού της δημοσίευσης .[#toc-checking-post-id]
 ===================================================================
 
-Τι συμβαίνει αν κάποιος αλλάξει το URL και εισάγει το `postId` που δεν υπάρχει? Θα πρέπει να παρέχουμε στο χρήστη ένα ωραίο σφάλμα "η σελίδα δεν βρέθηκε". Ας ενημερώσουμε τη μέθοδο render στο `PostPresenter`:
+Τι συμβαίνει αν κάποιος αλλάξει το URL και εισάγει το `id` που δεν υπάρχει? Θα πρέπει να παρέχουμε στο χρήστη ένα ωραίο σφάλμα "η σελίδα δεν βρέθηκε". Ας ενημερώσουμε τη μέθοδο render στο `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/en/@home.texy b/quickstart/en/@home.texy
index e900687fef..557b20c8cb 100644
--- a/quickstart/en/@home.texy
+++ b/quickstart/en/@home.texy
@@ -7,7 +7,7 @@ Get to know Nette Framework while creating a simple blog with comments. Let's be
 After the first two chapters, you will have your own working blog and you'll be ready to publish your awesome posts, although the features will be pretty much limited after completing these two chapters. To make things nicer for your users, you should also read the following chapters and keep improving your application.
 
 .[tip]
-This tutorial assumes that you completed the [Installation |nette:installation] document and have successfully set up your tooling.
+This tutorial assumes that you completed the [Installation |nette:installation] document and have successfully set up your tooling. It also assumes that you understand [object-oriented programming in PHP |nette:introduction-to-object-oriented-programming].
 
 Please use PHP 8.1 or later. You can find the complete application [on GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Web Project has the following structure:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← basic necessary classes
+│   ├── <b>UI/</b>           ← presenters, templates & co.
+│   │   └── <b>Home/</b>     ← Home presenter directory
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ The most important directory for you is `app/`. You can find `Bootstrap.php` fil
 Cleanup
 =======
 
-The Web Project contains a welcome page, which we can remove - feel free to delete the `app/Presenters/templates/Home/default.latte` file and replace it with the text "Hello world!".
+The Web Project contains a welcome page, which we can remove - feel free to delete the `app/UI/Home/default.latte` file and replace it with the text "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ The Web Project contains a welcome page, which we can remove - feel free to dele
 Tracy (Debugger)
 ================
 
-An extremely important tool for development is [a debugger called Tracy |tracy:]. Try to make some errors in your `app/Presenters/HomePresenter.php` file (e.g. remove a curly bracket from the definition of class HomePresenter) and see what happens. A red-screen page will pop up with an understandable error description.
+An extremely important tool for development is [a debugger called Tracy |tracy:]. Try to make some errors in your `app/UI/Home/HomePresenter.php` file (e.g. remove a curly bracket from the definition of class HomePresenter) and see what happens. A red-screen page will pop up with an understandable error description.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy will significantly help you while hunting down errors. Also note the floating Tracy Bar in the bottom right corner, which informs you about important runtime data.
 
@@ -88,8 +88,7 @@ In the production mode, Tracy is, of course, disabled and does not reveal any se
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/en/authentication.texy b/quickstart/en/authentication.texy
index cf88eb126f..a193dabd50 100644
--- a/quickstart/en/authentication.texy
+++ b/quickstart/en/authentication.texy
@@ -28,9 +28,9 @@ We now have the backend part of authentication ready and we need to provide a us
 
 Let's start with the login form. You already know how forms work in a presenter. Create the `SignPresenter` and method `createComponentSignInForm`. It should look like this:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Template
 
 The form will be rendered in the template `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ We add also a *form handler* for signing in the user, that gets invoked right af
 
 The handler will just take the username and password the user entered and will pass it to the authenticator defined earlier. After the user has logged in, we will redirect him to the homepage.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ We will secure a form for adding and editing posts. It is defined in the present
 
 We create a method `startup()` that is started immediately at the beginning of the [presenter life cycle|application:presenters#life-cycle-of-presenter]. This redirects non-logged-in users to the login form.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Hide Links
 ----------
 
-An unauthenticated user can no longer see the *create* nor *edit page*, but he can still see the links pointing to them. Let's hide those as well. One such link is in `app/Presenters/templates/Home/default.latte`, and it should be visible only if the user is logged in.
+An unauthenticated user can no longer see the *create* nor *edit page*, but he can still see the links pointing to them. Let's hide those as well. One such link is in `app/UI/Home/default.latte`, and it should be visible only if the user is logged in.
 
 We can hide it using *n:attribute* called `n:if`. If the statement inside it is `false`, the whole `<a>` tag and it's contents will be not displayed:
 
@@ -131,7 +131,7 @@ this is a shortcut for (do not confuse it with `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-You should hide the edit link located in `app/Presenters/templates/Post/show.latte` in a similar fashion.
+You should hide the edit link located in `app/UI/Post/show.latte` in a similar fashion.
 
 
 Login Form Link
@@ -139,7 +139,7 @@ Login Form Link
 
 Hey, but how do we get to the login page? There is no link pointing to it. Let's add one in the `@layout.latte` template file. Try finding a nice place, it can be anywhere you like it the most.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ If the user is not yet logged in, we will show the "Sign in" link. Otherwise, we
 
 The logout action looks like this, and because we redirect the user immediately, there is no need for a view template.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/en/comments.texy b/quickstart/en/comments.texy
index a87d7f4481..b73b355cec 100644
--- a/quickstart/en/comments.texy
+++ b/quickstart/en/comments.texy
@@ -44,7 +44,7 @@ First, we need to create a form, that will allow the users to comment on our pag
 
 Nette Framework has a concept of *components*. A **component** is a reusable class or piece of code, that can be attached to another component. Even a presenter is a component. Each component is created using the component factory. So let’s define the comments form factory in `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // means Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Let’s explain it a little bit. The first line creates a new instance of `Form`
 
 Once the form component is defined in a presenter, we can render (display) it in a template. To do so, place the tag `{control}` at the end of the post detail template, in `Post/show.latte`. Because the component's name is `commentForm` (it's derived from the name of the method `createComponentCommentForm`), the tag will look like this
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 It means "after the form is successfully submitted, call the method `commentFormSucceeded` of the current presenter". This method does not exist yet, so let’s create it.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ The new method has one argument which is the instance of the form being submitte
 
 There are two more method calls to explain. The redirect literally redirects to the current page. You should do that every time when the form is submitted, valid, and the callback operation did what it should have done. Also, when you redirect the page after submitting the form, you won’t see the well known `Would you like to submit the post data again?` message that you can sometimes see in the browser. (In general, after submitting a form by `POST` method, you should always redirect the user to a `GET` action.)
 
-The `flashMessage` is for informing the user about the result of some operation. Because we’re redirecting, the message cannot be directly passed to the template and rendered. So there is this method, that will store it and make it available on the next page load. The flash messages are rendered in the default `app/Presenters/templates/@layout.latte` file, and it looks like this:
+The `flashMessage` is for informing the user about the result of some operation. Because we’re redirecting, the message cannot be directly passed to the template and rendered. So there is this method, that will store it and make it available on the next page load. The flash messages are rendered in the default `app/UI/@layout.latte` file, and it looks like this:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer uses the foreign keys to resolve relations between table
 
 As you may remember, we’ve passed the `$post` variable to the template in `PostPresenter::renderShow()` and now we want to iterate through all the comments that have the column `post_id` equal to our `$post->id`. You can do it by calling `$post->related('comments')`. It’s that simple. Look at the resulting code.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 And the template:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/en/creating-posts.texy b/quickstart/en/creating-posts.texy
index c9c57f8ea2..221aeec2b9 100644
--- a/quickstart/en/creating-posts.texy
+++ b/quickstart/en/creating-posts.texy
@@ -20,11 +20,11 @@ Later we’ll also add authentication and allow only logged-in users to add new
 New Presenter
 =============
 
-Name the new presenter `EditPresenter` and save it in `app/Presenters/EditPresenter.php`. It also needs to connect to the database, so here again we write a constructor that will require a database connection:
+Name the new presenter `EditPresenter` and save it in `app/UI/Edit/`. It also needs to connect to the database, so here again we write a constructor that will require a database connection:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Forms and components have been already covered when we were adding support for c
 
 Now add this method to the `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Saving New Post from Form
 
 Continue by adding a handler method.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Page for Creating a New Post
 
 Let’s just create the template `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Link for Creating Posts
 
 You probably already know how to add a link to `EditPresenter` and its `create` action. Try it out.
 
-Just add to the `app/Presenters/templates/Home/default.latte` file:
+Just add to the `app/UI/Home/default.latte` file:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Let’s also add the capability to edit existing posts. It shall be pretty simpl
 
 We’ll add a new `edit` page to the `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 And create the template `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ And create the template `Edit/edit.latte`:
 
 And update the method `postFormSucceeded`, which will be able either to add a new post (as it does now), or to edit existing ones:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-When `postId` parameter is provided, it means that a post is being edited. In such case, we’ll check that the post really exists and if so, we’ll update it in the database. If the `postId` is not provided, it means that a new post shall be added.
+When `id` parameter is provided, it means that a post is being edited. In such case, we’ll check that the post really exists and if so, we’ll update it in the database. If the `id` is not provided, it means that a new post shall be added.
 
-But where does the `postId` come from? It is the parameter passed to `renderEdit` method.
+But where does the `id` come from? It is the parameter passed to `renderEdit` method.
 
-You can now add a link to the `app/Presenters/templates/Post/show.latte` template:
+You can now add a link to the `app/UI/Post/show.latte` template:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/en/home-page.texy b/quickstart/en/home-page.texy
index 411f3dd8a3..b27822ff19 100644
--- a/quickstart/en/home-page.texy
+++ b/quickstart/en/home-page.texy
@@ -66,9 +66,9 @@ Connecting to the Database
 
 Now, when the database is created and we have some posts in it, it’s the right time to display them on our new shiny page.
 
-First, we need to tell our application about which database to use. The database connection configuration is stored in `config/local.neon`. Set the connection DSN((Data Source Name)) and your credentials. It should look like this:
+First, we need to tell our application about which database to use. The database connection configuration is stored in `config/common.neon`. Set the connection DSN((Data Source Name)) and your credentials. It should look like this:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Be aware of indenting while editing this file. [NEON format|neon:format] accepts both spaces and tabs but not both together! The configuration file in the Web Project uses tabs as default.
 
-The whole configuration including is stored in `config/` in files `common.neon` and `local.neon`. File `common.neon` contains the global configuration of the application and `local.neon` contains only the parameters specific to the environment (e.g. the difference between development and production server).
-
 
 Injecting the Database Connection
 =================================
 
 The presenter `HomePresenter`, which will list the articles, needs a database connection. To receive it, write a constructor like this:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Loading Posts from the Database
 
 Now let’s fetch the posts from the database and pass them to the template, which will then render the HTML code. This is what the so-called *render* method is for:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-The presenter now has one render method `renderDefault()` that passes data to a view called `default`. Presenter templates can be found in `app/Presenters/templates/{PresenterName}/{viewName}.latte`, so in this case the template will be located in `app/Presenters/templates/Home/default.latte`. In the template, a variable named `$posts` is now available, which contains the posts from database.
+The presenter now has one render method `renderDefault()` that passes data to a view called `default`. Presenter templates can be found in `app/UI/{PresenterName}/{viewName}.latte`, so in this case the template will be located in `app/UI/Home/default.latte`. In the template, a variable named `$posts` is now available, which contains the posts from database.
 
 
 Template
@@ -128,9 +125,9 @@ Template
 
 There is a generic template for the whole page (called *layout*, with header, stylesheets, footer, ...) and then specific templates for each view (e.g. for displaying the list of blog posts), which can override some of layout template parts.
 
-By default, the layout template is located in `templates/@layout.latte`, which contains:
+By default, the layout template is located in `app/UI/@layout.latte`, which contains:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ By default, the layout template is located in `templates/@layout.latte`, which c
 
 `{include content}` inserts a block named `content` into the main template. You can define it in the templates of each view. In this case, we will edit the file `Home/default.latte` like this:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ It defines the *content* [block |latte:tags#block], which will be inserted into
 
 Let’s display the blog posts - we will edit the template like this:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Let’s display the blog posts - we will edit the template like this:
 
 If you refresh your browser, you’ll see the list of your blog posts. The list isn't very fancy or colorful, so feel free to add some [shiny CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] to `www/css/style.css` and link it in a layout:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ The `|date` thing is called a filter. Filters are used to format the output. Thi
 
 One more thing. We can make the code a little bit shorter and thus simpler. We can replace *Latte tags* with *n:attributes* like this:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/en/model.texy b/quickstart/en/model.texy
index 08765fa6b8..8dce0cbc8b 100644
--- a/quickstart/en/model.texy
+++ b/quickstart/en/model.texy
@@ -36,9 +36,9 @@ In the class we pass the database Explorer:[api:Nette\Database\Explorer]. This w
 
 We will switch to `HomePresenter` which we will edit so that we get rid of the dependency on `Nette\Database\Explorer` replacing that with a new dependency on our new class.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/en/single-post.texy b/quickstart/en/single-post.texy
index 9618f4281a..4f34bc1d97 100644
--- a/quickstart/en/single-post.texy
+++ b/quickstart/en/single-post.texy
@@ -5,13 +5,13 @@ Single Post Page
 Let’s add another page to our blog, which will display the content of one particular blog post.
 
 
-We need to create a new render method, that will fetch one specific blog post and pass it to the template. Having this view in `HomePresenter` is not nice because it’s about a blog post, not the homepage. So, let’s create a new class `PostPresenter` and place it to `app/Presenters`. It will need a database connection, so put the *database injection* code there again.
+We need to create a new render method, that will fetch one specific blog post and pass it to the template. Having this view in `HomePresenter` is not nice because it’s about a blog post, not the homepage. So, let’s create a new class `PostPresenter` and place it to `app/UI/Post/`. It will need a database connection, so put the *database injection* code there again.
 
 The `PostPresenter` should look like this:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-We have to set a correct namespaces `App\Presenters` for our presenter. It depends on [presenter mapping |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+We have to set a correct namespaces `App\UI\Post` for our presenter. It depends on [presenter mapping |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 The `renderShow` method requires one argument - the ID of the post to be displayed. Then, it loads the post from the database and passes the result to the template.
 
 In the `Home/default.latte` template we add a link to the `Post:show` action:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Tag `{link}` generates URL address which points to the action `Post:show`. This
 
 The same we can write shortly using n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ The template for `Post:show` action does not yet exist. We can open a link to th
 
 So we'll create `Post/show.latte` with this content:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ The fourth line displays the *title* of the blog post as a `<h1>` heading. There
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-In simple words, it *re-defines* a block called `title`. The block is defined in *layout template* (`/app/Presenters/templates/@layout.latte:11`) and like with OOP overriding, it gets overridden here. Therefore, the page’s `<title>` will contain the title of the displayed post. We’ve overridden the title of the page and all we needed was `n:block="title"`. Great, huh?
+In simple words, it *re-defines* a block called `title`. The block is defined in *layout template* (`/app/UI/@layout.latte:11`) and like with OOP overriding, it gets overridden here. Therefore, the page’s `<title>` will contain the title of the displayed post. We’ve overridden the title of the page and all we needed was `n:block="title"`. Great, huh?
 
 The fifth and the last line of the template displays full content of your post.
 
@@ -97,14 +97,14 @@ The fifth and the last line of the template displays full content of your post.
 Checking Post ID
 ================
 
-What happens if someone alters the URL and inserts `postId` which does not exist? We should provide the user with a nice "page not found" error. Let’s update the render method in `PostPresenter`:
+What happens if someone alters the URL and inserts `id` which does not exist? We should provide the user with a nice "page not found" error. Let’s update the render method in `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/es/@home.texy b/quickstart/es/@home.texy
index e7fcf1dbba..bfad494e54 100644
--- a/quickstart/es/@home.texy
+++ b/quickstart/es/@home.texy
@@ -7,7 +7,7 @@ Conoce Nette Framework mientras creas un sencillo blog con comentarios. ¡Empece
 Después de los dos primeros capítulos, tendrás tu propio blog funcionando y estarás listo para publicar tus increíbles posts, aunque las características serán bastante limitadas después de completar estos dos capítulos. Para hacer las cosas más agradables para tus usuarios, también deberías leer los siguientes capítulos y seguir mejorando tu aplicación.
 
 .[tip]
-Este tutorial asume que usted ha completado el documento de [Instalación |nette:installation] y ha configurado con éxito sus herramientas.
+Este tutorial asume que usted ha completado el documento de [Instalación |nette:installation] y ha configurado exitosamente sus herramientas. También asume que usted entiende la [programación orientada a objetos en PHP |nette:introduction-to-object-oriented-programming].
 
 Por favor, utilice PHP 8.1 o posterior. Puedes encontrar la aplicación completa [en GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Web Project tiene la siguiente estructura:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← directorio de aplicaciones
-│   ├── <b>Presenters/</b>   ← clases de presentador
-│   │   └── <b>templates/</b>← plantillas
-│   ├── <b>Router/</b>       ← configuración de direcciones URL
+│   ├── <b>Core/</b>         ← clases básicas necesarias.
+│   ├── <b>UI/</b>           ← presentadores, plantillas & co.
+│   │   └── <b>Home/</b>     ← Directorio de presentadores de inicio.
 │   └── <b>Bootstrap.php</b> ← clase de arranque Bootstrap
 ├── <b>bin/</b>              ← scripts para la línea de comandos
 ├── <b>config/</b>           ← archivos de configuración
@@ -67,7 +67,7 @@ El directorio más importante para ti es `app/`. Allí puedes encontrar el archi
 Limpiar .[#toc-cleanup]
 =======================
 
-El Proyecto Web contiene una página de bienvenida, que podemos eliminar - siéntase libre de borrar el archivo `app/Presenters/templates/Home/default.latte` y sustituirlo por el texto "¡Hola mundo!".
+El Proyecto Web contiene una página de bienvenida, que podemos eliminar - siéntase libre de borrar el archivo `app/UI/Home/default.latte` y sustituirlo por el texto "¡Hola mundo!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ El Proyecto Web contiene una página de bienvenida, que podemos eliminar - sién
 Tracy (Depurador) .[#toc-tracy-debugger]
 ========================================
 
-Una herramienta extremadamente importante para el desarrollo es [un depurador llamado Tracy |tracy:]. Intente cometer algunos errores en su archivo `app/Presenters/HomePresenter.php` (por ejemplo, elimine una llave de la definición de la clase HomePresenter) y vea qué ocurre. Aparecerá una página en pantalla roja con una descripción comprensible del error.
+Una herramienta extremadamente importante para el desarrollo es [un depurador llamado Tracy |tracy:]. Intente cometer algunos errores en su archivo `app/UI/Home/HomePresenter.php` (por ejemplo, elimine una llave de la definición de la clase HomePresenter) y vea qué ocurre. Aparecerá una página en pantalla roja con una descripción comprensible del error.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy te ayudará significativamente mientras buscas errores. Observe también la barra flotante de Tracy en la esquina inferior derecha, que le informa sobre datos importantes en tiempo de ejecución.
 
@@ -88,8 +88,7 @@ En el modo de producción, Tracy está, por supuesto, desactivado y no revela ni
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/es/authentication.texy b/quickstart/es/authentication.texy
index 377aa23105..08d7042b80 100644
--- a/quickstart/es/authentication.texy
+++ b/quickstart/es/authentication.texy
@@ -28,9 +28,9 @@ Ya tenemos lista la parte backend de la autenticación y necesitamos proporciona
 
 Empecemos con el formulario de inicio de sesión. Ya sabes cómo funcionan los formularios en un presentador. Crea el `SignPresenter` y el método `createComponentSignInForm`. Debería tener este aspecto:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Plantilla .[#toc-template]
 
 El formulario se mostrará en la plantilla `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Añadimos también un *form handler* para registrar al usuario, que es invocado
 
 El manejador tomará el nombre de usuario y la contraseña introducidos por el usuario y los pasará al autenticador definido anteriormente. Después de que el usuario haya iniciado sesión, lo redirigiremos a la página de inicio.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Aseguraremos un formulario para añadir y editar entradas. Está definido en el
 
 Creamos un método `startup()` que se inicia inmediatamente al principio del [ciclo de vida |application:presenters#life-cycle-of-presenter] del presentador. Esto redirige a los usuarios que no han iniciado sesión al formulario de inicio de sesión.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Ocultar enlaces .[#toc-hide-links]
 ----------------------------------
 
-Un usuario no autentificado ya no puede ver la página *crear* ni *editar*, pero todavía puede ver los enlaces que apuntan a ellas. Ocultémoslos también. Uno de esos enlaces está en `app/Presenters/templates/Home/default.latte`, y debería ser visible sólo si el usuario ha iniciado sesión.
+Un usuario no autentificado ya no puede ver la página *crear* ni *editar*, pero todavía puede ver los enlaces que apuntan a ellas. Ocultémoslos también. Uno de esos enlaces está en `app/UI/Home/default.latte`, y debería ser visible sólo si el usuario ha iniciado sesión.
 
 Podemos ocultarlo usando un *n:attribute* llamado `n:if`. Si la declaración que contiene es `false`, toda la etiqueta `<a>` y su contenido no se mostrarán:
 
@@ -131,7 +131,7 @@ Podemos ocultarlo usando un *n:attribute* llamado `n:if`. Si la declaración que
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Debe ocultar el enlace de edición situado en `app/Presenters/templates/Post/show.latte` de forma similar.
+Debe ocultar el enlace de edición situado en `app/UI/Post/show.latte` de forma similar.
 
 
 Enlace al formulario de inicio de sesión .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Enlace al formulario de inicio de sesión .[#toc-login-form-link]
 
 Hola, pero ¿cómo llegamos a la página de inicio de sesión? No hay ningún enlace que apunte a ella. Vamos a añadir uno en el archivo de plantilla `@layout.latte`. Intenta encontrar un buen lugar, puede ser donde más te guste.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Si el usuario aún no ha iniciado sesión, mostraremos el enlace "Iniciar sesió
 
 La acción de cierre de sesión tiene este aspecto, y como redirigimos al usuario inmediatamente, no hay necesidad de una plantilla de vista.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/es/comments.texy b/quickstart/es/comments.texy
index 35b33c1be5..7241127788 100644
--- a/quickstart/es/comments.texy
+++ b/quickstart/es/comments.texy
@@ -44,7 +44,7 @@ Primero, necesitamos crear un formulario, que permitirá a los usuarios comentar
 
 Nette Framework tiene un concepto de *componentes*. Un **componente** es una clase reutilizable o una pieza de código, que puede ser adjuntada a otro componente. Incluso un presentador es un componente. Cada componente se crea utilizando la fábrica de componentes. Así que vamos a definir la fábrica de formularios de comentarios en `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // means Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Vamos a explicarlo un poco. La primera línea crea una nueva instancia del compo
 
 Una vez definido el componente formulario en un presentador, podemos renderizarlo (mostrarlo) en una plantilla. Para ello, coloque la etiqueta `{control}` al final de la plantilla de detalles de la entrada, en `Post/show.latte`. Dado que el nombre del componente es `commentForm` (se deriva del nombre del método `createComponentCommentForm`), la etiqueta tendrá el siguiente aspecto
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Significa "después de que el formulario se envíe correctamente, llama al método `commentFormSucceeded` del presentador actual". Este método no existe todavía, así que vamos a crearlo.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ El nuevo método tiene un argumento que es la instancia del formulario que se es
 
 Hay otras dos llamadas a métodos que explicar. La redirección redirige literalmente a la página actual. Deberías hacer eso cada vez que el formulario es enviado, válido, y la operación callback hizo lo que debería haber hecho. Además, cuando redirija la página después de enviar el formulario, no verá el conocido mensaje `Would you like to submit the post data again?` que a veces puede ver en el navegador. (En general, después de enviar un formulario por el método `POST`, siempre debes redirigir al usuario a una acción `GET` ).
 
-El `flashMessage` sirve para informar al usuario del resultado de alguna operación. Debido a que estamos redirigiendo, el mensaje no puede ser pasado directamente a la plantilla y renderizado. Así que existe este método, que lo almacenará y lo hará disponible en la siguiente carga de página. Los mensajes flash son renderizados en el archivo por defecto `app/Presenters/templates/@layout.latte`, y se ve así:
+El `flashMessage` sirve para informar al usuario del resultado de alguna operación. Debido a que estamos redirigiendo, el mensaje no puede ser pasado directamente a la plantilla y renderizado. Así que existe este método, que lo almacenará y lo hará disponible en la siguiente carga de página. Los mensajes flash son renderizados en el archivo por defecto `app/UI/@layout.latte`, y se ve así:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer utiliza las claves externas para resolver las relaciones
 
 Como recordará, hemos pasado la variable `$post` a la plantilla en `PostPresenter::renderShow()` y ahora queremos iterar por todos los comentarios que tengan la columna `post_id` igual a nuestra `$post->id`. Puedes hacerlo llamando a `$post->related('comments')`. Así de sencillo. Mira el código resultante.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 Y la plantilla:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/es/creating-posts.texy b/quickstart/es/creating-posts.texy
index 12c932928f..0c7bc6b660 100644
--- a/quickstart/es/creating-posts.texy
+++ b/quickstart/es/creating-posts.texy
@@ -20,11 +20,11 @@ Más adelante también añadiremos autenticación y permitiremos que sólo los u
 Nuevo presentador .[#toc-new-presenter]
 =======================================
 
-Nombra al nuevo presentador `EditPresenter` y guárdalo en `app/Presenters/EditPresenter.php`. También necesita conectarse a la base de datos, así que aquí de nuevo escribimos un constructor que requerirá una conexión a la base de datos:
+Nombra al nuevo presentador `EditPresenter` y guárdalo en `app/UI/Edit/`. También necesita conectarse a la base de datos, así que aquí de nuevo escribimos un constructor que requerirá una conexión a la base de datos:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Los formularios y componentes ya han sido cubiertos cuando añadimos soporte par
 
 Ahora añade este método a `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Guardar nueva entrada desde el formulario .[#toc-saving-new-post-from-form]
 
 Continúe añadiendo un método manejador.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Página para crear un nuevo post .[#toc-page-for-creating-a-new-post]
 
 Vamos a crear la plantilla `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Enlace para crear entradas .[#toc-link-for-creating-posts]
 
 Probablemente ya sabes cómo añadir un enlace a `EditPresenter` y su acción `create`. Pruébalo.
 
-Sólo tiene que añadir al archivo `app/Presenters/templates/Home/default.latte`:
+Sólo tiene que añadir al archivo `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Añadamos también la capacidad de editar entradas existentes. Será bastante si
 
 Añadiremos una nueva página `edit` a `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 Y crearemos la plantilla `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ Y crearemos la plantilla `Edit/edit.latte`:
 
 Y actualizar el método `postFormSucceeded`, que será capaz de añadir un nuevo mensaje (como lo hace ahora), o para editar los ya existentes:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Cuando se proporciona el parámetro `postId`, significa que se está editando un post. En tal caso, comprobaremos que la entrada existe realmente y, si es así, la actualizaremos en la base de datos. Si no se proporciona el parámetro `postId`, significa que se añadirá un nuevo mensaje.
+Cuando se proporciona el parámetro `id`, significa que se está editando un post. En tal caso, comprobaremos que la entrada existe realmente y, si es así, la actualizaremos en la base de datos. Si no se proporciona el parámetro `id`, significa que se añadirá un nuevo mensaje.
 
-¿Pero de dónde viene `postId`? Es el parámetro que se pasa al método `renderEdit`.
+¿Pero de dónde viene `id`? Es el parámetro que se pasa al método `renderEdit`.
 
-Ahora puede añadir un enlace a la plantilla `app/Presenters/templates/Post/show.latte`:
+Ahora puede añadir un enlace a la plantilla `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/es/home-page.texy b/quickstart/es/home-page.texy
index 9eb7e78e61..e5874d2c5f 100644
--- a/quickstart/es/home-page.texy
+++ b/quickstart/es/home-page.texy
@@ -66,9 +66,9 @@ Conexión a la base de datos .[#toc-connecting-to-the-database]
 
 Ahora, cuando la base de datos está creada y tenemos algunos posts en ella, es el momento de mostrarlos en nuestra nueva y brillante página.
 
-Primero, necesitamos decirle a nuestra aplicación qué base de datos usar. La configuración de la conexión a la base de datos se almacena en `config/local.neon`. Configura la conexión DSN((Data Source Name)) y tus credenciales. Debería verse así:
+Primero, necesitamos decirle a nuestra aplicación qué base de datos usar. La configuración de la conexión a la base de datos se almacena en `config/common.neon`. Configura la conexión DSN((Data Source Name)) y tus credenciales. Debería verse así:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Tenga en cuenta la sangría al editar este archivo. El [formato NEON |neon:format] acepta tanto espacios como tabuladores, pero no ambos a la vez. El archivo de configuración del Proyecto Web utiliza tabuladores por defecto.
 
-Toda la configuración incluida se almacena en `config/` en los archivos `common.neon` y `local.neon`. El archivo `common.neon` contiene la configuración global de la aplicación y `local.neon` contiene sólo los parámetros específicos del entorno (por ejemplo, la diferencia entre el servidor de desarrollo y el de producción).
-
 
 Inyección de la conexión a la base de datos .[#toc-injecting-the-database-connection]
 =====================================================================================
 
 El presentador `HomePresenter`, que listará los artículos, necesita una conexión a la base de datos. Para recibirla, escribe un constructor como este:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Cargar mensajes de la base de datos .[#toc-loading-posts-from-the-database]
 
 Ahora vamos a obtener las entradas de la base de datos y pasarlas a la plantilla, que luego renderizará el código HTML. Para esto está el método *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-El presentador tiene ahora un método render `renderDefault()` que pasa los datos a una vista llamada `default`. Las plantillas del presentador se pueden encontrar en `app/Presenters/templates/{PresenterName}/{viewName}.latte`, así que en este caso la plantilla se encontrará en `app/Presenters/templates/Home/default.latte`. En la plantilla, ahora está disponible una variable llamada `$posts`, que contiene los mensajes de la base de datos.
+El presentador tiene ahora un método render `renderDefault()` que pasa los datos a una vista llamada `default`. Las plantillas del presentador se pueden encontrar en `app/UI/{PresenterName}/{viewName}.latte`, así que en este caso la plantilla se encontrará en `app/UI/Home/default.latte`. En la plantilla, ahora está disponible una variable llamada `$posts`, que contiene los mensajes de la base de datos.
 
 
 Plantilla .[#toc-template]
@@ -128,9 +125,9 @@ Plantilla .[#toc-template]
 
 Existe una plantilla genérica para toda la página (llamada *layout*, con cabecera, hojas de estilo, pie de página, ...) y luego plantillas específicas para cada vista (por ejemplo, para mostrar la lista de entradas del blog), que pueden anular algunas partes de la plantilla layout.
 
-Por defecto, la plantilla de diseño se encuentra en `templates/@layout.latte`, que contiene:
+Por defecto, la plantilla de diseño se encuentra en `app/UI/@layout.latte`, que contiene:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Por defecto, la plantilla de diseño se encuentra en `templates/@layout.latte`,
 
 `{include content}` inserta un bloque llamado `content` en la plantilla principal. Puedes definirlo en las plantillas de cada vista. En este caso, editaremos el archivo `Home/default.latte` así:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Define el [bloque |latte:tags#block] *content*, que se insertará en el diseño.
 
 Vamos a mostrar las entradas del blog - editaremos la plantilla así:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Vamos a mostrar las entradas del blog - editaremos la plantilla así:
 
 Si actualizas tu navegador, verás la lista de entradas de tu blog. La lista no es muy elegante o colorido, así que siéntase libre de añadir un poco de [CSS brillante |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a `www/css/style.css` y vincularlo en un diseño:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Lo de `|date` se llama filtro. Los filtros se utilizan para dar formato a la sal
 
 Una cosa más. Podemos hacer el código un poco más corto y por lo tanto más simple. Podemos reemplazar *Latte tags* por *n:attributes* así:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/es/model.texy b/quickstart/es/model.texy
index 4946906423..7c06309a65 100644
--- a/quickstart/es/model.texy
+++ b/quickstart/es/model.texy
@@ -36,9 +36,9 @@ En la clase pasaremos la base de datos Explorer:[api:Nette\Database\Explorer]. E
 
 Pasaremos a `HomePresenter` que editaremos de forma que nos deshagamos de la dependencia de `Nette\Database\Explorer` sustituyéndola por una nueva dependencia de nuestra nueva clase.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/es/single-post.texy b/quickstart/es/single-post.texy
index 6a37b6f544..687aedbd96 100644
--- a/quickstart/es/single-post.texy
+++ b/quickstart/es/single-post.texy
@@ -5,13 +5,13 @@ Página individual
 Vamos a añadir otra página a nuestro blog, que mostrará el contenido de una entrada del blog en particular.
 
 
-Necesitamos crear un nuevo método de renderizado, que obtendrá una entrada de blog específica y la pasará a la plantilla. Tener esta vista en `HomePresenter` no es agradable porque se trata de una entrada de blog, no de la página principal. Por lo tanto, vamos a crear una nueva clase `PostPresenter` y colocarla en `app/Presenters`. Necesitará una conexión a la base de datos, por lo que pondremos el código de *inyección a la base de datos* allí de nuevo.
+Necesitamos crear un nuevo método de renderizado, que obtendrá una entrada de blog específica y la pasará a la plantilla. Tener esta vista en `HomePresenter` no es agradable porque se trata de una entrada de blog, no de la página principal. Por lo tanto, vamos a crear una nueva clase `PostPresenter` y colocarla en `app/UI/Post/`. Necesitará una conexión a la base de datos, por lo que pondremos el código de *inyección a la base de datos* allí de nuevo.
 
 El `PostPresenter` debería verse así:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Tenemos que establecer un namespaces correcto `App\Presenters` para nuestro presentador. Depende de la [asignación del |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] presentador.
+Tenemos que establecer un namespaces correcto `App\UI\Post` para nuestro presentador. Depende de la [asignación del |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] presentador.
 
 El método `renderShow` requiere un argumento - el ID de la entrada a mostrar. Luego, carga la entrada desde la base de datos y pasa el resultado a la plantilla.
 
 En la plantilla `Home/default.latte` añadimos un enlace a la acción `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ La etiqueta `{link}` genera una dirección URL que apunta a la acción `Post:sho
 
 Lo mismo podemos escribir en breve utilizando n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ La plantilla para la acción `Post:show` aún no existe. Podemos abrir un enlace
 
 Así que vamos a crear `Post/show.latte` con este contenido:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ La cuarta línea muestra el *título* de la entrada del blog como un `<h1>` enca
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-En palabras simples, *redefine* un bloque llamado `title`. El bloque está definido en la *plantilla de diseño* (`/app/Presenters/templates/@layout.latte:11`) y, al igual que ocurre con la sobreescritura de programación orientada a objetos, se sobreescribe aquí. Por lo tanto, la página `<title>` contendrá el título de la entrada mostrada. Hemos sobreescrito el título de la página y todo lo que necesitábamos era `n:block="title"`. Genial, ¿eh?
+En palabras simples, *redefine* un bloque llamado `title`. El bloque está definido en la *plantilla de diseño* (`/app/UI/@layout.latte:11`) y, al igual que ocurre con la sobreescritura de programación orientada a objetos, se sobreescribe aquí. Por lo tanto, la página `<title>` contendrá el título de la entrada mostrada. Hemos sobreescrito el título de la página y todo lo que necesitábamos era `n:block="title"`. Genial, ¿eh?
 
 La quinta y última línea de la plantilla muestra el contenido completo de tu post.
 
@@ -97,14 +97,14 @@ La quinta y última línea de la plantilla muestra el contenido completo de tu p
 Comprobando el ID del post .[#toc-checking-post-id]
 ===================================================
 
-¿Qué pasa si alguien altera la URL e inserta `postId` que no existe? Deberíamos proporcionar al usuario un bonito error de "página no encontrada". Actualicemos el método render en `PostPresenter`:
+¿Qué pasa si alguien altera la URL e inserta `id` que no existe? Deberíamos proporcionar al usuario un bonito error de "página no encontrada". Actualicemos el método render en `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/files/qs-tracy.avif b/quickstart/files/qs-tracy.avif
new file mode 100644
index 0000000000..ad44340733
Binary files /dev/null and b/quickstart/files/qs-tracy.avif differ
diff --git a/quickstart/files/qs-tracy.webp b/quickstart/files/qs-tracy.webp
deleted file mode 100644
index bd5f3cf757..0000000000
Binary files a/quickstart/files/qs-tracy.webp and /dev/null differ
diff --git a/quickstart/fr/@home.texy b/quickstart/fr/@home.texy
index f658dbaf6c..5e6ceaeb7e 100644
--- a/quickstart/fr/@home.texy
+++ b/quickstart/fr/@home.texy
@@ -7,7 +7,7 @@ Apprenez à connaître Nette Framework tout en créant un simple blog avec des c
 Après les deux premiers chapitres, vous aurez votre propre blog fonctionnel et vous serez prêt à publier vos superbes articles, bien que les fonctionnalités soient assez limitées après avoir terminé ces deux chapitres. Pour rendre les choses plus agréables pour vos utilisateurs, vous devriez également lire les chapitres suivants et continuer à améliorer votre application.
 
 .[tip]
-Ce tutoriel suppose que vous avez terminé le document d'[installation |nette:installation] et que vous avez configuré votre outil avec succès.
+Ce tutoriel suppose que vous avez terminé le document d'[installation |nette:installation] et que vous avez configuré votre outil avec succès. Il suppose également que vous comprenez la [programmation orientée objet en PHP |nette:introduction-to-object-oriented-programming].
 
 Veuillez utiliser PHP 8.1 ou plus récent. Vous pouvez trouver l'application complète [sur GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Le projet Web a la structure suivante :
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← répertoire des applications
-│   ├── <b>Presenters/</b>   ← classes de présentateurs
-│   │   └── <b>templates/</b>← modèles
-│   ├── <b>Router/</b>       ← configuration des adresses URL
+│   ├── <b>Core/</b>         ← basic necessary classes
+│   ├── <b>UI/</b>           ← presenters, templates & co.
+│   │   └── <b>Home/</b>     ← Home répertoire de présentateurs
 │   └── <b>Bootstrap.php</b> ← classe de démarrage Bootstrap
 ├── <b>bin/</b>              ← scripts pour la ligne de commande
 ├── <b>config/</b>           ← les fichiers de configuration
@@ -67,7 +67,7 @@ Le répertoire le plus important pour vous est `app/`. Vous y trouverez le fichi
 Nettoyage de .[#toc-cleanup]
 ============================
 
-Le projet Web contient une page de bienvenue, que nous pouvons supprimer - n'hésitez pas à supprimer le fichier `app/Presenters/templates/Home/default.latte` et à le remplacer par le texte "Hello world !".
+Le projet Web contient une page de bienvenue, que nous pouvons supprimer - n'hésitez pas à supprimer le fichier `app/UI/Home/default.latte` et à le remplacer par le texte "Hello world !".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Le projet Web contient une page de bienvenue, que nous pouvons supprimer - n'hé
 Tracy (Débogueur) .[#toc-tracy-debugger]
 ========================================
 
-Un outil extrêmement important pour le développement est [un débogueur appelé Tracy |tracy:]. Essayez de faire quelques erreurs dans votre fichier `app/Presenters/HomePresenter.php` (par exemple, supprimez une accolade de la définition de la classe HomePresenter) et voyez ce qui se passe. Une page d'écran rouge apparaîtra avec une description compréhensible de l'erreur.
+Un outil extrêmement important pour le développement est [un débogueur appelé Tracy |tracy:]. Essayez de faire quelques erreurs dans votre fichier `app/UI/Home/HomePresenter.php` (par exemple, supprimez une accolade de la définition de la classe HomePresenter) et voyez ce qui se passe. Une page d'écran rouge apparaîtra avec une description compréhensible de l'erreur.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy vous aidera considérablement dans la recherche des erreurs. Notez également la barre Tracy flottante dans le coin inférieur droit, qui vous informe sur les données d'exécution importantes.
 
@@ -88,8 +88,7 @@ En mode production, Tracy est, bien entendu, désactivé et ne révèle aucune i
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/fr/authentication.texy b/quickstart/fr/authentication.texy
index 638a3e8ea8..3fa51ed0c5 100644
--- a/quickstart/fr/authentication.texy
+++ b/quickstart/fr/authentication.texy
@@ -28,9 +28,9 @@ Nous avons maintenant la partie backend de l'authentification prête et nous dev
 
 Commençons par le formulaire de connexion. Vous savez déjà comment fonctionnent les formulaires dans un présentateur. Créez le site `SignPresenter` et la méthode `createComponentSignInForm`. Cela devrait ressembler à ceci :
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Modèle .[#toc-template]
 
 Le formulaire sera rendu dans le modèle `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Nous ajoutons également un *manipulateur de formulaire* pour la connexion de l'
 
 Le gestionnaire prendra simplement le nom d'utilisateur et le mot de passe que l'utilisateur a entré et les passera à l'authentificateur défini plus tôt. Après que l'utilisateur se soit connecté, nous le redirigerons vers la page d'accueil.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Nous allons sécuriser un formulaire pour l'ajout et la modification des message
 
 Nous créons une méthode `startup()` qui est lancée immédiatement au début du [cycle de vie du présentateur |application:presenters#life-cycle-of-presenter]. Cette méthode redirige les utilisateurs non connectés vers le formulaire de connexion.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Cacher les liens .[#toc-hide-links]
 -----------------------------------
 
-Un utilisateur non authentifié ne peut plus voir les pages *créer* et *modifier*, mais il peut toujours voir les liens qui y mènent. Cachons-les également. L'un de ces liens se trouve sur `app/Presenters/templates/Home/default.latte`, et il ne doit être visible que si l'utilisateur est connecté.
+Un utilisateur non authentifié ne peut plus voir les pages *créer* et *modifier*, mais il peut toujours voir les liens qui y mènent. Cachons-les également. L'un de ces liens se trouve sur `app/UI/Home/default.latte`, et il ne doit être visible que si l'utilisateur est connecté.
 
 Nous pouvons le masquer en utilisant *n:attribut* appelé `n:if`. Si la déclaration qu'il contient est `false`, l'ensemble de la balise `<a>` et son contenu ne seront pas affichés :
 
@@ -131,7 +131,7 @@ ceci est un raccourci pour (ne pas confondre avec `tag-if`) :
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Vous devez masquer le lien d'édition situé dans `app/Presenters/templates/Post/show.latte` de manière similaire.
+Vous devez masquer le lien d'édition situé dans `app/UI/Post/show.latte` de manière similaire.
 
 
 Lien vers le formulaire de connexion .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Lien vers le formulaire de connexion .[#toc-login-form-link]
 
 Hé, mais comment accéder à la page de connexion ? Il n'y a pas de lien qui pointe vers elle. Ajoutons-en un dans le fichier modèle `@layout.latte`. Essayez de trouver un endroit sympa, ça peut être n'importe quel endroit qui vous plaît le plus.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Si l'utilisateur n'est pas encore connecté, nous afficherons le lien "Sign in".
 
 L'action de déconnexion ressemble à ceci, et parce que nous redirigeons l'utilisateur immédiatement, il n'y a pas besoin d'un modèle de vue.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/fr/comments.texy b/quickstart/fr/comments.texy
index fb14964d78..931f8a36ff 100644
--- a/quickstart/fr/comments.texy
+++ b/quickstart/fr/comments.texy
@@ -44,7 +44,7 @@ Tout d'abord, nous devons créer un formulaire qui permettra aux utilisateurs de
 
 Nette Framework a un concept de *composants*. Un **composant** est une classe réutilisable ou un morceau de code, qui peut être attaché à un autre composant. Même un présentateur est un composant. Chaque composant est créé à l'aide de la fabrique de composants. Définissons donc la fabrique du formulaire de commentaires dans `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // signifie Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Nous allons l'expliquer un peu. La première ligne crée une nouvelle instance d
 
 Une fois le composant de formulaire défini dans un présentateur, nous pouvons le rendre (l'afficher) dans un modèle. Pour ce faire, placez la balise `{control}` à la fin du modèle de détail de l'article, dans `Post/show.latte`. Comme le nom du composant est `commentForm` (dérivé du nom de la méthode `createComponentCommentForm`), la balise ressemblera à ceci
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Elle signifie "après que le formulaire ait été soumis avec succès, appelez la méthode `commentFormSucceeded` du présentateur actuel". Cette méthode n'existe pas encore, alors créons-la.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ La nouvelle méthode a un argument qui est l'instance du formulaire soumis, cré
 
 Il y a deux autres appels de méthode à expliquer. La redirection redirige littéralement vers la page actuelle. Vous devez le faire à chaque fois que le formulaire est soumis, valide et que l'opération de rappel a fait ce qu'elle devait faire. En outre, lorsque vous redirigez la page après avoir soumis le formulaire, vous ne verrez pas le message bien connu `Would you like to submit the post data again?` que vous pouvez parfois voir dans le navigateur. (En général, après avoir soumis un formulaire par la méthode `POST`, vous devriez toujours rediriger l'utilisateur vers une action `GET` ).
 
-Le message `flashMessage` sert à informer l'utilisateur du résultat d'une opération quelconque. Comme il s'agit d'une redirection, le message ne peut pas être transmis directement au modèle et rendu. Il y a donc cette méthode qui le stocke et le rend disponible au prochain chargement de la page. Les messages flash sont rendus dans le fichier `app/Presenters/templates/@layout.latte` par défaut, et cela ressemble à ceci :
+Le message `flashMessage` sert à informer l'utilisateur du résultat d'une opération quelconque. Comme il s'agit d'une redirection, le message ne peut pas être transmis directement au modèle et rendu. Il y a donc cette méthode qui le stocke et le rend disponible au prochain chargement de la page. Les messages flash sont rendus dans le fichier `app/UI/@layout.latte` par défaut, et cela ressemble à ceci :
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer utilise les clés étrangères pour résoudre les relati
 
 Comme vous vous en souvenez peut-être, nous avons passé la variable `$post` au modèle dans `PostPresenter::renderShow()` et maintenant nous voulons itérer à travers tous les commentaires qui ont la colonne `post_id` égale à notre `$post->id`. Vous pouvez le faire en appelant `$post->related('comments')`. C'est aussi simple que cela. Regardez le code résultant.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 Et le modèle :
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/fr/creating-posts.texy b/quickstart/fr/creating-posts.texy
index 05a4cc92de..0717e822ea 100644
--- a/quickstart/fr/creating-posts.texy
+++ b/quickstart/fr/creating-posts.texy
@@ -20,11 +20,11 @@ Plus tard, nous ajouterons également l'authentification et autoriserons uniquem
 Nouveau présentateur .[#toc-new-presenter]
 ==========================================
 
-Nommez le nouveau présentateur `EditPresenter` et enregistrez-le dans `app/Presenters/EditPresenter.php`. Il doit également se connecter à la base de données, donc ici aussi nous écrivons un constructeur qui nécessitera une connexion à la base de données :
+Nommez le nouveau présentateur `EditPresenter` et enregistrez-le dans `app/UI/Edit/`. Il doit également se connecter à la base de données, donc ici aussi nous écrivons un constructeur qui nécessitera une connexion à la base de données :
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Les formulaires et les composants ont déjà été abordés lorsque nous avons a
 
 Maintenant, ajoutez cette méthode à l'adresse `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Enregistrement d'un nouveau message à partir d'un formulaire .[#toc-saving-new-
 
 Continuez en ajoutant une méthode de gestion.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Page de création d'un nouveau message .[#toc-page-for-creating-a-new-post]
 
 Créons simplement le modèle `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Lien pour la création de messages .[#toc-link-for-creating-posts]
 
 Vous savez probablement déjà comment ajouter un lien à `EditPresenter` et à son action `create`. Essayez-le.
 
-Il suffit d'ajouter au fichier `app/Presenters/templates/Home/default.latte`:
+Il suffit d'ajouter au fichier `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Ajoutons également la possibilité de modifier des messages existants. Ce sera
 
 Nous allons ajouter une nouvelle page `edit` au site `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 Et créer le modèle `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ Et créer le modèle `Edit/edit.latte`:
 
 Et mettre à jour la méthode `postFormSucceeded`, qui permettra soit d'ajouter un nouveau message (comme maintenant), soit de modifier les messages existants :
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Lorsque le paramètre `postId` est fourni, cela signifie qu'un message est en cours de modification. Dans ce cas, nous vérifierons que le message existe réellement et si c'est le cas, nous le mettrons à jour dans la base de données. Si le paramètre `postId` n'est pas fourni, cela signifie qu'un nouveau message sera ajouté.
+Lorsque le paramètre `id` est fourni, cela signifie qu'un message est en cours de modification. Dans ce cas, nous vérifierons que le message existe réellement et si c'est le cas, nous le mettrons à jour dans la base de données. Si le paramètre `id` n'est pas fourni, cela signifie qu'un nouveau message sera ajouté.
 
-Mais d'où vient le `postId`? C'est le paramètre passé à la méthode `renderEdit`.
+Mais d'où vient le `id`? C'est le paramètre passé à la méthode `renderEdit`.
 
-Vous pouvez maintenant ajouter un lien vers le modèle `app/Presenters/templates/Post/show.latte`:
+Vous pouvez maintenant ajouter un lien vers le modèle `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/fr/home-page.texy b/quickstart/fr/home-page.texy
index 9b97de5ee3..7bc98ecc1c 100644
--- a/quickstart/fr/home-page.texy
+++ b/quickstart/fr/home-page.texy
@@ -66,9 +66,9 @@ Connexion à la base de données .[#toc-connecting-to-the-database]
 
 Maintenant, quand la base de données est créée et que nous avons des articles dedans, c'est le bon moment pour les afficher sur notre nouvelle page brillante.
 
-Tout d'abord, nous devons indiquer à notre application quelle base de données utiliser. La configuration de la connexion à la base de données est stockée dans `config/local.neon`. Définissez la connexion DSN((Data Source Name)) et vos informations d'identification. Cela devrait ressembler à ceci :
+Tout d'abord, nous devons indiquer à notre application quelle base de données utiliser. La configuration de la connexion à la base de données est stockée dans `config/common.neon`. Définissez la connexion DSN((Data Source Name)) et vos informations d'identification. Cela devrait ressembler à ceci :
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Faites attention à l'indentation lorsque vous modifiez ce fichier. Le [format NEON |neon:format] accepte les espaces et les tabulations, mais pas les deux ensemble ! Le fichier de configuration du projet Web utilise les tabulations par défaut.
 
-L'ensemble de la configuration y compris est stocké dans `config/` dans les fichiers `common.neon` et `local.neon`. Le fichier `common.neon` contient la configuration globale de l'application et `local.neon` ne contient que les paramètres spécifiques à l'environnement (par exemple, la différence entre le serveur de développement et le serveur de production).
-
 
 Injection de la connexion à la base de données .[#toc-injecting-the-database-connection]
 ========================================================================================
 
 Le présentateur `HomePresenter`, qui va lister les articles, a besoin d'une connexion à la base de données. Pour la recevoir, écrivez un constructeur comme celui-ci :
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Chargement des messages depuis la base de données .[#toc-loading-posts-from-the
 
 Maintenant, récupérons les messages de la base de données et transmettons-les au modèle, qui rendra ensuite le code HTML. C'est à cela que sert la méthode dite *render* :
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Le présentateur a maintenant une méthode de rendu `renderDefault()` qui transmet les données à une vue appelée `default`. Les modèles de présentateur peuvent être trouvés dans `app/Presenters/templates/{PresenterName}/{viewName}.latte`, donc dans ce cas le modèle sera situé dans `app/Presenters/templates/Home/default.latte`. Dans le modèle, une variable nommée `$posts` est maintenant disponible, qui contient les messages de la base de données.
+Le présentateur a maintenant une méthode de rendu `renderDefault()` qui transmet les données à une vue appelée `default`. Les modèles de présentateur peuvent être trouvés dans `app/UI/{PresenterName}/{viewName}.latte`, donc dans ce cas le modèle sera situé dans `app/UI/Home/default.latte`. Dans le modèle, une variable nommée `$posts` est maintenant disponible, qui contient les messages de la base de données.
 
 
 Modèle .[#toc-template]
@@ -128,9 +125,9 @@ Modèle .[#toc-template]
 
 Il existe un modèle générique pour l'ensemble de la page (appelé *layout*, avec l'en-tête, les feuilles de style, le pied de page, ...), puis des modèles spécifiques pour chaque vue (par exemple, pour afficher la liste des articles du blog), qui peuvent remplacer certaines parties du modèle layout.
 
-Par défaut, le modèle de mise en page est situé dans `templates/@layout.latte`, qui contient :
+Par défaut, le modèle de mise en page est situé dans `app/UI/@layout.latte`, qui contient :
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Par défaut, le modèle de mise en page est situé dans `templates/@layout.latte
 
 `{include content}` insère un bloc nommé `content` dans le modèle principal. Vous pouvez le définir dans les modèles de chaque vue. Dans ce cas, nous allons éditer le fichier `Home/default.latte` comme ceci :
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Il définit le [bloc |latte:tags#block]*contenu*, qui sera inséré dans la mise
 
 Affichons les articles du blog - nous allons modifier le modèle comme suit :
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Affichons les articles du blog - nous allons modifier le modèle comme suit :
 
 Si vous rafraîchissez votre navigateur, vous verrez la liste de vos articles de blog. La liste n'est pas très fantaisiste ou colorée, alors n'hésitez pas à ajouter quelques [CSS brillants |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] à `www/css/style.css` et à les lier dans une mise en page :
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ L'élément `|date` est appelé un filtre. Les filtres sont utilisés pour forma
 
 Une dernière chose. Nous pouvons rendre le code un peu plus court et donc plus simple. Nous pouvons remplacer les *balises lattes* par des *n:attributs* comme ceci :
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/fr/model.texy b/quickstart/fr/model.texy
index 19a0e76642..54cf940d09 100644
--- a/quickstart/fr/model.texy
+++ b/quickstart/fr/model.texy
@@ -36,9 +36,9 @@ Dans la classe nous passons la base de données Explorer :[api:Nette\Database\Ex
 
 Nous passerons à `HomePresenter` que nous éditerons de manière à nous débarrasser de la dépendance sur `Nette\Database\Explorer` en la remplaçant par une nouvelle dépendance sur notre nouvelle classe.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/fr/single-post.texy b/quickstart/fr/single-post.texy
index 66aeaae68b..8659f68320 100644
--- a/quickstart/fr/single-post.texy
+++ b/quickstart/fr/single-post.texy
@@ -5,13 +5,13 @@ Page d'affichage unique
 Ajoutons une autre page à notre blog, qui affichera le contenu d'un article particulier.
 
 
-Nous devons créer une nouvelle méthode de rendu, qui récupérera un article de blog spécifique et le transmettra au modèle. Avoir cette vue dans `HomePresenter` n'est pas agréable car il s'agit d'un article de blog, pas de la page d'accueil. Donc, créons une nouvelle classe `PostPresenter` et plaçons-la dans `app/Presenters`. Elle aura besoin d'une connexion à la base de données, donc remettez le code *database injection*.
+Nous devons créer une nouvelle méthode de rendu, qui récupérera un article de blog spécifique et le transmettra au modèle. Avoir cette vue dans `HomePresenter` n'est pas agréable car il s'agit d'un article de blog, pas de la page d'accueil. Donc, créons une nouvelle classe `PostPresenter` et plaçons-la dans `app/UI/Post/`. Elle aura besoin d'une connexion à la base de données, donc remettez le code *database injection*.
 
 Le `PostPresenter` devrait ressembler à ceci :
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Nous devons définir un espace de noms correct `App\Presenters` pour notre présentateur. Cela dépend du [mappage du présentateur |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Nous devons définir un espace de noms correct `App\UI\Post` pour notre présentateur. Cela dépend du [mappage du présentateur |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 La méthode `renderShow` requiert un argument - l'ID de l'article à afficher. Ensuite, elle charge l'article depuis la base de données et transmet le résultat au modèle.
 
 Dans le modèle `Home/default.latte`, nous ajoutons un lien vers l'action `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ La balise `{link}` génère une adresse URL qui pointe vers l'action `Post:show`
 
 On peut écrire la même chose en utilisant n:attribute :
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Le modèle pour l'action `Post:show` n'existe pas encore. Nous pouvons ouvrir un
 
 Nous allons donc créer `Post/show.latte` avec ce contenu :
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ La quatrième ligne affiche le *titre* de l'article de blog comme un `<h1>` titr
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-En termes simples, il *re-définit* un bloc appelé `title`. Le bloc est défini dans le *modèle de mise en page* (`/app/Presenters/templates/@layout.latte:11`) et, comme dans le cas de la surcharge de la POO, il est surchargé ici. Par conséquent, la page `<title>` de la page contiendra le titre de l'article affiché. Nous avons remplacé le titre de la page et tout ce dont nous avions besoin était `n:block="title"`. Super, non ?
+En termes simples, il *re-définit* un bloc appelé `title`. Le bloc est défini dans le *modèle de mise en page* (`/app/UI/@layout.latte:11`) et, comme dans le cas de la surcharge de la POO, il est surchargé ici. Par conséquent, la page `<title>` de la page contiendra le titre de l'article affiché. Nous avons remplacé le titre de la page et tout ce dont nous avions besoin était `n:block="title"`. Super, non ?
 
 La cinquième et dernière ligne du modèle affiche le contenu complet de votre article.
 
@@ -97,14 +97,14 @@ La cinquième et dernière ligne du modèle affiche le contenu complet de votre
 Vérification de l'ID du message .[#toc-checking-post-id]
 ========================================================
 
-Que se passe-t-il si quelqu'un modifie l'URL et insère `postId` qui n'existe pas ? Nous devrions fournir à l'utilisateur une belle erreur "page non trouvée". Mettons à jour la méthode de rendu dans `PostPresenter`:
+Que se passe-t-il si quelqu'un modifie l'URL et insère `id` qui n'existe pas ? Nous devrions fournir à l'utilisateur une belle erreur "page non trouvée". Mettons à jour la méthode de rendu dans `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/hu/@home.texy b/quickstart/hu/@home.texy
index 0039d3d464..eee76cf4d6 100644
--- a/quickstart/hu/@home.texy
+++ b/quickstart/hu/@home.texy
@@ -7,7 +7,7 @@ Ismerkedjen meg a Nette Frameworkkel, miközben létrehoz egy egyszerű blogot k
 Az első két fejezet után saját működő blogod lesz, és készen állsz arra, hogy közzétedd a fantasztikus bejegyzéseidet, bár a funkciók eléggé korlátozottak lesznek a két fejezet befejezése után. Hogy a felhasználók számára még szebb legyen, érdemes a következő fejezeteket is elolvasnod, és folyamatosan fejlesztened az alkalmazásodat.
 
 .[tip]
-Ez a bemutató feltételezi, hogy befejezte a [Telepítés |nette:installation] dokumentumot, és sikeresen beállította a szerszámokat.
+Ez a bemutató feltételezi, hogy befejezte a [Telepítés |nette:installation] dokumentumot, és sikeresen beállította a szerszámokat. Feltételezi továbbá, hogy ért az [objektumorientált PHP programozáshoz |nette:introduction-to-object-oriented-programming].
 
 Kérjük, használjon PHP 8.1 vagy újabb verziót. A teljes alkalmazás megtalálható a [GitHubon |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ A Web Project a következő felépítésű:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← alapvető szükséges osztályok
+│   ├── <b>UI/</b>           ← prezenterek, sablonok és társai.
+│   │   │ └── <b>Home/</b>   ← Főoldal prezenter könyvtár
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ A számodra legfontosabb könyvtár a `app/`. Ott találod a `Bootstrap.php` fá
 Tisztítsa meg a .[#toc-cleanup]
 ===============================
 
-A webes projekt tartalmaz egy üdvözlő oldalt, amelyet eltávolíthatunk - nyugodtan töröljük a `app/Presenters/templates/Home/default.latte` fájlt, és cseréljük ki a "Hello world!" szövegre.
+A webes projekt tartalmaz egy üdvözlő oldalt, amelyet eltávolíthatunk - nyugodtan töröljük a `app/UI/Home/default.latte` fájlt, és cseréljük ki a "Hello world!" szövegre.
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ A webes projekt tartalmaz egy üdvözlő oldalt, amelyet eltávolíthatunk - nyu
 Tracy (hibakereső) .[#toc-tracy-debugger]
 =========================================
 
-A fejlesztés rendkívül fontos eszköze a [Tracy nevű hibakereső |tracy:]. Próbálj meg néhány hibát elkövetni a `app/Presenters/HomePresenter.php` fájlodban (pl. távolíts el egy szögletes zárójelet a HomePresenter osztály definíciójából), és nézd meg, mi történik. Egy piros képernyős oldal fog felugrani egy érthető hibaleírással.
+A fejlesztés rendkívül fontos eszköze a [Tracy nevű hibakereső |tracy:]. Próbálj meg néhány hibát elkövetni a `app/UI/Home/HomePresenter.php` fájlodban (pl. távolíts el egy szögletes zárójelet a HomePresenter osztály definíciójából), és nézd meg, mi történik. Egy piros képernyős oldal fog felugrani egy érthető hibaleírással.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 A Tracy jelentősen segít a hibák felkutatásában. Figyelje meg a jobb alsó sarokban lebegő Tracy sávot is, amely tájékoztatja Önt a fontos futásidejű adatokról.
 
@@ -88,8 +88,7 @@ Termelési üzemmódban a Tracy természetesen le van tiltva, és nem árul el s
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/hu/authentication.texy b/quickstart/hu/authentication.texy
index 1a9e205641..668c79e20a 100644
--- a/quickstart/hu/authentication.texy
+++ b/quickstart/hu/authentication.texy
@@ -28,9 +28,9 @@ Most már készen áll a hitelesítés backend része, és meg kell adnunk egy f
 
 Kezdjük a bejelentkezési űrlappal. Azt már tudjuk, hogyan működnek az űrlapok a prezenterben. Hozzuk létre a `SignPresenter` és a `createComponentSignInForm` metódust. Ennek így kell kinéznie:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Sablon .[#toc-template]
 
 Az űrlap a sablonban lesz megjelenítve `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Hozzáadunk egy *űrlapkezelőt* is a felhasználó bejelentkezéséhez, amely a
 
 A kezelő csak a felhasználó által megadott felhasználónevet és jelszót veszi át, és továbbítja a korábban definiált hitelesítőnek. Miután a felhasználó bejelentkezett, átirányítjuk őt a kezdőlapra.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Biztosítani fogunk egy űrlapot a hozzászólások hozzáadásához és szerkes
 
 Létrehozunk egy `startup()` metódust, amely a [prezenter életciklusának |application:presenters#life-cycle-of-presenter] kezdetén azonnal elindul. Ez a nem bejelentkezett felhasználókat a bejelentkezési űrlapra irányítja át.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Linkek elrejtése .[#toc-hide-links]
 -----------------------------------
 
-Egy nem hitelesített felhasználó már nem láthatja sem a *készítés*, sem a *szerkesztés oldalt*, de a rájuk mutató linkeket továbbra is láthatja. Rejtsük el azokat is. Az egyik ilyen link a `app/Presenters/templates/Home/default.latte` oldalon található, és csak akkor legyen látható, ha a felhasználó bejelentkezett.
+Egy nem hitelesített felhasználó már nem láthatja sem a *készítés*, sem a *szerkesztés oldalt*, de a rájuk mutató linkeket továbbra is láthatja. Rejtsük el azokat is. Az egyik ilyen link a `app/UI/Home/default.latte` oldalon található, és csak akkor legyen látható, ha a felhasználó bejelentkezett.
 
 Ezt a `n:if` nevű *n:attribútummal* tudjuk elrejteni. Ha a benne lévő utasítás a `false`, akkor az egész `<a>` tag és annak tartalma nem jelenik meg:
 
@@ -131,7 +131,7 @@ Ez egy rövidítés (ne keverjük össze a `tag-if` címmel):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Hasonló módon el kell rejtenie a `app/Presenters/templates/Post/show.latte` alatt található szerkesztési linket.
+Hasonló módon el kell rejtenie a `app/UI/Post/show.latte` alatt található szerkesztési linket.
 
 
 Bejelentkezési űrlap link .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Bejelentkezési űrlap link .[#toc-login-form-link]
 
 Szia, de hogyan jutunk el a bejelentkezési oldalra? Nincs rá mutató link. Adjunk hozzá egyet a `@layout.latte` sablonfájlban. Próbálj meg találni egy szép helyet, lehet bárhol, ahol a legjobban tetszik.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Ha a felhasználó még nincs bejelentkezve, akkor a "Sign in" linket fogjuk meg
 
 A kijelentkezési művelet így néz ki, és mivel azonnal átirányítjuk a felhasználót, nincs szükség nézetsablonra.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/hu/comments.texy b/quickstart/hu/comments.texy
index bf26a316dd..63f775794c 100644
--- a/quickstart/hu/comments.texy
+++ b/quickstart/hu/comments.texy
@@ -44,7 +44,7 @@ Először is létre kell hoznunk egy űrlapot, amely lehetővé teszi a felhaszn
 
 A Nette Framework rendelkezik a *komponensek* fogalmával. A **komponens** egy újrafelhasználható osztály vagy kódrészlet, amely egy másik komponenshez csatolható. Még a prezenter is egy komponens. Minden komponens a komponens gyár segítségével jön létre. Definiáljuk tehát a `PostPresenter` oldalon a comments form factory-t .
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // jelentése: Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Magyarázzuk el egy kicsit. Az első sor létrehoz egy új példányt a `Form` k
 
 Miután az űrlapkomponens definiálva van egy prezenterben, megjeleníthetjük (megjeleníthetjük) egy sablonban. Ehhez helyezze a `{control}` címkét a poszt részlet sablonjának végére, a `Post/show.latte`. Mivel a komponens neve `commentForm` (a `createComponentCommentForm` metódus nevéből származik), a címke így fog kinézni
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Ez azt jelenti, hogy "az űrlap sikeres elküldése után hívja meg az aktuális prezenter `commentFormSucceeded` metódusát". Ez a metódus még nem létezik, ezért hozzuk létre.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Az új metódusnak egy argumentuma van, ami a beküldendő űrlap példánya, am
 
 Még két metódushívást kell elmagyarázni. A redirect szó szerint átirányít az aktuális oldalra. Ezt minden alkalommal meg kell tennünk, amikor az űrlapot elküldtük, érvényes, és a callback művelet megtette, amit kellett volna. Továbbá, ha az űrlap elküldése után átirányítod az oldalt, nem fogod látni a jól ismert `Would you like to submit the post data again?` üzenetet, amelyet néha láthatsz a böngészőben. (Általánosságban elmondható, hogy egy űrlap `POST` módszerrel történő elküldése után mindig át kell irányítania a felhasználót a `GET` műveletre).
 
-A `flashMessage` arra szolgál, hogy tájékoztassa a felhasználót valamilyen művelet eredményéről. Mivel átirányítunk, az üzenetet nem lehet közvetlenül a sablonhoz átadni és megjeleníteni. Ezért van ez a metódus, amely tárolja és a következő oldalbetöltéskor elérhetővé teszi. A flash üzeneteket az alapértelmezett `app/Presenters/templates/@layout.latte` fájlban rendereljük, és ez így néz ki:
+A `flashMessage` arra szolgál, hogy tájékoztassa a felhasználót valamilyen művelet eredményéről. Mivel átirányítunk, az üzenetet nem lehet közvetlenül a sablonhoz átadni és megjeleníteni. Ezért van ez a metódus, amely tárolja és a következő oldalbetöltéskor elérhetővé teszi. A flash üzeneteket az alapértelmezett `app/UI/@layout.latte` fájlban rendereljük, és ez így néz ki:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ A Nette Database Explorer az idegen kulcsokat használja a táblák közötti ka
 
 Mint emlékezhetsz, a `$post` változót átadtuk a sablonban a `PostPresenter::renderShow()`, és most szeretnénk végigmenni az összes olyan megjegyzésen, amelynek a `post_id` oszlopa megegyezik a mi `$post->id`-unkkal . Ezt a `$post->related('comments')` meghívásával teheti meg. Ez ilyen egyszerű. Nézze meg a kapott kódot.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 És a sablont:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/hu/creating-posts.texy b/quickstart/hu/creating-posts.texy
index c5161e1580..b61c4f1aca 100644
--- a/quickstart/hu/creating-posts.texy
+++ b/quickstart/hu/creating-posts.texy
@@ -20,11 +20,11 @@ Később hitelesítést is hozzáadunk, és csak a bejelentkezett felhasználók
 Új bemutató .[#toc-new-presenter]
 =================================
 
-Nevezzük el az új prezentert `EditPresenter` és mentsük el a `app/Presenters/EditPresenter.php` címre. Az új prezenternek is csatlakoznia kell az adatbázishoz, ezért itt is írunk egy konstruktort, amelyhez adatbázis-kapcsolat szükséges:
+Nevezzük el az új prezentert `EditPresenter` és mentsük el a `app/UI/Edit/` címre. Az új prezenternek is csatlakoznia kell az adatbázishoz, ezért itt is írunk egy konstruktort, amelyhez adatbázis-kapcsolat szükséges:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Az űrlapokkal és komponensekkel már foglalkoztunk, amikor a hozzászólások
 
 Most adjuk hozzá ezt a metódust a `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ protected function createComponentPostForm(): Form
 
 Folytassa egy kezelő metódus hozzáadásával.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Csak egy gyors magyarázat: lekérdezi az értékeket az űrlapról, beilleszti
 
 Hozzuk csak létre a `Edit/create.latte` sablont:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Link a hozzászólások létrehozásához .[#toc-link-for-creating-posts]
 
 Valószínűleg már tudod, hogyan adhatsz linket a `EditPresenter` és a `create` művelethez. Próbálja ki.
 
-Csak adja hozzá a `app/Presenters/templates/Home/default.latte` fájlhoz:
+Csak adja hozzá a `app/UI/Home/default.latte` fájlhoz:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Adjuk hozzá a meglévő hozzászólások szerkesztésének lehetőségét is. E
 
 Hozzáadunk egy új `edit` oldalt a `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 És létrehozzuk a `Edit/edit.latte` sablont:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ public function renderEdit(int $postId): void
 
 És frissítsük a `postFormSucceeded` módszert, amely képes lesz új hozzászólást hozzáadni (ahogy most is), vagy a meglévőket szerkeszteni:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Ha a `postId` paramétert adjuk meg, az azt jelenti, hogy egy hozzászólást szerkesztünk. Ilyen esetben ellenőrizzük, hogy a bejegyzés valóban létezik-e, és ha igen, akkor frissítjük az adatbázisban. Ha a `postId` nincs megadva, akkor ez azt jelenti, hogy egy új bejegyzést kell hozzáadni.
+Ha a `id` paramétert adjuk meg, az azt jelenti, hogy egy hozzászólást szerkesztünk. Ilyen esetben ellenőrizzük, hogy a bejegyzés valóban létezik-e, és ha igen, akkor frissítjük az adatbázisban. Ha a `id` nincs megadva, akkor ez azt jelenti, hogy egy új bejegyzést kell hozzáadni.
 
-De honnan származik a `postId`? Ez a `renderEdit` metódusnak átadott paraméter.
+De honnan származik a `id`? Ez a `renderEdit` metódusnak átadott paraméter.
 
-Most már hozzáadhat egy linket a `app/Presenters/templates/Post/show.latte` sablonhoz:
+Most már hozzáadhat egy linket a `app/UI/Post/show.latte` sablonhoz:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/hu/home-page.texy b/quickstart/hu/home-page.texy
index bbb0f10169..3a23d6d885 100644
--- a/quickstart/hu/home-page.texy
+++ b/quickstart/hu/home-page.texy
@@ -66,9 +66,9 @@ Csatlakozás az adatbázishoz .[#toc-connecting-to-the-database]
 
 Most, hogy az adatbázis elkészült, és van benne néhány bejegyzés, itt az ideje, hogy megjelenítsük őket az új, csillogó oldalunkon.
 
-Először is meg kell mondanunk az alkalmazásunknak, hogy melyik adatbázist használja. Az adatbázis-kapcsolat konfigurációját a `config/local.neon` oldalon tároljuk. Állítsuk be a DSN((Data Source Name)) kapcsolatot és a hitelesítő adatokat. Így kell kinéznie:
+Először is meg kell mondanunk az alkalmazásunknak, hogy melyik adatbázist használja. Az adatbázis-kapcsolat konfigurációját a `config/common.neon` oldalon tároljuk. Állítsuk be a DSN((Data Source Name)) kapcsolatot és a hitelesítő adatokat. Így kell kinéznie:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Figyeljen a behúzásokra a fájl szerkesztése közben. A [NEON formátum |neon:format] elfogadja a szóközöket és a tabulátorokat is, de nem mindkettőt együtt! A webes projekt konfigurációs fájlja alapértelmezés szerint tabulátorokat használ.
 
-A teljes konfiguráció, beleértve a `config/` fájlt is, a `common.neon` és a `local.neon` fájlokban található. A `common.neon` fájl tartalmazza az alkalmazás globális konfigurációját, a `local.neon` pedig csak a környezetre jellemző paramétereket (pl. a fejlesztési és a termelési szerver közötti különbség).
-
 
 Az adatbázis-csatlakozás beillesztése .[#toc-injecting-the-database-connection]
 ===============================================================================
 
 A cikkeket listázó `HomePresenter` bemutatónak szüksége van egy adatbázis-kapcsolatra. Ahhoz, hogy megkapja, írjunk egy ilyen konstruktort:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Hozzászólások betöltése az adatbázisból .[#toc-loading-posts-from-the-dat
 
 Most pedig hívjuk le a bejegyzéseket az adatbázisból, és adjuk át a sablonhoz, amely ezután megjeleníti a HTML kódot. Erre szolgál az úgynevezett *render* metódus:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-A prezenternek most egy renderelési metódusa van: `renderDefault()`, amely az adatokat a `default` nevű nézetnek adja át. A prezenter sablonok a `app/Presenters/templates/{PresenterName}/{viewName}.latte` oldalon találhatók, így ebben az esetben a sablon a `app/Presenters/templates/Home/default.latte` oldalon lesz. A sablonban most már elérhető egy `$posts` nevű változó, amely az adatbázisból származó bejegyzéseket tartalmazza.
+A prezenternek most egy renderelési metódusa van: `renderDefault()`, amely az adatokat a `default` nevű nézetnek adja át. A prezenter sablonok a `app/UI/{PresenterName}/{viewName}.latte` oldalon találhatók, így ebben az esetben a sablon a `app/UI/Home/default.latte` oldalon lesz. A sablonban most már elérhető egy `$posts` nevű változó, amely az adatbázisból származó bejegyzéseket tartalmazza.
 
 
 Sablon .[#toc-template]
@@ -128,9 +125,9 @@ Sablon .[#toc-template]
 
 Van egy általános sablon az egész oldalra (az úgynevezett *layout*, fejléccel, stíluslapokkal, lábléccel, ...), majd specifikus sablonok az egyes nézetekhez (pl. a blogbejegyzések listájának megjelenítéséhez), amelyek felülírhatják a layout sablon egyes részeit.
 
-Alapértelmezés szerint az elrendezési sablon a `templates/@layout.latte` oldalon található, amely a következőket tartalmazza:
+Alapértelmezés szerint az elrendezési sablon a `app/UI/@layout.latte` oldalon található, amely a következőket tartalmazza:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Alapértelmezés szerint az elrendezési sablon a `templates/@layout.latte` olda
 
 `{include content}` beilleszt egy `content` nevű blokkot a fő sablonba. Ezt az egyes nézetek sablonjaiban határozhatja meg. Ebben az esetben a `Home/default.latte` fájlt így szerkesztjük:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Ez határozza meg a *tartalom* [blokkot |latte:tags#block], amely be lesz illesz
 
 Jelenítsük meg a blogbejegyzéseket - a sablont így szerkesztjük:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Jelenítsük meg a blogbejegyzéseket - a sablont így szerkesztjük:
 
 Ha frissítjük a böngészőnket, megjelenik a blogbejegyzések listája. A lista nem túl díszes vagy színes, ezért nyugodtan adjunk hozzá néhány [csillogó CSS-t |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a `www/css/style.css` címre, és linkeljük be egy elrendezésbe:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ A `|date` dolgot szűrőnek hívják. A szűrők a kimenet formázására szolg
 
 Még egy dolog. A kódot egy kicsit rövidebbé és ezáltal egyszerűbbé tehetjük. A *Latte címkéket* helyettesíthetjük *n:attribútumokkal*, így:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/hu/model.texy b/quickstart/hu/model.texy
index 13eea18802..c16362782b 100644
--- a/quickstart/hu/model.texy
+++ b/quickstart/hu/model.texy
@@ -36,9 +36,9 @@ Az osztályban átadjuk az adatbázis Explorer-t:[api:Nette\Database\Explorer].
 
 Átváltunk a `HomePresenter` -ra, amelyet úgy szerkesztünk, hogy megszabadulunk a `Nette\Database\Explorer` függőségtől, és azt az új osztályunk függőségével helyettesítjük.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/hu/single-post.texy b/quickstart/hu/single-post.texy
index d04ee616b9..90fdb96fc5 100644
--- a/quickstart/hu/single-post.texy
+++ b/quickstart/hu/single-post.texy
@@ -5,13 +5,13 @@ Egyetlen poszt oldal
 Adjunk hozzá egy másik oldalt a blogunkhoz, amely egy adott blogbejegyzés tartalmát jeleníti meg.
 
 
-Létre kell hoznunk egy új renderelési metódust, amely egy adott blogbejegyzést fog lekérni és átadni a sablonhoz. Ha ez a nézet a `HomePresenter` oldalon van, az nem szép, mert egy blogbejegyzésről van szó, nem pedig a kezdőlapról. Tehát hozzunk létre egy új osztályt `PostPresenter` és helyezzük el a `app/Presenters`. Szüksége lesz egy adatbázis-kapcsolatra, ezért a *adatbázis injekció* kódot ismét oda tesszük.
+Létre kell hoznunk egy új renderelési metódust, amely egy adott blogbejegyzést fog lekérni és átadni a sablonhoz. Ha ez a nézet a `HomePresenter` oldalon van, az nem szép, mert egy blogbejegyzésről van szó, nem pedig a kezdőlapról. Tehát hozzunk létre egy új osztályt `PostPresenter` és helyezzük el a `app/UI/Post/`. Szüksége lesz egy adatbázis-kapcsolatra, ezért a *adatbázis injekció* kódot ismét oda tesszük.
 
 A `PostPresenter` így kell kinéznie:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Be kell állítanunk egy megfelelő névteret `App\Presenters` a prezenterünk számára. Ez a [prezenter leképezésétől |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] függ.
+Be kell állítanunk egy megfelelő névteret `App\UI\Post` a prezenterünk számára. Ez a [prezenter leképezésétől |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] függ.
 
 A `renderShow` módszer egy argumentumot igényel - a megjelenítendő poszt azonosítóját. Ezután betölti a bejegyzést az adatbázisból, és az eredményt átadja a sablonhoz.
 
 A `Home/default.latte` sablonban a `Post:show` műveletre mutató linket adunk hozzá:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ A `{link}` címke URL-címet generál, amely a `Post:show` akcióra mutat. Ez a
 
 Ugyanezt röviden megírhatjuk az n:attribútum használatával:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ A `Post:show` művelet sablonja még nem létezik. Meg tudjuk nyitni a linket er
 
 Tehát létrehozzuk a `Post/show.latte` címet ezzel a tartalommal:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ A negyedik sor a blogbejegyzés *címét* jeleníti meg, mint egy `<h1>` címké
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Egyszerűen fogalmazva, *újra definiál* egy `title` nevű blokkot. A blokk a *layout template*-ben (`/app/Presenters/templates/@layout.latte:11`) van definiálva, és az OOP felülbíráláshoz hasonlóan itt is felülírásra kerül. Ezért az oldal `<title>` a megjelenített bejegyzés címét fogja tartalmazni. Az oldal címét felülbíráltuk, és ehhez csak a `n:block="title"` kellett. Nagyszerű, nem?
+Egyszerűen fogalmazva, *újra definiál* egy `title` nevű blokkot. A blokk a *layout template*-ben (`/app/UI/@layout.latte:11`) van definiálva, és az OOP felülbíráláshoz hasonlóan itt is felülírásra kerül. Ezért az oldal `<title>` a megjelenített bejegyzés címét fogja tartalmazni. Az oldal címét felülbíráltuk, és ehhez csak a `n:block="title"` kellett. Nagyszerű, nem?
 
 A sablon ötödik és egyben utolsó sorában megjelenik a bejegyzés teljes tartalma.
 
@@ -97,14 +97,14 @@ A sablon ötödik és egyben utolsó sorában megjelenik a bejegyzés teljes tar
 A bejegyzés azonosítójának ellenőrzése .[#toc-checking-post-id]
 ===============================================================
 
-Mi történik, ha valaki megváltoztatja az URL-t és beilleszti a `postId` címet, ami nem létezik? Egy szép "az oldal nem található" hibaüzenetet kell adnunk a felhasználónak. Frissítsük a renderelési metódust a `PostPresenter`:
+Mi történik, ha valaki megváltoztatja az URL-t és beilleszti a `id` címet, ami nem létezik? Egy szép "az oldal nem található" hibaüzenetet kell adnunk a felhasználónak. Frissítsük a renderelési metódust a `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/it/@home.texy b/quickstart/it/@home.texy
index b4e7d163e7..61fdeeb289 100644
--- a/quickstart/it/@home.texy
+++ b/quickstart/it/@home.texy
@@ -7,7 +7,7 @@ Imparate a conoscere Nette Framework creando un semplice blog con commenti. Iniz
 Dopo i primi due capitoli, avrete il vostro blog funzionante e sarete pronti a pubblicare i vostri fantastici post, anche se le funzionalità saranno piuttosto limitate dopo aver completato questi due capitoli. Per rendere le cose più piacevoli ai vostri utenti, dovreste leggere anche i capitoli successivi e continuare a migliorare la vostra applicazione.
 
 .[tip]
-Questa esercitazione presuppone che abbiate completato il documento [Installazione |nette:installation] e che abbiate configurato con successo il vostro tooling.
+Questa esercitazione presuppone che si sia completato il documento di [installazione |nette:installation] e che si sia configurato con successo lo strumento. Si presuppone inoltre che si conosca la [programmazione orientata agli oggetti in PHP |nette:introduction-to-object-oriented-programming].
 
 Utilizzare PHP 8.1 o successivo. L'applicazione completa è disponibile [su GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Il progetto Web ha la seguente struttura:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← classi di base necessarie
+│   ├── <b>UI/</b>           ← presentatori, modelli & co.
+│   │   └── <b>Home/</b>     ← Elenco presentatori Home
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ La directory più importante per voi è `app/`. Vi si trova il file `Bootstrap.p
 Pulire .[#toc-cleanup]
 ======================
 
-Il progetto Web contiene una pagina di benvenuto, che possiamo rimuovere: cancellate pure il file `app/Presenters/templates/Home/default.latte` e sostituitelo con il testo "Hello world!".
+Il progetto Web contiene una pagina di benvenuto, che possiamo rimuovere: cancellate pure il file `app/UI/Home/default.latte` e sostituitelo con il testo "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Il progetto Web contiene una pagina di benvenuto, che possiamo rimuovere: cancel
 Tracy (Debugger) .[#toc-tracy-debugger]
 =======================================
 
-Uno strumento estremamente importante per lo sviluppo è [un debugger chiamato Tracy |tracy:]. Provate a fare qualche errore nel vostro file `app/Presenters/HomePresenter.php` (per esempio, rimuovendo una parentesi graffa dalla definizione della classe HomePresenter) e vedete cosa succede. Verrà visualizzata una pagina a schermo rosso con una descrizione comprensibile dell'errore.
+Uno strumento estremamente importante per lo sviluppo è [un debugger chiamato Tracy |tracy:]. Provate a fare qualche errore nel vostro file `app/UI/Home/HomePresenter.php` (per esempio, rimuovendo una parentesi graffa dalla definizione della classe HomePresenter) e vedete cosa succede. Verrà visualizzata una pagina a schermo rosso con una descrizione comprensibile dell'errore.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy vi aiuterà notevolmente nella ricerca degli errori. Notate anche la barra Tracy fluttuante nell'angolo in basso a destra, che vi informa su importanti dati di runtime.
 
@@ -88,8 +88,7 @@ In modalità di produzione, Tracy è ovviamente disattivato e non rivela alcuna
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/it/authentication.texy b/quickstart/it/authentication.texy
index d87349e81c..f9e88d85d9 100644
--- a/quickstart/it/authentication.texy
+++ b/quickstart/it/authentication.texy
@@ -28,9 +28,9 @@ Ora abbiamo la parte di backend dell'autenticazione pronta e dobbiamo fornire un
 
 Cominciamo con il modulo di accesso. Si sa già come funzionano i moduli in un presentatore. Creare il metodo `SignPresenter` e il metodo `createComponentSignInForm`. Dovrebbe avere questo aspetto:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Modello .[#toc-template]
 
 Il modulo sarà reso nel template `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Aggiungiamo anche un *gestore del modulo* per l'accesso dell'utente, che viene i
 
 Il gestore prenderà il nome utente e la password inseriti dall'utente e li passerà all'autenticatore definito in precedenza. Dopo che l'utente si è loggato, lo reindirizziamo alla homepage.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Verrà messo in sicurezza un modulo per l'aggiunta e la modifica dei messaggi. 
 
 Creiamo un metodo `startup()` che viene avviato immediatamente all'inizio del [ciclo di vita del presentatore |application:presenters#life-cycle-of-presenter]. Questo metodo reindirizza gli utenti non loggati al modulo di login.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Nascondi link .[#toc-hide-links]
 --------------------------------
 
-Un utente non autenticato non può più vedere la pagina *create* né la pagina *edit*, ma può ancora vedere i collegamenti che puntano a esse. Nascondiamo anche quelli. Uno di questi collegamenti si trova in `app/Presenters/templates/Home/default.latte`, e dovrebbe essere visibile solo se l'utente è loggato.
+Un utente non autenticato non può più vedere la pagina *create* né la pagina *edit*, ma può ancora vedere i collegamenti che puntano a esse. Nascondiamo anche quelli. Uno di questi collegamenti si trova in `app/UI/Home/default.latte`, e dovrebbe essere visibile solo se l'utente è loggato.
 
 Possiamo nasconderlo usando un *n:attributo* chiamato `n:if`. Se l'istruzione al suo interno è `false`, l'intero tag `<a>` e il suo contenuto non saranno visualizzati:
 
@@ -131,7 +131,7 @@ questa è una scorciatoia per (non confonderla con `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Si dovrebbe nascondere il link di modifica situato in `app/Presenters/templates/Post/show.latte` in modo simile.
+Si dovrebbe nascondere il link di modifica situato in `app/UI/Post/show.latte` in modo simile.
 
 
 Collegamento al modulo di accesso .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Collegamento al modulo di accesso .[#toc-login-form-link]
 
 Ehi, ma come si arriva alla pagina di login? Non c'è nessun link che punta ad essa. Aggiungiamone uno nel file del template `@layout.latte`. Prova a trovare un posto carino, può essere ovunque ti piaccia di più.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Se l'utente non ha ancora effettuato il login, mostreremo il link "Accedi". Altr
 
 L'azione di logout ha questo aspetto e, poiché reindirizziamo l'utente immediatamente, non è necessario un modello di vista.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/it/comments.texy b/quickstart/it/comments.texy
index b92370bd88..3f349facd9 100644
--- a/quickstart/it/comments.texy
+++ b/quickstart/it/comments.texy
@@ -44,7 +44,7 @@ Per prima cosa, dobbiamo creare un modulo che permetta agli utenti di commentare
 
 Nette Framework ha un concetto di *componenti*. Un **componente** è una classe o un pezzo di codice riutilizzabile, che può essere collegato a un altro componente. Anche un presentatore è un componente. Ogni componente viene creato utilizzando il component factory. Definiamo quindi il factory del modulo dei commenti in `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // significa Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Spieghiamolo un po'. La prima riga crea una nuova istanza del componente `Form`.
 
 Una volta definito il componente del modulo in un presentatore, possiamo renderlo (visualizzarlo) in un template. Per farlo, posizionare il tag `{control}` alla fine del template dei dettagli del post, in `Post/show.latte`. Poiché il nome del componente è `commentForm` (deriva dal nome del metodo `createComponentCommentForm`), il tag avrà il seguente aspetto
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Significa "dopo che il modulo è stato inviato con successo, chiamare il metodo `commentFormSucceeded` del presentatore corrente". Questo metodo non esiste ancora, quindi creiamolo.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Il metodo new ha un parametro, che è l'istanza del form da inviare, creata dal
 
 Ci sono altre due chiamate di metodo da spiegare. Il redirect reindirizza letteralmente alla pagina corrente. Si dovrebbe fare ogni volta che il form è stato inviato, è valido e l'operazione di callback ha fatto ciò che doveva fare. Inoltre, quando si reindirizza la pagina dopo l'invio del modulo, non si vedrà il noto messaggio `Would you like to submit the post data again?`, che a volte si può vedere nel browser. (In generale, dopo aver inviato un modulo con il metodo `POST`, si dovrebbe sempre reindirizzare l'utente a un'azione `GET` ).
 
-Il messaggio `flashMessage` serve a informare l'utente sul risultato di qualche operazione. Poiché si tratta di un rinvio, il messaggio non può essere passato direttamente al template e reso. Quindi c'è questo metodo, che lo memorizza e lo rende disponibile al successivo caricamento della pagina. I messaggi flash sono resi nel file predefinito `app/Presenters/templates/@layout.latte` e si presentano così:
+Il messaggio `flashMessage` serve a informare l'utente sul risultato di qualche operazione. Poiché si tratta di un rinvio, il messaggio non può essere passato direttamente al template e reso. Quindi c'è questo metodo, che lo memorizza e lo rende disponibile al successivo caricamento della pagina. I messaggi flash sono resi nel file predefinito `app/UI/@layout.latte` e si presentano così:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer utilizza le chiavi esterne per risolvere le relazioni tr
 
 Come ricorderete, abbiamo passato la variabile `$post` al modello in `PostPresenter::renderShow()` e ora vogliamo iterare tutti i commenti che hanno la colonna `post_id` uguale alla nostra `$post->id`. Per farlo, basta richiamare `$post->related('comments')`. È così semplice. Guardate il codice risultante.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 E il modello:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/it/creating-posts.texy b/quickstart/it/creating-posts.texy
index 7f69936955..cb923a07ab 100644
--- a/quickstart/it/creating-posts.texy
+++ b/quickstart/it/creating-posts.texy
@@ -20,11 +20,11 @@ In seguito aggiungeremo anche l'autenticazione e permetteremo solo agli utenti l
 Nuovo presentatore .[#toc-new-presenter]
 ========================================
 
-Nominiamo il nuovo presentatore `EditPresenter` e salviamolo in `app/Presenters/EditPresenter.php`. Deve anche connettersi al database, quindi anche in questo caso scriviamo un costruttore che richieda una connessione al database:
+Nominiamo il nuovo presentatore `EditPresenter` e salviamolo in `app/UI/Edit/`. Deve anche connettersi al database, quindi anche in questo caso scriviamo un costruttore che richieda una connessione al database:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ I moduli e i componenti sono già stati trattati quando abbiamo aggiunto il supp
 
 Ora aggiungete questo metodo a `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Salvare un nuovo messaggio dal modulo .[#toc-saving-new-post-from-form]
 
 Continuare aggiungendo un metodo di gestione.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Pagina per la creazione di un nuovo post .[#toc-page-for-creating-a-new-post]
 
 Creiamo il modello `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Collegamento per la creazione dei post .[#toc-link-for-creating-posts]
 
 Probabilmente sapete già come aggiungere un link a `EditPresenter` e alla relativa azione `create`. Provate.
 
-Basta aggiungere al file `app/Presenters/templates/Home/default.latte`:
+Basta aggiungere al file `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Aggiungiamo anche la possibilità di modificare i post esistenti. Sarà piuttost
 
 Aggiungeremo una nuova pagina `edit` al sito `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 E creeremo il modello `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ E creeremo il modello `Edit/edit.latte`:
 
 E aggiornare il metodo `postFormSucceeded`, che potrà sia aggiungere un nuovo post (come fa ora), sia modificare quelli esistenti:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Quando viene fornito il parametro `postId`, significa che si sta modificando un post. In questo caso, controlleremo che il post esista davvero e, in caso affermativo, lo aggiorneremo nel database. Se il parametro `postId` non viene fornito, significa che verrà aggiunto un nuovo post.
+Quando viene fornito il parametro `id`, significa che si sta modificando un post. In questo caso, controlleremo che il post esista davvero e, in caso affermativo, lo aggiorneremo nel database. Se il parametro `id` non viene fornito, significa che verrà aggiunto un nuovo post.
 
-Ma da dove viene `postId`? È il parametro passato al metodo `renderEdit`.
+Ma da dove viene `id`? È il parametro passato al metodo `renderEdit`.
 
-Ora è possibile aggiungere un link al modello `app/Presenters/templates/Post/show.latte`:
+Ora è possibile aggiungere un link al modello `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/it/home-page.texy b/quickstart/it/home-page.texy
index f5698f2217..509c2d54e7 100644
--- a/quickstart/it/home-page.texy
+++ b/quickstart/it/home-page.texy
@@ -66,9 +66,9 @@ Connessione al database .[#toc-connecting-to-the-database]
 
 Ora, quando il database è stato creato e abbiamo alcuni post al suo interno, è il momento giusto per visualizzarli sulla nostra nuova pagina.
 
-Per prima cosa, dobbiamo indicare alla nostra applicazione quale database utilizzare. La configurazione della connessione al database è memorizzata in `config/local.neon`. Impostare la connessione DSN((Data Source Name)) e le credenziali. Dovrebbe essere così:
+Per prima cosa, dobbiamo indicare alla nostra applicazione quale database utilizzare. La configurazione della connessione al database è memorizzata in `config/common.neon`. Impostare la connessione DSN((Data Source Name)) e le credenziali. Dovrebbe essere così:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Fare attenzione all'indentazione durante la modifica di questo file. Il [formato NEON |neon:format] accetta sia spazi che tabulazioni, ma non entrambi insieme! Il file di configurazione del progetto Web utilizza le tabulazioni come impostazione predefinita.
 
-L'intera configurazione è memorizzata in `config/` nei file `common.neon` e `local.neon`. Il file `common.neon` contiene la configurazione globale dell'applicazione e `local.neon` contiene solo i parametri specifici dell'ambiente (ad esempio, la differenza tra il server di sviluppo e quello di produzione).
-
 
 Iniettare la connessione al database .[#toc-injecting-the-database-connection]
 ==============================================================================
 
 Il presentatore `HomePresenter`, che elencherà gli articoli, ha bisogno di una connessione al database. Per riceverla, scrivere un costruttore come questo:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Caricamento dei post dal database .[#toc-loading-posts-from-the-database]
 
 Ora recuperiamo i post dal database e passiamoli al template, che poi renderà il codice HTML. A questo serve il cosiddetto metodo *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Il presentatore ha ora un metodo di render `renderDefault()` che passa i dati a una vista chiamata `default`. I modelli del presentatore si trovano in `app/Presenters/templates/{PresenterName}/{viewName}.latte`, quindi in questo caso il modello si trova in `app/Presenters/templates/Home/default.latte`. Nel modello, è ora disponibile una variabile chiamata `$posts`, che contiene i post del database.
+Il presentatore ha ora un metodo di render `renderDefault()` che passa i dati a una vista chiamata `default`. I modelli del presentatore si trovano in `app/UI/{PresenterName}/{viewName}.latte`, quindi in questo caso il modello si trova in `app/UI/Home/default.latte`. Nel modello, è ora disponibile una variabile chiamata `$posts`, che contiene i post del database.
 
 
 Modello .[#toc-template]
@@ -128,9 +125,9 @@ Modello .[#toc-template]
 
 Esiste un modello generico per l'intera pagina (chiamato *layout*, con intestazione, fogli di stile, piè di pagina, ...) e poi modelli specifici per ogni vista (ad esempio per visualizzare l'elenco dei post del blog), che possono sovrascrivere alcune parti del modello di layout.
 
-Per impostazione predefinita, il modello di layout si trova in `templates/@layout.latte`, che contiene:
+Per impostazione predefinita, il modello di layout si trova in `app/UI/@layout.latte`, che contiene:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Per impostazione predefinita, il modello di layout si trova in `templates/@layou
 
 `{include content}` inserisce un blocco chiamato `content` nel modello principale. È possibile definirlo nei modelli di ciascuna vista. In questo caso, modificheremo il file `Home/default.latte` in questo modo:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Definisce il [blocco |latte:tags#block]*content*, che sarà inserito nel layout.
 
 Visualizziamo i post del blog: modificheremo il template in questo modo:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Visualizziamo i post del blog: modificheremo il template in questo modo:
 
 Se si aggiorna il browser, si vedrà l'elenco dei post del blog. L'elenco non è molto elegante o colorato, quindi sentitevi liberi di aggiungere qualche [CSS brillante |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a `www/css/style.css` e di collegarlo a un layout:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ L'elemento `|date` è chiamato filtro. I filtri sono usati per formattare l'outp
 
 Un'altra cosa. Possiamo rendere il codice un po' più corto e quindi più semplice. Possiamo sostituire i tag *Latte* con *n:attributi* in questo modo:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/it/model.texy b/quickstart/it/model.texy
index 9a6c891511..1388912b41 100644
--- a/quickstart/it/model.texy
+++ b/quickstart/it/model.texy
@@ -36,9 +36,9 @@ Nella classe passiamo il database Explorer:[api:Nette\Database\Explorer]. Questo
 
 Passiamo a `HomePresenter`, che modificheremo in modo da eliminare la dipendenza da `Nette\Database\Explorer`, sostituendola con una nuova dipendenza dalla nostra nuova classe.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/it/single-post.texy b/quickstart/it/single-post.texy
index a897bca6ee..21d5484d05 100644
--- a/quickstart/it/single-post.texy
+++ b/quickstart/it/single-post.texy
@@ -5,13 +5,13 @@ Pagina del singolo post
 Aggiungiamo un'altra pagina al nostro blog, che mostrerà il contenuto di un particolare post.
 
 
-Dobbiamo creare un nuovo metodo di rendering, che recupererà un post specifico del blog e lo passerà al template. Avere questa vista in `HomePresenter` non è bello, perché si tratta di un post del blog, non della homepage. Quindi, creiamo una nuova classe `PostPresenter` e posizioniamola in `app/Presenters`. Avrà bisogno di una connessione al database, quindi inseriamo di nuovo il codice *database injection*.
+Dobbiamo creare un nuovo metodo di rendering, che recupererà un post specifico del blog e lo passerà al template. Avere questa vista in `HomePresenter` non è bello, perché si tratta di un post del blog, non della homepage. Quindi, creiamo una nuova classe `PostPresenter` e posizioniamola in `app/UI/Post/`. Avrà bisogno di una connessione al database, quindi inseriamo di nuovo il codice *database injection*.
 
 `PostPresenter` dovrebbe avere questo aspetto:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Dobbiamo impostare un namespace `App\Presenters` corretto per il nostro presentatore. Dipende dalla [mappatura del presentatore |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Dobbiamo impostare un namespace `App\UI\Post` corretto per il nostro presentatore. Dipende dalla [mappatura del presentatore |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Il metodo `renderShow` richiede un solo parametro: l'ID del post da visualizzare. Quindi, carica il post dal database e passa il risultato al template.
 
 Nel modello `Home/default.latte` aggiungiamo un link all'azione `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Il tag `{link}` genera un indirizzo URL che punta all'azione `Post:show`. Questo
 
 Lo stesso si può scrivere brevemente usando n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Il template per l'azione `Post:show` non esiste ancora. Possiamo aprire un link
 
 Creeremo quindi `Post/show.latte` con questo contenuto:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ La quarta riga mostra il *titolo* del post del blog come un `<h1>` titolo. C'è
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-In parole povere, *ridefinisce* un blocco chiamato `title`. Il blocco è definito nel *modello di layout* (`/app/Presenters/templates/@layout.latte:11`) e, come per l'overriding OOP, viene sovrascritto qui. Pertanto, la pagina `<title>` conterrà il titolo del post visualizzato. Abbiamo sovrascritto il titolo della pagina e tutto ciò di cui avevamo bisogno era `n:block="title"`. Ottimo, no?
+In parole povere, *ridefinisce* un blocco chiamato `title`. Il blocco è definito nel *modello di layout* (`/app/UI/@layout.latte:11`) e, come per l'overriding OOP, viene sovrascritto qui. Pertanto, la pagina `<title>` conterrà il titolo del post visualizzato. Abbiamo sovrascritto il titolo della pagina e tutto ciò di cui avevamo bisogno era `n:block="title"`. Ottimo, no?
 
 La quinta e ultima riga del template mostra il contenuto completo del post.
 
@@ -97,14 +97,14 @@ La quinta e ultima riga del template mostra il contenuto completo del post.
 Controllo dell'ID del post .[#toc-checking-post-id]
 ===================================================
 
-Cosa succede se qualcuno altera l'URL e inserisce `postId` che non esiste? Dovremmo fornire all'utente un simpatico errore di "pagina non trovata". Aggiorniamo il metodo di rendering in `PostPresenter`:
+Cosa succede se qualcuno altera l'URL e inserisce `id` che non esiste? Dovremmo fornire all'utente un simpatico errore di "pagina non trovata". Aggiorniamo il metodo di rendering in `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/pl/@home.texy b/quickstart/pl/@home.texy
index f436718ce8..66f60870f7 100644
--- a/quickstart/pl/@home.texy
+++ b/quickstart/pl/@home.texy
@@ -7,7 +7,7 @@ Poznajmy wspólnie Nette Framework, tworząc jednocześnie prosty blog z komenta
 Po pierwszych dwóch rozdziałach będziesz miał swój własny działający blog i będziesz gotowy do publikowania swoich niesamowitych postów, chociaż funkcje będą dość mocno ograniczone po ukończeniu tych dwóch rozdziałów. Aby uczynić rzeczy milszymi dla Twoich użytkowników, powinieneś również przeczytać kolejne rozdziały i wciąż ulepszać swoją aplikację.
 
 .[tip]
-Ten poradnik zakłada, że użytkownik ukończył dokument [Instalacja |nette:installation] i pomyślnie skonfigurował swoje oprzyrządowanie.
+Ten samouczek zakłada, że ukończyłeś dokument [instalacyjny |nette:installation] i pomyślnie skonfigurowałeś swoje narzędzia. Zakłada również, że rozumiesz [programowanie obiektowe w PHP |nette:introduction-to-object-oriented-programming].
 
 Proszę używać PHP 8.1 lub nowszego. Kompletną aplikację można znaleźć [na GitHubie |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Projekt internetowy ma następującą strukturę:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← adresář s aplikací
-│   ├── <b>Presenters/</b>   ← třídy presenterů
-│   │   └── <b>templates/</b>← šablony
-│   ├── <b>Router/</b>       ← konfigurace URL adres
+│   ├── <b>Core/</b>         ← podstawowe niezbędne klasy
+│   ├─── <b>UI/</b>          ← prezentery, szablony i inne.
+│   │   └── <b>Home/</b>     ← Katalog prezenterów Home
 │   └── <b>Bootstrap.php</b> ← zaváděcí třída Bootstrap
 ├── <b>bin/</b>              ← skripty spouštěné z příkazové řádky
 ├── <b>config/</b>           ← konfigurační soubory
@@ -67,7 +67,7 @@ Najważniejszym dla nas folderem jest `app/`. Znajdziemy tu plik `Bootstrap.php`
 Czyszczenie .[#toc-cleanup]
 ===========================
 
-Web Project zawiera splash page, który usuwamy zanim zaczniemy cokolwiek programować. Nie krępuj się więc zastąpić zawartości strony `app/Presenters/templates/Home/default.latte` słowami "Hello world!".
+Web Project zawiera splash page, który usuwamy zanim zaczniemy cokolwiek programować. Nie krępuj się więc zastąpić zawartości strony `app/UI/Home/default.latte` słowami "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Web Project zawiera splash page, który usuwamy zanim zaczniemy cokolwiek progra
 Tracy (debugger) .[#toc-tracy-debugger]
 =======================================
 
-Niezwykle ważnym narzędziem programistycznym jest [debugger Tracy |tracy:]. Spróbuj wywołać błąd w `app/Presenters/HomePresenter.php` (np. Usuwając nawias w definicji klasy HomePresenter) i zobacz, co się stanie. Pojawi się strona z powiadomieniem, która wyraźnie opisuje błąd.
+Niezwykle ważnym narzędziem programistycznym jest [debugger Tracy |tracy:]. Spróbuj wywołać błąd w `app/UI/Home/HomePresenter.php` (np. Usuwając nawias w definicji klasy HomePresenter) i zobacz, co się stanie. Pojawi się strona z powiadomieniem, która wyraźnie opisuje błąd.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy pomoże nam ogromnie, gdy będziemy szukać błędów w aplikacji. Zwróć też uwagę na pływający w prawym dolnym rogu ekranu pasek Tracy Bar, który zawiera informacje z uruchomionej aplikacji.
 
@@ -88,8 +88,7 @@ Oczywiście w trybie produkcyjnym Tracy jest wyłączona i nie wyświetla żadny
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy($appDir . '/log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/pl/authentication.texy b/quickstart/pl/authentication.texy
index 4bc155b993..80583220d7 100644
--- a/quickstart/pl/authentication.texy
+++ b/quickstart/pl/authentication.texy
@@ -28,9 +28,9 @@ Teraz mamy już gotowe uwierzytelnienie i musimy przygotować interfejs użytkow
 
 Zacznijmy od formularza logowania. Wiemy już jak działają formularze w presenterech. Stwórzmy więc prezenter `SignPresenter` i napiszmy metodę `createComponentSignInForm`. Powinna ona wyglądać coś takiego:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Szablon .[#toc-template]
 
 Formularz zostanie wyrenderowany w szablonie `in.latte`:
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Přihlášení</h1>
 
@@ -77,7 +77,7 @@ Następnie dodamy callback dla logowania użytkownika, który zostanie wywołany
 
 Callback po prostu bierze nazwę użytkownika i hasło, które użytkownik wypełnił i przekazuje je do authenticatora. Po zalogowaniu przekierowujemy na stronę główną.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Udostępniamy formularz do dodawania i edycji prezenterów. Jest to zdefiniowane
 
 Stworzymy metodę `startup()`, która jest uruchamiana natychmiast na początku [cyklu życia prezentera |application:presenters#Life-Cycle-of-Presenter]. To przekierowuje niezalogowanych użytkowników do formularza logowania.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Ukryj linki .[#toc-hide-links]
 ------------------------------
 
-Nieautoryzowany użytkownik nie może już zobaczyć strony *create* lub *edit*, ale nadal może zobaczyć linki do nich. Te również powinniśmy ukryć. Jeden z takich linków znajduje się w szablonie `app/Presenters/templates/Home/default.latte` i powinien być widoczny tylko dla zalogowanych użytkowników.
+Nieautoryzowany użytkownik nie może już zobaczyć strony *create* lub *edit*, ale nadal może zobaczyć linki do nich. Te również powinniśmy ukryć. Jeden z takich linków znajduje się w szablonie `app/UI/Home/default.latte` i powinien być widoczny tylko dla zalogowanych użytkowników.
 
 Możemy go ukryć używając *n:atrybutu* w imieniu `n:if`. Jeśli ten warunek jest `false`, to cały znacznik `<a>`, łącznie z treścią, pozostanie ukryty.
 
@@ -131,7 +131,7 @@ co jest skrótem następującej notacji (nie mylić z `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Vytvořit příspěvek</a>{/if}
 ```
 
-W ten sam sposób ukrywamy link w szablonie `app/Presenters/templates/Post/show.latte`.
+W ten sam sposób ukrywamy link w szablonie `app/UI/Post/show.latte`.
 
 
 Link do logowania .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Link do logowania .[#toc-login-form-link]
 
 Jak właściwie dostać się na stronę logowania? Nie ma żadnego linku, który by do niego prowadził. Dodajmy więc go do szablonu `@layout.latte`. Spróbujcie znaleźć odpowiednie miejsce - może to być niemal każde.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Články</a></li>
@@ -156,7 +156,7 @@ Jeśli użytkownik nie jest zalogowany, pojawi się link "Zaloguj się". W przec
 
 Ponieważ przekierowujemy użytkownika od razu po wylogowaniu, nie jest potrzebny żaden szablon. Wylogowanie wygląda tak:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/pl/comments.texy b/quickstart/pl/comments.texy
index 2845f36f24..06f203d8fe 100644
--- a/quickstart/pl/comments.texy
+++ b/quickstart/pl/comments.texy
@@ -44,7 +44,7 @@ Najpierw musimy stworzyć formularz, który pozwoli użytkownikom komentować po
 
 Nette Framework wykorzystuje pojęcie *komponentu*. **Komponent** to klasa wielokrotnego użytku lub fragment kodu, który można dołączyć do innego komponentu. Nawet prezenter jest składnikiem. Każdy komponent jest tworzony poprzez fabrykę. Stwórzmy więc fabrykę dla formularza komentarza w prezenterze `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // czyli Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Wyjaśnijmy to jeszcze raz trochę. Pierwsza linia tworzy nową instancję kompo
 
 Jeśli formularz jest już zdefiniowany w prezenterze, możemy go renderować (wyświetlać) w szablonie. Zrobimy to, umieszczając znacznik `{control}` na końcu szablonu renderującego jeden konkretny post, w `Post/show.latte`. Ponieważ komponent nazywa się `commentForm` (nazwa pochodzi od nazwy metody `createComponentCommentForm`), znacznik będzie wyglądał tak:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Vložte nový příspěvek</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Poprzedni zapis oznacza "po udanym przesłaniu formularza wywołaj metodę `commentFormSucceeded` z bieżącego prezentera". Jednak ta metoda jeszcze nie istnieje. Więc stwórzmy go:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Ta nowa metoda przyjmuje jeden argument, którym jest instancja formularza, któ
 
 Są jeszcze dwie metody, które zasługują na wyjaśnienie. Metoda Redirect dosłownie przekierowuje z powrotem na bieżącą stronę. Jest to przydatne do zrobienia po każdym przesłaniu formularza, o ile zawierał on prawidłowe dane, a callback wykonał operację tak, jak powinien. Ponadto, jeśli przekierujemy stronę po przesłaniu formularza, nie zobaczymy znanego komunikatu `Chcete odeslat data z formuláře znovu?`, który czasem widzimy w przeglądarce. (Ogólnie rzecz biorąc, po przesłaniu formularza metodą `POST` zawsze powinno nastąpić przekierowanie do akcji `GET` ).
 
-Metoda `flashMessage` służy do informowania użytkownika o wyniku jakiejś operacji. Ponieważ przekierowujemy, wiadomość nie może być po prostu przekazana do szablonu i wyrenderowana. Dlatego istnieje ta metoda, która zapisuje wiadomość i udostępnia ją przy następnym załadowaniu strony. Komunikaty flash są renderowane w głównym szablonie `app/Presenters/templates/@layout.latte` i wygląda to tak:
+Metoda `flashMessage` służy do informowania użytkownika o wyniku jakiejś operacji. Ponieważ przekierowujemy, wiadomość nie może być po prostu przekazana do szablonu i wyrenderowana. Dlatego istnieje ta metoda, która zapisuje wiadomość i udostępnia ją przy następnym załadowaniu strony. Komunikaty flash są renderowane w głównym szablonie `app/UI/@layout.latte` i wygląda to tak:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer wykorzystuje klucze obce do rozwiązywania relacji międ
 
 Jak pamiętasz, przekazaliśmy zmienną `$post` do szablonu za pomocą metody `PostPresenter::renderShow()`, a teraz chcemy iterować po wszystkich komentarzach, które mają wartość kolumny `post_id` pasującą do `$post->id`. Możemy to zrobić, wywołując `$post->related('comments')`. Tak, to takie proste. Przyjrzyjmy się wynikowemu kodowi:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 I szablon:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Komentáře</h2>
 
diff --git a/quickstart/pl/creating-posts.texy b/quickstart/pl/creating-posts.texy
index c5240e5efb..71cdab992e 100644
--- a/quickstart/pl/creating-posts.texy
+++ b/quickstart/pl/creating-posts.texy
@@ -20,11 +20,11 @@ Później dodamy również logowanie i pozwolimy tylko zalogowanym użytkownikom
 Nowy prezenter .[#toc-new-presenter]
 ====================================
 
-Nowy prezenter będzie się nazywał `EditPresenter` i będzie przechowywany w `app/Presenters/EditPresenter.php`. Musi również połączyć się z bazą danych, więc ponownie napiszemy tutaj konstruktor, który będzie wymagał połączenia z bazą danych:
+Nowy prezenter będzie się nazywał `EditPresenter` i będzie przechowywany w `app/UI/Edit/`. Musi również połączyć się z bazą danych, więc ponownie napiszemy tutaj konstruktor, który będzie wymagał połączenia z bazą danych:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Formy i komponenty wyjaśniliśmy już przy okazji tworzenia komentarzy. Jeśli
 
 Teraz dodajmy tę metodę do prezentera `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Zapisywanie nowego postu z poziomu formularza .[#toc-saving-new-post-from-form]
 
 Dalej dodajemy metodę, która przetwarza dane z formularza:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Strona do tworzenia nowego postu .[#toc-page-for-creating-a-new-post]
 
 Utwórzmy teraz szablon `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>Nový příspěvek</h1>
 
@@ -105,7 +105,7 @@ Link do tworzenia postów .[#toc-link-for-creating-posts]
 
 Zapewne już wiesz jak dodać link do strony `EditPresenter` i jej akcji `create`. Wypróbuj to.
 
-Wystarczy dodać `app/Presenters/templates/Home/default.latte` do pliku:
+Wystarczy dodać `app/UI/Home/default.latte` do pliku:
 
 ```latte
 <a n:href="Edit:create">Napsat nový příspěvek</a>
@@ -119,12 +119,12 @@ Teraz dodamy również możliwość edycji postu. To będzie bardzo proste. Mamy
 
 Dodamy nową stronę `edit` do prezentera `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 I utwórz kolejny szablon `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Upravit příspěvek</h1>
 
@@ -146,15 +146,15 @@ I utwórz kolejny szablon `Edit/edit.latte`:
 
 I zmodyfikuj metodę `postFormSucceeded`, aby można było zarówno dodać nowy artykuł (tak jak teraz), jak i edytować istniejący:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Jeśli parametr `postId` jest dostępny , oznacza to, że będziemy edytować post. W takim przypadku sprawdzimy, czy żądany post naprawdę istnieje, a jeśli tak, zaktualizuj go w bazie danych. Jeśli parametr `postId` nie jest dostępny, oznacza to, że należy dodać nowy post.
+Jeśli parametr `id` jest dostępny , oznacza to, że będziemy edytować post. W takim przypadku sprawdzimy, czy żądany post naprawdę istnieje, a jeśli tak, zaktualizuj go w bazie danych. Jeśli parametr `id` nie jest dostępny, oznacza to, że należy dodać nowy post.
 
-Skąd jednak bierze się parametr `postId`? Jest to parametr, który został wstawiony do metody `renderEdit`.
+Skąd jednak bierze się parametr `id`? Jest to parametr, który został wstawiony do metody `renderEdit`.
 
-Teraz możemy dodać link do szablonu `app/Presenters/templates/Post/show.latte`:
+Teraz możemy dodać link do szablonu `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Upravit příspěvek</a>
diff --git a/quickstart/pl/home-page.texy b/quickstart/pl/home-page.texy
index 205ecb59d6..b43021ee74 100644
--- a/quickstart/pl/home-page.texy
+++ b/quickstart/pl/home-page.texy
@@ -66,9 +66,9 @@ Podłączenie do bazy danych .[#toc-connecting-to-the-database]
 
 Teraz, gdy baza danych jest utworzona i mamy kilka artykułów w niej zapisanych, to dobry moment, aby wyświetlić je na naszej pięknej, nowej stronie.
 
-Najpierw musimy powiedzieć aplikacji, z jakiej bazy danych ma korzystać. Konfigurujemy połączenie z bazą danych w pliku `config/local.neon` używając DSN((Data Source Name)) i poświadczeń logowania. Powinno to wyglądać coś takiego:
+Najpierw musimy powiedzieć aplikacji, z jakiej bazy danych ma korzystać. Konfigurujemy połączenie z bazą danych w pliku `config/common.neon` używając DSN((Data Source Name)) i poświadczeń logowania. Powinno to wyglądać coś takiego:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *zde vložte jméno uživatele*
@@ -78,20 +78,17 @@ database:
 .[note]
 Podczas edycji tego pliku zwróć uwagę na wcięcie linii. Format [NEON |neon:format] akceptuje zarówno wcięcie spacji, jak i wcięcie tabulatora, ale nie oba jednocześnie. Domyślny plik konfiguracyjny w Web Project wykorzystuje zakładki.
 
-Cała konfiguracja, w tym konfiguracja bazy danych, jest przechowywana w katalogu `/config/` w plikach `common.neon` i `local.neon`. Plik `common.neon` zawiera globalne ustawienia aplikacji, a plik `local.neon` zawiera tylko te parametry, które są specyficzne dla bieżącego środowiska (różnica między serwerami deweloperskimi i produkcyjnymi, itp.)
-
 
 Przekazanie połączenia z bazą danych .[#toc-injecting-the-database-connection]
 ==============================================================================
 
 Prezenter `HomePresenter`, który będzie obsługiwał zestawienie artykułów, potrzebuje połączenia z bazą danych. Aby go uzyskać, użyjemy konstruktora, który wygląda tak:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ final class HomePresenter extends Nette\Application\UI\Presenter
 
 Teraz ładujemy posty z bazy danych i wysyłamy je do szablonu, który następnie renderuje je jako kod HTML. Do tego właśnie służy tzw. metoda *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Presenter zawiera teraz jedną metodę render `renderDefault()`, która przekazuje dane z bazy danych do szablonu (View). Szablony znajdują się w `app/Presenters/templates/{PresenterName}/{viewName}.latte`, więc w tym przypadku szablon znajduje się w `app/Presenters/templates/Home/default.latte`. Szablon będzie miał teraz zmienną `$posts`, która zawiera posty pobrane z bazy danych.
+Presenter zawiera teraz jedną metodę render `renderDefault()`, która przekazuje dane z bazy danych do szablonu (View). Szablony znajdują się w `app/UI/{PresenterName}/{viewName}.latte`, więc w tym przypadku szablon znajduje się w `app/UI/Home/default.latte`. Szablon będzie miał teraz zmienną `$posts`, która zawiera posty pobrane z bazy danych.
 
 
 Szablon .[#toc-template]
@@ -128,9 +125,9 @@ Szablon .[#toc-template]
 
 Dla całej strony mamy szablon główny (który nazywa się *layout*, zawiera nagłówek, style, stopkę,...) oraz specyficzne szablony dla każdego widoku (View) (np. do wyświetlania postów na blogu), które mogą nadpisywać niektóre części szablonu głównego.
 
-Domyślnie szablon układu znajduje się w `app/Presenters/templates/@layout.latte` i zawiera:
+Domyślnie szablon układu znajduje się w `app/UI/@layout.latte` i zawiera:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Domyślnie szablon układu znajduje się w `app/Presenters/templates/@layout.lat
 
 Wpis `{include content}` wstawia do głównego szablonu blok o nazwie `content`. zdefiniujemy to w poszczególnych szablonach widoku (View). W naszym przypadku zmodyfikujemy plik `Home/default.latte` w następujący sposób:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ W ten sposób zdefiniowaliśmy [blok |latte:tags#block] *content*, który zostan
 
 Wyświetlmy wpisy na blogu - zmodyfikujmy szablon w następujący sposób:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>Můj blog</h1>
 
@@ -166,7 +163,7 @@ Wyświetlmy wpisy na blogu - zmodyfikujmy szablon w następujący sposób:
 
 Jeśli odświeżymy przeglądarkę, zobaczymy zestawienie wszystkich postów. Listing nie jest jeszcze zbyt ładny, nawet nie jest kolorowy, więc możemy dodać kilka [stylów CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] do pliku `www/css/style.css` i połączyć go w układzie:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Wpis `|date:` nazywamy filtrem. Filtry mają za zadanie sformatować dane wyjśc
 
 Jeszcze jedna rzecz. Możemy skrócić i uprościć poprzedni kod. Możemy to zrobić zastępując znaczniki *Latte* przez *n:attributes*:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>Můj blog</h1>
 
diff --git a/quickstart/pl/model.texy b/quickstart/pl/model.texy
index 8a5b786b04..0eeca48622 100644
--- a/quickstart/pl/model.texy
+++ b/quickstart/pl/model.texy
@@ -36,9 +36,9 @@ W klasie będziemy mieli konstruktor przekazujący eksplorator bazy danych:[api:
 
 Przechodzimy na stronę `HomePresenter`, którą modyfikujemy pozbywając się zależności od `Nette\Database\Explorer` i zastępując ją zależnością od naszej nowej klasy.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/pl/single-post.texy b/quickstart/pl/single-post.texy
index f02f3543c9..d4f35d231c 100644
--- a/quickstart/pl/single-post.texy
+++ b/quickstart/pl/single-post.texy
@@ -5,13 +5,13 @@ Strona z wkładem
 Teraz stwórzmy kolejną stronę bloga, która będzie wyświetlała jeden konkretny post.
 
 
-Musimy stworzyć nową metodę renderującą, która pobiera jeden konkretny artykuł i przekazuje go do szablonu. Posiadanie tej metody w `HomePresenter` nie jest zbyt miłe, ponieważ mówimy o artykule, a nie o stronie głównej. Stwórzmy więc `PostPresenter` w `app/Presenters`. Ten prezenter również musi połączyć się z bazą danych, więc tutaj znowu napiszemy konstruktor, który będzie wymagał połączenia z bazą danych.
+Musimy stworzyć nową metodę renderującą, która pobiera jeden konkretny artykuł i przekazuje go do szablonu. Posiadanie tej metody w `HomePresenter` nie jest zbyt miłe, ponieważ mówimy o artykule, a nie o stronie głównej. Stwórzmy więc `PostPresenter` w `app/UI/Post/`. Ten prezenter również musi połączyć się z bazą danych, więc tutaj znowu napiszemy konstruktor, który będzie wymagał połączenia z bazą danych.
 
 `PostPresenter` Mogłoby to wtedy wyglądać tak:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Nie zapomnij uwzględnić prawidłowej przestrzeni nazw `App\Presenters`, która podlega ustawieniom [mapowania prezentera |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Nie zapomnij uwzględnić prawidłowej przestrzeni nazw `App\UI\Post`, która podlega ustawieniom [mapowania prezentera |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Metoda `renderShow` wymaga jednego argumentu - ID jednego konkretnego artykułu, który ma być wyświetlony. Następnie pobiera ten artykuł z bazy danych i przekazuje go do szablonu.
 
 W szablonie `Home/default.latte` wstawiamy link do akcji `Post:show`.
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Znacznik `{link}` generuje adres URL, który wskazuje na akcję `Post:show`. Prz
 
 To samo można napisać w skrócie, używając atrybutu n::
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Nie ma jednak jeszcze szablonu dla akcji `Post:show`. Możemy spróbować otworz
 
 Stwórzmy więc szablon `Post/show.latte` z tą treścią:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← zpět na výpis příspěvků</a></p>
@@ -89,7 +89,7 @@ Czwarta linia wyświetla *tytuł* wpisu na blogu w znaczniku HTML `<h1>`. Ten zn
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Po prostu ten blok predefiniuje blok o nazwie `title`. Blok ten jest już zdefiniowany w głównym szablonie *layout* (`/app/Presenters/templates/@layout.latte:11`) i podobnie jak w przypadku nakładek na metody w OOP, nakłada ten blok w szablonie głównym w dokładnie taki sam sposób. Więc `<title>` strona zawiera teraz nagłówek wyświetlanego postu, a wszystko co musieliśmy zrobić to użyć jednego prostego atrybutu `n:block="title"`. Świetnie, prawda?
+Po prostu ten blok predefiniuje blok o nazwie `title`. Blok ten jest już zdefiniowany w głównym szablonie *layout* (`/app/UI/@layout.latte:11`) i podobnie jak w przypadku nakładek na metody w OOP, nakłada ten blok w szablonie głównym w dokładnie taki sam sposób. Więc `<title>` strona zawiera teraz nagłówek wyświetlanego postu, a wszystko co musieliśmy zrobić to użyć jednego prostego atrybutu `n:block="title"`. Świetnie, prawda?
 
 Piąta i ostatnia linia szablonu wyświetla całą zawartość jednego konkretnego postu.
 
@@ -97,14 +97,14 @@ Piąta i ostatnia linia szablonu wyświetla całą zawartość jednego konkretne
 Sprawdź identyfikator postu .[#toc-checking-post-id]
 ====================================================
 
-Co się stanie jeśli ktoś zmieni ID w URL i umieści jakiś nieistniejący `postId`? Powinniśmy zaoferować użytkownikowi ładny błąd "page not found". Zmodyfikujmy więc nieco metodę render w `PostPresenter`:
+Co się stanie jeśli ktoś zmieni ID w URL i umieści jakiś nieistniejący `id`? Powinniśmy zaoferować użytkownikowi ładny błąd "page not found". Zmodyfikujmy więc nieco metodę render w `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Stránka nebyla nalezena');
 	}
diff --git a/quickstart/pt/@home.texy b/quickstart/pt/@home.texy
index 95cf8a86d9..5a097ade02 100644
--- a/quickstart/pt/@home.texy
+++ b/quickstart/pt/@home.texy
@@ -7,7 +7,7 @@ Conheça o Nette Framework enquanto cria um blog simples com comentários. Vamos
 Após os dois primeiros capítulos, você terá seu próprio blog de trabalho e estará pronto para publicar seus incríveis posts, embora as características sejam bastante limitadas após completar estes dois capítulos. Para tornar as coisas mais agradáveis para seus usuários, você também deve ler os capítulos seguintes e continuar melhorando sua aplicação.
 
 .[tip]
-Este tutorial pressupõe que você completou o documento de [instalação |nette:installation] e configurou com sucesso suas ferramentas.
+Este tutorial pressupõe que você tenha concluído o documento [de instalação |nette:installation] e configurado com êxito suas ferramentas. Ele também pressupõe que você entenda de [programação orientada a objetos em PHP |nette:introduction-to-object-oriented-programming].
 
 Por favor, use PHP 8.1 ou posterior. Você pode encontrar a aplicação completa [no GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ O Projeto Web tem a seguinte estrutura:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← classes básicas necessárias
+│   ├── <b>UI/</b>           ← apresentadores, modelos e outros.
+│   │   └── <b>Home/</b>     ← Home presenter directory
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ O diretório mais importante para você é `app/`. Lá você pode encontrar o ar
 Limpeza .[#toc-cleanup]
 =======================
 
-O Projeto Web contém uma página de boas-vindas, que podemos remover - sinta-se à vontade para excluir o arquivo `app/Presenters/templates/Home/default.latte` e substituí-lo pelo texto "Olá mundo!
+O Projeto Web contém uma página de boas-vindas, que podemos remover - sinta-se à vontade para excluir o arquivo `app/UI/Home/default.latte` e substituí-lo pelo texto "Olá mundo!
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ O Projeto Web contém uma página de boas-vindas, que podemos remover - sinta-se
 Tracy (Depurador) .[#toc-tracy-debugger]
 ========================================
 
-Uma ferramenta extremamente importante para o desenvolvimento é [uma depuradora chamada Tracy |tracy:]. Tente cometer alguns erros em seu arquivo `app/Presenters/HomePresenter.php` (por exemplo, remova um colchete da definição da classe HomePresenter) e veja o que acontece. Uma página na tela vermelha irá aparecer com uma descrição compreensível do erro.
+Uma ferramenta extremamente importante para o desenvolvimento é [uma depuradora chamada Tracy |tracy:]. Tente cometer alguns erros em seu arquivo `app/UI/Home/HomePresenter.php` (por exemplo, remova um colchete da definição da classe HomePresenter) e veja o que acontece. Uma página na tela vermelha irá aparecer com uma descrição compreensível do erro.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy o ajudará significativamente durante a caça aos erros. Observe também a barra flutuante Tracy no canto inferior direito, que o informa sobre dados importantes de tempo de execução.
 
@@ -88,8 +88,7 @@ No modo de produção, Tracy está, naturalmente, desativada e não revela nenhu
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/pt/authentication.texy b/quickstart/pt/authentication.texy
index 5e936f7f38..3860058b5b 100644
--- a/quickstart/pt/authentication.texy
+++ b/quickstart/pt/authentication.texy
@@ -28,9 +28,9 @@ Agora temos a parte back-end da autenticação pronta e precisamos fornecer uma
 
 Vamos começar com o formulário de login. Você já sabe como funcionam os formulários em um apresentador. Crie o `SignPresenter` e o método `createComponentSignInForm`. Deve ser parecido com isto:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Modelo .[#toc-template]
 
 O formulário será apresentado no modelo `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Acrescentamos também um *agitador de formulário* para assinar no usuário, que
 
 O manipulador pegará apenas o nome de usuário e a senha que o usuário digitou e a passará para o autenticador definido anteriormente. Após o login do usuário, nós o redirecionaremos para a página inicial.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Iremos assegurar um formulário para adicionar e editar postos. Ele está defini
 
 Criamos um método `startup()` que é iniciado imediatamente no início do [ciclo de vida do apresentador |application:presenters#life-cycle-of-presenter]. Isto redireciona os usuários não-logados para o formulário de login.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Ocultar Links .[#toc-hide-links]
 --------------------------------
 
-Um usuário não autenticado não pode mais ver a página *criar* nem *editar*, mas ele ainda pode ver os links que apontam para eles. Vamos escondê-los também. Um desses links está em `app/Presenters/templates/Home/default.latte`, e deve ser visível somente se o usuário estiver logado.
+Um usuário não autenticado não pode mais ver a página *criar* nem *editar*, mas ele ainda pode ver os links que apontam para eles. Vamos escondê-los também. Um desses links está em `app/UI/Home/default.latte`, e deve ser visível somente se o usuário estiver logado.
 
 Podemos escondê-lo usando *n:attribute* chamado `n:if`. Se a declaração dentro dele for `false`, o todo `<a>` e o seu conteúdo não será exibido:
 
@@ -131,7 +131,7 @@ este é um atalho para (não confundir com `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Você deve ocultar o link de edição localizado em `app/Presenters/templates/Post/show.latte` de maneira semelhante.
+Você deve ocultar o link de edição localizado em `app/UI/Post/show.latte` de maneira semelhante.
 
 
 Link para o Formulário de Login .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Link para o Formulário de Login .[#toc-login-form-link]
 
 Mas como chegamos à página de login? Não há nenhum link que aponte para ela. Vamos adicionar um no arquivo modelo `@layout.latte`. Tente encontrar um lugar agradável, pode ser em qualquer lugar que você mais goste.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Se o usuário ainda não estiver logado, mostraremos o link "Entrar". Caso contr
 
 A ação de logout parece assim, e como redirecionamos o usuário imediatamente, não há necessidade de um modelo de visualização.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/pt/comments.texy b/quickstart/pt/comments.texy
index bdd311b926..127573bc63 100644
--- a/quickstart/pt/comments.texy
+++ b/quickstart/pt/comments.texy
@@ -44,7 +44,7 @@ Primeiro, precisamos criar um formulário, que permitirá aos usuários comentar
 
 Nette Framework tem um conceito de *componentes*. Um **componente*** é uma classe ou código reutilizável, que pode ser anexado a outro componente. Até mesmo um apresentador é um componente. Cada componente é criado usando a fábrica de componentes. Portanto, vamos definir os comentários da fábrica em `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // means Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Vamos explicar um pouco. A primeira linha cria uma nova instância do componente
 
 Uma vez que o componente do formulário é definido em um apresentador, podemos renderizá-lo (exibir) em um modelo. Para isso, coloque a tag `{control}` no final do modelo de detalhe do post, em `Post/show.latte`. Como o nome do componente é `commentForm` (é derivado do nome do método `createComponentCommentForm`), a tag terá o seguinte aspecto
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Significa "depois que o formulário for enviado com sucesso, ligue para o método `commentFormSucceeded` do atual apresentador". Este método ainda não existe, portanto, vamos criá-lo.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ O novo método tem um argumento que é a instância do formulário que está sen
 
 Há mais duas chamadas de método para explicar. O redirecionamento é literalmente redirecionado para a página atual. Você deve fazer isso toda vez que o formulário for apresentado, válido, e a operação de retorno da chamada fez o que deveria ter feito. Além disso, quando você redireciona a página após enviar o formulário, você não verá a conhecida mensagem `Would you like to submit the post data again?` que às vezes você pode ver no navegador. (Em geral, após submeter um formulário pelo método `POST`, você deve sempre redirecionar o usuário para uma ação `GET` ).
 
-O `flashMessage` é para informar o usuário sobre o resultado de alguma operação. Como estamos redirecionando, a mensagem não pode ser passada diretamente para o modelo e entregue. Portanto, existe este método, que irá armazená-lo e torná-lo disponível no carregamento da próxima página. As mensagens flash são renderizadas no arquivo padrão `app/Presenters/templates/@layout.latte`, e é assim que parece:
+O `flashMessage` é para informar o usuário sobre o resultado de alguma operação. Como estamos redirecionando, a mensagem não pode ser passada diretamente para o modelo e entregue. Portanto, existe este método, que irá armazená-lo e torná-lo disponível no carregamento da próxima página. As mensagens flash são renderizadas no arquivo padrão `app/UI/@layout.latte`, e é assim que parece:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ O Nette Database Explorer utiliza as chaves estrangeiras para resolver as relaç
 
 Como você deve se lembrar, passamos a variável `$post` para o modelo em `PostPresenter::renderShow()` e agora queremos iterar através de todos os comentários que têm a coluna `post_id` igual ao nosso `$post->id`. Você pode fazer isso ligando para `$post->related('comments')`. É muito simples. Veja o código resultante.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 E o modelo:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/pt/creating-posts.texy b/quickstart/pt/creating-posts.texy
index 674ea61299..2034dcd60b 100644
--- a/quickstart/pt/creating-posts.texy
+++ b/quickstart/pt/creating-posts.texy
@@ -20,11 +20,11 @@ Mais tarde também adicionaremos autenticação e permitiremos apenas usuários
 Novo apresentador .[#toc-new-presenter]
 =======================================
 
-Nomeie o novo apresentador `EditPresenter` e salve-o em `app/Presenters/EditPresenter.php`. Ele também precisa se conectar ao banco de dados, então aqui novamente escrevemos um construtor que exigirá uma conexão com o banco de dados:
+Nomeie o novo apresentador `EditPresenter` e salve-o em `app/UI/Edit/`. Ele também precisa se conectar ao banco de dados, então aqui novamente escrevemos um construtor que exigirá uma conexão com o banco de dados:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Formulários e componentes já foram cobertos quando estávamos adicionando apoi
 
 Agora adicione este método ao `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Salvando novos postos do formulário .[#toc-saving-new-post-from-form]
 
 Continue adicionando um método de manipulador.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Página para criar um novo posto .[#toc-page-for-creating-a-new-post]
 
 Vamos apenas criar o modelo `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Link para a criação de postos .[#toc-link-for-creating-posts]
 
 Você provavelmente já sabe como adicionar um link para `EditPresenter` e sua ação `create`. Experimente-o.
 
-Basta adicionar ao arquivo `app/Presenters/templates/Home/default.latte`:
+Basta adicionar ao arquivo `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Vamos também acrescentar a capacidade de editar os postos existentes. Será mui
 
 Vamos adicionar uma nova página `edit` ao `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 E crie o modelo `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ E crie o modelo `Edit/edit.latte`:
 
 E atualizar o método `postFormSucceeded`, que poderá ou adicionar um novo post (como faz agora), ou editar os já existentes:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Quando o parâmetro `postId` é fornecido, isso significa que um post está sendo editado. Nesse caso, verificaremos se o post realmente existe e, se for o caso, atualizá-lo-emos no banco de dados. Se o parâmetro `postId` não for fornecido, significa que um novo post será adicionado.
+Quando o parâmetro `id` é fornecido, isso significa que um post está sendo editado. Nesse caso, verificaremos se o post realmente existe e, se for o caso, atualizá-lo-emos no banco de dados. Se o parâmetro `id` não for fornecido, significa que um novo post será adicionado.
 
-Mas de onde vem o `postId`? É o parâmetro passado para o método `renderEdit`.
+Mas de onde vem o `id`? É o parâmetro passado para o método `renderEdit`.
 
-Agora você pode adicionar um link para o modelo `app/Presenters/templates/Post/show.latte`:
+Agora você pode adicionar um link para o modelo `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/pt/home-page.texy b/quickstart/pt/home-page.texy
index 9d93cca03f..e79d079686 100644
--- a/quickstart/pt/home-page.texy
+++ b/quickstart/pt/home-page.texy
@@ -66,9 +66,9 @@ Conexão com o banco de dados .[#toc-connecting-to-the-database]
 
 Agora, quando o banco de dados é criado e temos alguns posts nele, é o momento certo para exibi-los em nossa nova página brilhante.
 
-Em primeiro lugar, precisamos informar nossa aplicação sobre qual banco de dados utilizar. A configuração da conexão do banco de dados é armazenada em `config/local.neon`. Defina a conexão DSN((Data Source Name)) e suas credenciais. Deve ter este aspecto:
+Em primeiro lugar, precisamos informar nossa aplicação sobre qual banco de dados utilizar. A configuração da conexão do banco de dados é armazenada em `config/common.neon`. Defina a conexão DSN((Data Source Name)) e suas credenciais. Deve ter este aspecto:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Esteja atento à indentação durante a edição deste arquivo. [O formato NEON |neon:format] aceita ambos os espaços e abas, mas não ambos juntos! O arquivo de configuração no Projeto Web utiliza abas como padrão.
 
-Toda a configuração inclusive é armazenada em `config/` nos arquivos `common.neon` e `local.neon`. O arquivo `common.neon` contém a configuração global da aplicação e `local.neon` contém apenas os parâmetros específicos do ambiente (por exemplo, a diferença entre servidor de desenvolvimento e de produção).
-
 
 Injetando a conexão do banco de dados .[#toc-injecting-the-database-connection]
 ===============================================================================
 
 O apresentador `HomePresenter`, que listará os artigos, precisa de uma conexão de banco de dados. Para recebê-la, escreva um construtor como este:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Carregamento de postes a partir do banco de dados .[#toc-loading-posts-from-the-
 
 Agora vamos buscar os posts no banco de dados e passá-los para o template, que então renderizará o código HTML. É para isso que serve o chamado método *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-O apresentador agora tem um método de renderização `renderDefault()` que passa dados para uma visualização chamada `default`. Os modelos do apresentador podem ser encontrados em `app/Presenters/templates/{PresenterName}/{viewName}.latte`, então neste caso o modelo será localizado em `app/Presenters/templates/Home/default.latte`. No modelo, uma variável chamada `$posts` está agora disponível, que contém os posts do banco de dados.
+O apresentador agora tem um método de renderização `renderDefault()` que passa dados para uma visualização chamada `default`. Os modelos do apresentador podem ser encontrados em `app/UI/{PresenterName}/{viewName}.latte`, então neste caso o modelo será localizado em `app/UI/Home/default.latte`. No modelo, uma variável chamada `$posts` está agora disponível, que contém os posts do banco de dados.
 
 
 Modelo .[#toc-template]
@@ -128,9 +125,9 @@ Modelo .[#toc-template]
 
 Há um modelo genérico para toda a página (chamado *layout*, com cabeçalho, folhas de estilo, rodapé, ...) e depois modelos específicos para cada visualização (por exemplo, para exibir a lista de posts do blog), que podem substituir algumas das peças do modelo de layout.
 
-Por padrão, o modelo de layout está localizado em `templates/@layout.latte`, que contém:
+Por padrão, o modelo de layout está localizado em `app/UI/@layout.latte`, que contém:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Por padrão, o modelo de layout está localizado em `templates/@layout.latte`, q
 
 `{include content}` insere um bloco chamado `content` no modelo principal. Você pode defini-lo nos gabaritos de cada vista. Neste caso, editaremos o arquivo `Home/default.latte` desta forma:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Ele define o [bloco |latte:tags#block]*content*, que será inserido no layout. S
 
 Vamos exibir os posts do blog - editaremos o modelo desta forma:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Vamos exibir os posts do blog - editaremos o modelo desta forma:
 
 Se você atualizar seu navegador, você verá a lista de seus posts no blog. A lista não é muito chique ou colorida, portanto, sinta-se à vontade para adicionar algum [CSS brilhante |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a `www/css/style.css` e vinculá-lo em um layout:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ A coisa `|date` é chamada de filtro. Os filtros são usados para formatar a sa
 
 Mais uma coisa. Podemos tornar o código um pouco mais curto e, portanto, mais simples. Podemos substituir as *etiquetas* por *n:atributos* desta forma:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/pt/model.texy b/quickstart/pt/model.texy
index 2f010ab7e7..e56af4c292 100644
--- a/quickstart/pt/model.texy
+++ b/quickstart/pt/model.texy
@@ -36,9 +36,9 @@ Na classe passamos no Explorer do banco de dados:[api:Nette\Database\Explorer].
 
 Mudaremos para `HomePresenter` que editaremos para nos livrarmos da dependência em `Nette\Database\Explorer`, substituindo-a por uma nova dependência de nossa nova classe.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/pt/single-post.texy b/quickstart/pt/single-post.texy
index d991cfed1b..7ff70300fa 100644
--- a/quickstart/pt/single-post.texy
+++ b/quickstart/pt/single-post.texy
@@ -5,13 +5,13 @@ Página única de postagem
 Vamos adicionar outra página ao nosso blog, que exibirá o conteúdo de um determinado post do blog.
 
 
-Precisamos criar um novo método de renderização, que irá buscar um post específico no blog e passá-lo para o modelo. Ter esta visão em `HomePresenter` não é legal porque se trata de um post de blog, não da página inicial. Então, vamos criar uma nova classe `PostPresenter` e colocá-la em `app/Presenters`. Ela precisará de uma conexão de banco de dados, então coloque o código *injeção de banco de dados* lá novamente.
+Precisamos criar um novo método de renderização, que irá buscar um post específico no blog e passá-lo para o modelo. Ter esta visão em `HomePresenter` não é legal porque se trata de um post de blog, não da página inicial. Então, vamos criar uma nova classe `PostPresenter` e colocá-la em `app/UI/Post/`. Ela precisará de uma conexão de banco de dados, então coloque o código *injeção de banco de dados* lá novamente.
 
 O `PostPresenter` deve se parecer com isto:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Temos que definir um namespaces correto `App\Presenters` para nosso apresentador. Isso depende do [mapeamento do apresentador |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Temos que definir um namespaces correto `App\UI\Post` para nosso apresentador. Isso depende do [mapeamento do apresentador |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 O método `renderShow` requer um argumento - a identificação do posto a ser exibido. Em seguida, ele carrega o posto do banco de dados e passa o resultado para o modelo.
 
 No modelo `Home/default.latte`, adicionamos um link para a ação `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ A tag `{link}` gera um endereço URL que aponta para a ação `Post:show`. Esta
 
 O mesmo podemos escrever em breve usando n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ O modelo para a ação `Post:show` ainda não existe. Podemos abrir um link para
 
 Por isso, criaremos `Post/show.latte` com este conteúdo:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ A quarta linha exibe o *título* do post do blog como um `<h1>` título. Há uma
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Em palavras simples, ele *redefine* um bloco chamado `title`. O bloco é definido no modelo *layout* (`/app/Presenters/templates/@layout.latte:11`) e, como no OOP, ele é anulado aqui. Portanto, a página é `<title>` conterá o título do post exibido. Anulamos o título da página e tudo o que precisávamos era `n:block="title"`. Ótimo, não é?
+Em palavras simples, ele *redefine* um bloco chamado `title`. O bloco é definido no modelo *layout* (`/app/UI/@layout.latte:11`) e, como no OOP, ele é anulado aqui. Portanto, a página é `<title>` conterá o título do post exibido. Anulamos o título da página e tudo o que precisávamos era `n:block="title"`. Ótimo, não é?
 
 A quinta e última linha do modelo exibe o conteúdo completo do seu post.
 
@@ -97,14 +97,14 @@ A quinta e última linha do modelo exibe o conteúdo completo do seu post.
 Verificação da identificação do posto .[#toc-checking-post-id]
 ==============================================================
 
-O que acontece se alguém altera a URL e insere `postId` que não existe? Devemos fornecer ao usuário um bom erro de "página não encontrada". Vamos atualizar o método de renderização em `PostPresenter`:
+O que acontece se alguém altera a URL e insere `id` que não existe? Devemos fornecer ao usuário um bom erro de "página não encontrada". Vamos atualizar o método de renderização em `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/ro/@home.texy b/quickstart/ro/@home.texy
index 35b39ebbdc..d8df6d0988 100644
--- a/quickstart/ro/@home.texy
+++ b/quickstart/ro/@home.texy
@@ -7,7 +7,7 @@ Faceți cunoștință cu Nette Framework în timp ce creați un blog simplu cu c
 După primele două capitole, veți avea propriul blog funcțional și veți fi gata să vă publicați postările minunate, deși funcțiile vor fi destul de limitate după finalizarea acestor două capitole. Pentru ca lucrurile să fie mai frumoase pentru utilizatori, ar trebui să citiți și următoarele capitole și să continuați să vă îmbunătățiți aplicația.
 
 .[tip]
-Acest tutorial pornește de la premisa că ați finalizat documentul de [instalare |nette:installation] și că ați configurat cu succes uneltele.
+Acest tutorial pornește de la premisa că ați finalizat documentul de [instalare |nette:installation] și că ați configurat cu succes uneltele. De asemenea, se presupune că înțelegeți [programarea orientată pe obiecte în PHP |nette:introduction-to-object-oriented-programming].
 
 Vă rugăm să utilizați PHP 8.1 sau o versiune ulterioară. Puteți găsi aplicația completă [pe GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Proiectul Web are următoarea structură:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← cursuri de bază necesare
+│   ├── <b>UI/</b>           ← prezentări, șabloane & co.
+│   │   └── <b>Home/</b>     ← Directorul prezentatorilor de acasă
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ Cel mai important director pentru dumneavoastră este `app/`. Acolo găsiți fi
 Curățați .[#toc-cleanup]
 ========================
 
-Proiectul Web conține o pagină de bun venit, pe care o putem elimina - nu ezitați să ștergeți fișierul `app/Presenters/templates/Home/default.latte` și să îl înlocuiți cu textul "Hello world!".
+Proiectul Web conține o pagină de bun venit, pe care o putem elimina - nu ezitați să ștergeți fișierul `app/UI/Home/default.latte` și să îl înlocuiți cu textul "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Proiectul Web conține o pagină de bun venit, pe care o putem elimina - nu ezit
 Tracy (Depanator) .[#toc-tracy-debugger]
 ========================================
 
-Un instrument extrem de important pentru dezvoltare este [un depanator numit Tracy |tracy:]. Încercați să faceți câteva erori în fișierul `app/Presenters/HomePresenter.php` (de exemplu, eliminați o paranteză curly bracket din definiția clasei HomePresenter) și vedeți ce se întâmplă. Va apărea o pagină pe ecran roșu cu o descriere inteligibilă a erorii.
+Un instrument extrem de important pentru dezvoltare este [un depanator numit Tracy |tracy:]. Încercați să faceți câteva erori în fișierul `app/UI/Home/HomePresenter.php` (de exemplu, eliminați o paranteză curly bracket din definiția clasei HomePresenter) și vedeți ce se întâmplă. Va apărea o pagină pe ecran roșu cu o descriere inteligibilă a erorii.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy vă va ajuta în mod semnificativ în timpul vânătorii de erori. Rețineți, de asemenea, bara Tracy plutitoare din colțul din dreapta jos, care vă informează cu privire la datele importante din timpul execuției.
 
@@ -88,8 +88,7 @@ Tracy vă va ajuta în mod semnificativ în timpul vânătorii de erori. Reține
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/ro/authentication.texy b/quickstart/ro/authentication.texy
index 4475c6dc3b..3718cf1dec 100644
--- a/quickstart/ro/authentication.texy
+++ b/quickstart/ro/authentication.texy
@@ -28,9 +28,9 @@ Acum avem gata partea de autentificare din backend și trebuie să furnizăm o i
 
 Să începem cu formularul de autentificare. Știți deja cum funcționează formularele într-un prezentator. Creați `SignPresenter` și metoda `createComponentSignInForm`. Ar trebui să arate astfel:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Există o intrare pentru numele de utilizator și parola.
 
 Formularul va fi redat în șablon `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Adăugăm, de asemenea, un *manager de formular* pentru autentificarea utilizato
 
 Manipulatorul va lua doar numele de utilizator și parola introduse de utilizator și le va transmite către autentificatorul definit anterior. După ce utilizatorul s-a logat, îl vom redirecționa către pagina de start.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Vom securiza un formular pentru adăugarea și editarea mesajelor. Acesta este d
 
 Creăm o metodă `startup()` care este lansată imediat la începutul [ciclului de viață al prezentatorului |application:presenters#life-cycle-of-presenter]. Aceasta redirecționează utilizatorii care nu sunt autentificați către formularul de autentificare.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Ascundeți linkurile .[#toc-hide-links]
 --------------------------------------
 
-Un utilizator neautentificat nu mai poate vedea nici pagina *create*, nici pagina *edit*, dar poate vedea în continuare legăturile care indică spre ele. Haideți să le ascundem și pe acestea. Un astfel de link se află în `app/Presenters/templates/Home/default.latte`, și ar trebui să fie vizibil numai dacă utilizatorul este autentificat.
+Un utilizator neautentificat nu mai poate vedea nici pagina *create*, nici pagina *edit*, dar poate vedea în continuare legăturile care indică spre ele. Haideți să le ascundem și pe acestea. Un astfel de link se află în `app/UI/Home/default.latte`, și ar trebui să fie vizibil numai dacă utilizatorul este autentificat.
 
 Îl putem ascunde folosind *n:atribut* numit `n:if`. Dacă afirmația din interiorul acestuia este `false`, întregul `<a>` tag și conținutul său nu vor fi afișate:
 
@@ -131,7 +131,7 @@ aceasta este o prescurtare pentru (nu o confundați cu `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Ar trebui să ascundeți linkul de editare aflat în `app/Presenters/templates/Post/show.latte` într-un mod similar.
+Ar trebui să ascundeți linkul de editare aflat în `app/UI/Post/show.latte` într-un mod similar.
 
 
 Legătura formularului de autentificare .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Legătura formularului de autentificare .[#toc-login-form-link]
 
 Hei, dar cum ajungem la pagina de autentificare? Nu există nici un link care să arate spre ea. Să adăugăm unul în fișierul șablon `@layout.latte`. Încercați să găsiți un loc frumos, poate fi oriunde vă place cel mai mult.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Dacă utilizatorul nu este încă logat, vom afișa link-ul "Sign in". În caz c
 
 Acțiunea de deconectare arată astfel și, deoarece redirecționăm utilizatorul imediat, nu este nevoie de un șablon de vizualizare.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/ro/comments.texy b/quickstart/ro/comments.texy
index fc25a4dfe7..554524a9d2 100644
--- a/quickstart/ro/comments.texy
+++ b/quickstart/ro/comments.texy
@@ -44,7 +44,7 @@ Formular pentru comentarii .[#toc-form-for-commenting]
 
 Nette Framework are un concept de *componente*. Un **component** este o clasă sau o bucată de cod reutilizabilă, care poate fi atașată unei alte componente. Chiar și un prezentator este o componentă. Fiecare componentă este creată cu ajutorul fabricii de componente. Deci, să definim fabrica de formulare de comentarii în `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // înseamnă Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Să o explicăm puțin. Prima linie creează o nouă instanță a componentei `F
 
 Odată ce componenta de formular este definită într-un prezentator, o putem reda (afișa) într-un șablon. Pentru a face acest lucru, plasați eticheta `{control}` la sfârșitul șablonului de detaliu al postării, în `Post/show.latte`. Deoarece numele componentei este `commentForm` (este derivat din numele metodei `createComponentCommentForm`), eticheta va arăta astfel
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Aceasta înseamnă "după ce formularul este trimis cu succes, apelați metoda `commentFormSucceeded` a prezentatorului curent". Această metodă nu există încă, așa că haideți să o creăm.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Metoda new are un singur argument, care este instanța formularului care se trim
 
 Mai sunt două apeluri de metode care trebuie explicate. Redirecționarea redirecționează literalmente către pagina curentă. Ar trebui să faceți acest lucru de fiecare dată când formularul este trimis, este valid și operațiunea de rechemare a făcut ceea ce trebuia să facă. De asemenea, atunci când redirecționați pagina după trimiterea formularului, nu veți vedea binecunoscutul mesaj `Would you like to submit the post data again?` pe care îl puteți vedea uneori în browser. (În general, după trimiterea unui formular prin metoda `POST`, ar trebui să redirecționați întotdeauna utilizatorul către o acțiune `GET` ).
 
- `flashMessage` are rolul de a informa utilizatorul despre rezultatul unei anumite operațiuni. Pentru că redirecționăm, mesajul nu poate fi trecut direct în șablon și redat. Așa că există această metodă, care îl va stoca și îl va face disponibil la următoarea încărcare a paginii. Mesajele flash sunt redate în fișierul implicit `app/Presenters/templates/@layout.latte` și arată astfel:
+ `flashMessage` are rolul de a informa utilizatorul despre rezultatul unei anumite operațiuni. Pentru că redirecționăm, mesajul nu poate fi trecut direct în șablon și redat. Așa că există această metodă, care îl va stoca și îl va face disponibil la următoarea încărcare a paginii. Mesajele flash sunt redate în fișierul implicit `app/UI/@layout.latte` și arată astfel:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer folosește cheile străine pentru a rezolva relațiile d
 
 După cum probabil vă amintiți, am trecut variabila `$post` în șablonul din `PostPresenter::renderShow()` și acum dorim să iterăm prin toate comentariile care au coloana `post_id` egală cu a noastră `$post->id`. Puteți face acest lucru apelând `$post->related('comments')`. Este atât de simplu. Priviți codul rezultat.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 Și șablonul:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/ro/creating-posts.texy b/quickstart/ro/creating-posts.texy
index 173842c595..b4276da862 100644
--- a/quickstart/ro/creating-posts.texy
+++ b/quickstart/ro/creating-posts.texy
@@ -20,11 +20,11 @@ Mai târziu vom adăuga și autentificarea și vom permite doar utilizatorilor a
 Noul prezentator .[#toc-new-presenter]
 ======================================
 
-Numiți noul prezentator `EditPresenter` și salvați-l în `app/Presenters/EditPresenter.php`. De asemenea, acesta trebuie să se conecteze la baza de date, așa că și aici vom scrie un constructor care va necesita o conexiune la baza de date:
+Numiți noul prezentator `EditPresenter` și salvați-l în `app/UI/Edit/`. De asemenea, acesta trebuie să se conecteze la baza de date, așa că și aici vom scrie un constructor care va necesita o conexiune la baza de date:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Formularele și componentele au fost deja abordate atunci când am adăugat supo
 
 Acum adăugați această metodă la `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Salvarea unei noi postări din formular .[#toc-saving-new-post-from-form]
 
 Continuați prin adăugarea unei metode de gestionare.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Pagina pentru crearea unei postări noi .[#toc-page-for-creating-a-new-post]
 
 Să creăm doar șablonul `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Legătură pentru crearea de mesaje .[#toc-link-for-creating-posts]
 
 Probabil că știți deja cum să adăugați un link la `EditPresenter` și la acțiunea sa `create`. Încercați-o.
 
-Trebuie doar să adăugați la fișierul `app/Presenters/templates/Home/default.latte`:
+Trebuie doar să adăugați la fișierul `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Să adăugăm, de asemenea, posibilitatea de a edita posturile existente. Va fi
 
 Vom adăuga o nouă pagină `edit` la `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 Și vom crea șablonul `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ public function renderEdit(int $postId): void
 
 Și actualizați metoda `postFormSucceeded`, care va putea fie să adauge o nouă postare (așa cum se întâmplă acum), fie să le editeze pe cele existente:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Atunci când este furnizat parametrul `postId`, înseamnă că se editează o postare. În acest caz, vom verifica dacă postul există cu adevărat și, dacă da, îl vom actualiza în baza de date. În cazul în care parametrul `postId` nu este furnizat, înseamnă că se va adăuga o nouă postare.
+Atunci când este furnizat parametrul `id`, înseamnă că se editează o postare. În acest caz, vom verifica dacă postul există cu adevărat și, dacă da, îl vom actualiza în baza de date. În cazul în care parametrul `id` nu este furnizat, înseamnă că se va adăuga o nouă postare.
 
-Dar de unde provine `postId`? Este parametrul transmis metodei `renderEdit`.
+Dar de unde provine `id`? Este parametrul transmis metodei `renderEdit`.
 
-Acum puteți adăuga un link la șablonul `app/Presenters/templates/Post/show.latte`:
+Acum puteți adăuga un link la șablonul `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/ro/home-page.texy b/quickstart/ro/home-page.texy
index b9c41ef20f..c6821e3474 100644
--- a/quickstart/ro/home-page.texy
+++ b/quickstart/ro/home-page.texy
@@ -66,9 +66,9 @@ Conectarea la baza de date .[#toc-connecting-to-the-database]
 
 Acum, când baza de date este creată și avem câteva mesaje în ea, este momentul potrivit pentru a le afișa pe noua noastră pagină strălucitoare.
 
-În primul rând, trebuie să spunem aplicației noastre ce bază de date să folosească. Configurația conexiunii la baza de date este stocată în `config/local.neon`. Setați conexiunea DSN((Data Source Name)) și acreditările. Ar trebui să arate astfel:
+În primul rând, trebuie să spunem aplicației noastre ce bază de date să folosească. Configurația conexiunii la baza de date este stocată în `config/common.neon`. Setați conexiunea DSN((Data Source Name)) și acreditările. Ar trebui să arate astfel:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Fiți atenți la indentare în timpul editării acestui fișier. [Formatul NEON |neon:format] acceptă atât spații, cât și tabulări, dar nu ambele împreună! Fișierul de configurare din proiectul web utilizează tabulatoarele în mod implicit.
 
-Întreaga configurație, inclusiv este stocată în `config/` în fișierele `common.neon` și `local.neon`. Fișierul `common.neon` conține configurația globală a aplicației, iar `local.neon` conține doar parametrii specifici mediului (de exemplu, diferența dintre serverul de dezvoltare și cel de producție).
-
 
 Injectarea conexiunii la baza de date .[#toc-injecting-the-database-connection]
 ===============================================================================
 
 Prezentatorul `HomePresenter`, care va lista articolele, are nevoie de o conexiune la baza de date. Pentru a o primi, scrieți un constructor ca acesta:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ final class HomePresenter extends Nette\Application\UI\Presenter
 
 Acum să preluăm posturile din baza de date și să le transmitem șablonului, care va reda apoi codul HTML. Pentru aceasta există așa-numita metodă *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Prezentatorul are acum o metodă de randare `renderDefault()` care transmite datele către o vizualizare numită `default`. Șabloanele prezentatorului pot fi găsite în `app/Presenters/templates/{PresenterName}/{viewName}.latte`, astfel încât în acest caz șablonul va fi localizat în `app/Presenters/templates/Home/default.latte`. În șablon, o variabilă numită `$posts` este acum disponibilă, care conține postările din baza de date.
+Prezentatorul are acum o metodă de randare `renderDefault()` care transmite datele către o vizualizare numită `default`. Șabloanele prezentatorului pot fi găsite în `app/UI/{PresenterName}/{viewName}.latte`, astfel încât în acest caz șablonul va fi localizat în `app/UI/Home/default.latte`. În șablon, o variabilă numită `$posts` este acum disponibilă, care conține postările din baza de date.
 
 
 Șablonul .[#toc-template]
@@ -128,9 +125,9 @@ Prezentatorul are acum o metodă de randare `renderDefault()` care transmite dat
 
 Există un șablon generic pentru întreaga pagină (numit *layout*, cu antet, foi de stil, footer, ...) și apoi șabloane specifice pentru fiecare vizualizare (de exemplu, pentru afișarea listei de articole de pe blog), care pot suprascrie unele dintre părțile șablonului layout.
 
-În mod implicit, șablonul de aspect este localizat în `templates/@layout.latte`, care conține:
+În mod implicit, șablonul de aspect este localizat în `app/UI/@layout.latte`, care conține:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Există un șablon generic pentru întreaga pagină (numit *layout*, cu antet, f
 
 `{include content}` inserează un bloc numit `content` în șablonul principal. Îl puteți defini în șabloanele fiecărei vizualizări. În acest caz, vom edita fișierul `Home/default.latte` în felul următor:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Acesta definește [blocul |latte:tags#block]*content*, care va fi inserat în as
 
 Să afișăm articolele de pe blog - vom edita șablonul astfel:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Să afișăm articolele de pe blog - vom edita șablonul astfel:
 
 Dacă vă reîmprospătați browserul, veți vedea lista postărilor de pe blog. Lista nu este foarte fantezistă sau colorată, așa că nu ezitați să adăugați niște [CSS strălucitor |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] la `www/css/style.css` și să o legați într-un layout:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Chestia `|date` se numește filtru. Filtrele sunt folosite pentru a formata ieș
 
 Încă un lucru. Putem face codul un pic mai scurt și, astfel, mai simplu. Putem înlocui *Latte tags* cu *n:attributes* astfel:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/ro/model.texy b/quickstart/ro/model.texy
index b5b25d50e1..02d1e3d7c6 100644
--- a/quickstart/ro/model.texy
+++ b/quickstart/ro/model.texy
@@ -36,9 +36,9 @@ final class PostFacade
 
 Vom trece la `HomePresenter` pe care îl vom edita astfel încât să scăpăm de dependența de `Nette\Database\Explorer` înlocuind-o cu o nouă dependență de noua noastră clasă.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/ro/single-post.texy b/quickstart/ro/single-post.texy
index e1a1de7e60..79c6d784f3 100644
--- a/quickstart/ro/single-post.texy
+++ b/quickstart/ro/single-post.texy
@@ -5,13 +5,13 @@ Pagină cu o singură postare
 Să adăugăm încă o pagină la blogul nostru, care va afișa conținutul unei anumite postări de pe blog.
 
 
-Trebuie să creăm o nouă metodă de redare, care va prelua o anumită postare de pe blog și o va transmite șablonului. A avea această vizualizare în `HomePresenter` nu este plăcută, deoarece este vorba despre un articol de blog, nu despre pagina de start. Așadar, să creăm o nouă clasă `PostPresenter` și să o plasăm în `app/Presenters`. Aceasta va avea nevoie de o conexiune la baza de date, așa că puneți din nou codul de *injecție în baza de date* acolo.
+Trebuie să creăm o nouă metodă de redare, care va prelua o anumită postare de pe blog și o va transmite șablonului. A avea această vizualizare în `HomePresenter` nu este plăcută, deoarece este vorba despre un articol de blog, nu despre pagina de start. Așadar, să creăm o nouă clasă `PostPresenter` și să o plasăm în `app/UI/Post/`. Aceasta va avea nevoie de o conexiune la baza de date, așa că puneți din nou codul de *injecție în baza de date* acolo.
 
 Clasa `PostPresenter` ar trebui să arate astfel:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Trebuie să setăm un namespace corect `App\Presenters` pentru prezentatorul nostru. Depinde de [cartografierea prezentatorului |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Trebuie să setăm un namespace corect `App\UI\Post` pentru prezentatorul nostru. Depinde de [cartografierea prezentatorului |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Metoda `renderShow` are nevoie de un singur argument - ID-ul postului care urmează să fie afișat. Apoi, aceasta încarcă postul din baza de date și transmite rezultatul către șablon.
 
 În șablonul `Home/default.latte` adăugăm un link către acțiunea `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Eticheta `{link}` generează o adresă URL care trimite la acțiunea `Post:show`
 
 Același lucru îl putem scrie pe scurt folosind n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Atributul `n:href` este similar cu eticheta `{link}`.
 
 Deci, vom crea `Post/show.latte` cu acest conținut:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ A patra linie afișează *titlul* postării de pe blog sub forma unui fișier `<
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Cu alte cuvinte, se *redefinește* un bloc numit `title`. Blocul este definit în *șablonul de machetare* (`/app/Presenters/templates/@layout.latte:11`) și, ca în cazul suprapunerii OOP, este suprapus aici. Prin urmare, pagina `<title>` va conține titlul articolului afișat. Am suprascris titlul paginii și tot ce aveam nevoie era `n:block="title"`. Grozav, nu?
+Cu alte cuvinte, se *redefinește* un bloc numit `title`. Blocul este definit în *șablonul de machetare* (`/app/UI/@layout.latte:11`) și, ca în cazul suprapunerii OOP, este suprapus aici. Prin urmare, pagina `<title>` va conține titlul articolului afișat. Am suprascris titlul paginii și tot ce aveam nevoie era `n:block="title"`. Grozav, nu?
 
 A cincea și ultima linie a șablonului afișează conținutul complet al postării.
 
@@ -97,14 +97,14 @@ A cincea și ultima linie a șablonului afișează conținutul complet al postă
 Verificarea ID-ului postului .[#toc-checking-post-id]
 =====================================================
 
-Ce se întâmplă dacă cineva modifică URL-ul și inserează `postId` care nu există? Ar trebui să oferim utilizatorului o eroare frumoasă de tipul "pagina nu a fost găsită". Să actualizăm metoda de redare din `PostPresenter`:
+Ce se întâmplă dacă cineva modifică URL-ul și inserează `id` care nu există? Ar trebui să oferim utilizatorului o eroare frumoasă de tipul "pagina nu a fost găsită". Să actualizăm metoda de redare din `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/ru/@home.texy b/quickstart/ru/@home.texy
index ed7270a31b..2efef9f2bc 100644
--- a/quickstart/ru/@home.texy
+++ b/quickstart/ru/@home.texy
@@ -7,7 +7,7 @@
 После первых двух глав у вас будет свой собственный работающий блог, и вы будете готовы публиковать свои потрясающие посты, хотя после завершения этих двух глав возможности будут довольно сильно ограничены. Чтобы сделать все более приятным для ваших пользователей, вам также следует прочитать следующие главы и продолжать совершенствовать свое приложение.
 
 .[tip]
-В этом руководстве предполагается, что вы завершили документ [Установка |nette:installation] и успешно настроили инструментарий.
+В данном руководстве предполагается, что вы выполнили документ " [Установка |nette:installation] " и успешно настроили инструментарий. Также предполагается, что вы понимаете [объектно-ориентированное программирование на PHP |nette:introduction-to-object-oriented-programming].
 
 Пожалуйста, используйте PHP 8.1 или более позднюю версию. Полное приложение вы можете найти [на GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ http://localhost/nette-blog/www/
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← каталог приложения
-│   ├── <b>Presenters/</b>   ← классы презентеров
-│   │   └── <b>templates/</b>← шаблоны
-│   ├── <b>Router/</b>       ← конфигурация адресов URL
+│   ├── <b>Core/</b>         ← основные необходимые классы
+│   ├── <b>UI/</b>           ← ведущие, шаблоны и др.
+│   │   └── <b>Home/</b>     ← Каталог ведущих
 │   └── <b>Bootstrap.php</b> ← загрузочный класс Bootstrap
 ├── <b>bin/</b>              ← скрипты для командной строки
 ├── <b>config/</b>           ← конфигурационные файлы
@@ -67,7 +67,7 @@ http://localhost/nette-blog/www/
 Очистка .[#toc-cleanup]
 =======================
 
-Веб-проект содержит страницу приветствия, которую мы можем удалить — смело замените содержимое файла `app/Presenters/templates/Home/default.latte` текстом `Hello world!`.
+Веб-проект содержит страницу приветствия, которую мы можем удалить — смело замените содержимое файла `app/UI/Home/default.latte` текстом `Hello world!`.
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ http://localhost/nette-blog/www/
 Tracy (отладчик) .[#toc-tracy-debugger]
 =======================================
 
-Чрезвычайно важным инструментом для разработки является [отладчик под названием Tracy |tracy:]. Попробуйте сделать несколько ошибок в вашем файле `app/Presenters/HomePresenter.php` (например, удалите фигурную скобку из определения класса HomePresenter) и посмотрите, что произойдет. Появится страница с красным экраном и понятным описанием ошибки.
+Чрезвычайно важным инструментом для разработки является [отладчик под названием Tracy |tracy:]. Попробуйте сделать несколько ошибок в вашем файле `app/UI/Home/HomePresenter.php` (например, удалите фигурную скобку из определения класса HomePresenter) и посмотрите, что произойдет. Появится страница с красным экраном и понятным описанием ошибки.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy существенно поможет вам в поиске ошибок. Также обратите внимание на плавающую панель Tracy Bar в правом нижнем углу, которая информирует вас о важных данных во время выполнения.
 
@@ -88,8 +88,7 @@ Tracy существенно поможет вам в поиске ошибок.
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/ru/authentication.texy b/quickstart/ru/authentication.texy
index 451a2382f2..77cdd2ec89 100644
--- a/quickstart/ru/authentication.texy
+++ b/quickstart/ru/authentication.texy
@@ -28,9 +28,9 @@ Nette автоматически создаст службу в контейне
 
 Давайте начнем с формы входа в систему. Вы уже знаете, как работают формы в презентере. Создайте `SignPresenter` и метод `createComponentSignInForm`. Это должно выглядеть следующим образом:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -60,9 +60,9 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 Шаблон .[#toc-template]
 -----------------------
 
-Форма будет отображаться в шаблоне `app/Presenters/templates/Sign/in.latte`.
+Форма будет отображаться в шаблоне `app/UI/Sign/in.latte`.
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Войти</h1>
 
@@ -77,7 +77,7 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 
 Обработчик просто принимает имя пользователя и пароль, которые пользователь ввел, и передает их аутентификатору. После входа в систему мы перенаправим вас на главную страницу:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ private function signInFormSucceeded(Form $form, \stdClass $data): void
 
 Создадим метод `startup()`, который запускается сразу в начале [жизненного цикла презентера|application:presenters#Life-Cycle-of-Presenter]. Это перенаправляет незарегистрированных пользователей на форму входа в систему.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Скрываем ссылки .[#toc-hide-links]
 ----------------------------------
 
-Неавторизованный пользователь больше не может видеть страницы создания и редактирования, но он всё ещё может видеть ссылки, указывающие на них. Давайте спрячем и их. Одна из таких ссылок находится в `app/Presenters/templates/Home/default.latte`, и она должна быть видна, только если пользователь вошел в систему.
+Неавторизованный пользователь больше не может видеть страницы создания и редактирования, но он всё ещё может видеть ссылки, указывающие на них. Давайте спрячем и их. Одна из таких ссылок находится в `app/UI/Home/default.latte`, и она должна быть видна, только если пользователь вошел в систему.
 
 Мы можем скрыть её с помощью *n:атрибута* под названием `n:if`. Если утверждение внутри него `false`, то весь тег `<a>` и его содержимое не будут отображаться:
 
@@ -131,15 +131,15 @@ public function startup(): void
 {if $user->isLoggedIn()}<a n:href="Edit:create">Создать пост</a>{/if}
 ```
 
-Аналогичным образом следует скрыть ссылку редактирования, расположенную в `app/Presenters/templates/Post/show.latte`.
+Аналогичным образом следует скрыть ссылку редактирования, расположенную в `app/UI/Post/show.latte`.
 
 
 Ссылка на форму входа .[#toc-login-form-link]
 =============================================
 
-Эй, но как нам попасть на страницу входа в систему? Нет ссылки, указывающей на нее. Давайте добавим её в файл шаблона `app/Presenters/templates/@layout.latte`. Попробуйте найти хорошее место, это может быть любое место, которое вам больше всего нравится.
+Эй, но как нам попасть на страницу входа в систему? Нет ссылки, указывающей на нее. Давайте добавим её в файл шаблона `app/UI/@layout.latte`. Попробуйте найти хорошее место, это может быть любое место, которое вам больше всего нравится.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Главная</a></li>
@@ -156,7 +156,7 @@ public function startup(): void
 
 Действие выхода из системы выглядит следующим образом, и поскольку мы перенаправляем пользователя немедленно, нет необходимости в шаблоне представления:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/ru/comments.texy b/quickstart/ru/comments.texy
index 8ce23c1520..35c55425db 100644
--- a/quickstart/ru/comments.texy
+++ b/quickstart/ru/comments.texy
@@ -44,7 +44,7 @@ CREATE TABLE `comments` (
 
 В Nette есть понятие *компоненты*. **Компонент** — это многократно используемый класс или фрагмент кода, который может быть присоединен к другому компоненту. Даже презентер является компонентом. Каждый компонент создается с помощью фабрики компонентов. Итак, давайте определим фабрику формы комментариев в `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // означает Nette\Application\UI\Form
@@ -65,9 +65,9 @@ protected function createComponentCommentForm(): Form
 
 Давайте немного объясним это. Первая строка создает новый экземпляр компонента `Form`. Методы, которые указаны ниже, размещают HTML-элементы *input* внутри формы. `->addText` будет отображаться как `<input type=text name=name>`, с `<label>Ваше имя:</label>`. Как вы уже догадались, `->addTextArea` прикрепляет `<textarea>`, а `->addSubmit` добавляет `<input type=submit>`. Подобных методов больше, но это всё, что вам нужно знать прямо сейчас. Вы можете [узнать больше в документации|forms:].
 
-После того как компонент формы определен в презентере, мы можем отобразить его в шаблоне. Для этого поместите тег `{control}` в конец шаблона детализации поста в `app/Presenters/templates/Post/show.latte`. Поскольку имя компонента — `commentForm` (оно происходит от названия метода `createComponentCommentForm`), тег будет выглядеть следующим образом:
+После того как компонент формы определен в презентере, мы можем отобразить его в шаблоне. Для этого поместите тег `{control}` в конец шаблона детализации поста в `app/UI/Post/show.latte`. Поскольку имя компонента — `commentForm` (оно происходит от названия метода `createComponentCommentForm`), тег будет выглядеть следующим образом:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Оставить комментарий</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Это означает «после успешной отправки формы вызвать метод `commentFormSucceeded` текущего презентера». Этот метод ещё не существует, поэтому давайте создадим его.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ private function commentFormSucceeded(\stdClass $data): void
 
 Необходимо объяснить ещё два вызова метода. `$this->redirect('this')` буквально перенаправляет на текущую страницу. Вы должны делать это каждый раз, когда форма отправлена, действительна, и операция обратного вызова сделала то, что должна была сделать. Кроме того, когда вы перенаправляете страницу после отправки формы, вы не увидите хорошо известного сообщения `Вы хотите отправить данные сообщения снова?`, которое иногда можно увидеть в браузере. (В целом, после отправки формы методом `POST`, вы всегда должны перенаправлять пользователя на действие `GET`).
 
-`$this->flashMessage` предназначен для информирования пользователя о результате некоторой операции. Поскольку мы перенаправляем, сообщение не может быть напрямую передано в шаблон и отображено. Поэтому существует метод, который сохранит его и сделает доступным при следующей загрузке страницы. Флэш-сообщения отображаются в стандартном файле `app/Presenters/templates/@layout.latte`, и выглядят они следующим образом:
+`$this->flashMessage` предназначен для информирования пользователя о результате некоторой операции. Поскольку мы перенаправляем, сообщение не может быть напрямую передано в шаблон и отображено. Поэтому существует метод, который сохранит его и сделает доступным при следующей загрузке страницы. Флэш-сообщения отображаются в стандартном файле `app/UI/@layout.latte`, и выглядят они следующим образом:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer использует внешние ключи для р
 
 Как вы помните, мы передали переменную `$post` шаблону в `PostPresenter::renderShow()` и теперь хотим перебрать все комментарии, у которых столбец `post_id` равен нашему `$post->id`. Вы можете сделать это, вызвав `$post->related('comments')`. Это так просто. Посмотрите на полученный код.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 В шаблоне:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Комментарии</h2>
 
diff --git a/quickstart/ru/creating-posts.texy b/quickstart/ru/creating-posts.texy
index d94a588045..bba63afe95 100644
--- a/quickstart/ru/creating-posts.texy
+++ b/quickstart/ru/creating-posts.texy
@@ -20,11 +20,11 @@
 Новый презентер .[#toc-new-presenter]
 =====================================
 
-Назовите новый презентер `EditPresenter` и сохраните его в `app/Presenters/EditPresenter.php`. Ему также необходимо подключиться к базе данных, поэтому здесь мы снова пишем конструктор, который потребует подключения к базе данных:
+Назовите новый презентер `EditPresenter` и сохраните его в `app/UI/Edit/`. Ему также необходимо подключиться к базе данных, поэтому здесь мы снова пишем конструктор, который потребует подключения к базе данных:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ final class EditPresenter extends Nette\Application\UI\Presenter
 
 Теперь добавьте этот метод в `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ protected function createComponentPostForm(): Form
 
 Добавим метод обработчика:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -86,9 +86,9 @@ private function postFormSucceeded(array $data): void
 Страница для создания нового поста .[#toc-page-for-creating-a-new-post]
 =======================================================================
 
-Давайте просто создадим шаблон (`app/Presenters/templates/Edit/create.latte`):
+Давайте просто создадим шаблон (`app/UI/Edit/create.latte`):
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>Новый пост</h1>
 
@@ -105,7 +105,7 @@ private function postFormSucceeded(array $data): void
 
 Вы, вероятно, уже знаете, как добавить ссылку на `EditPresenter` и его действие `create`. Попробуйте.
 
-Просто добавьте в файл `app/Presenters/templates/Home/default.latte`:
+Просто добавьте в файл `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Создать пост</a>
@@ -119,12 +119,12 @@ private function postFormSucceeded(array $data): void
 
 Мы добавим новую страницу `edit` в `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Пост не найден');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 И создайте шаблон `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Редактирование поста</h1>
 
@@ -146,15 +146,15 @@ public function renderEdit(int $postId): void
 
 И обновите метод `postFormSucceeded`, который сможет либо добавлять новый пост (как сейчас), либо редактировать существующие:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Если указан параметр `postId`, это означает, что пост редактируется. В этом случае мы проверим, действительно ли пост существует, и если да, то обновим его в базе данных. Если `postId` не указан, это означает, что будет добавлен новый пост.
+Если указан параметр `id`, это означает, что пост редактируется. В этом случае мы проверим, действительно ли пост существует, и если да, то обновим его в базе данных. Если `id` не указан, это означает, что будет добавлен новый пост.
 
-Но откуда берется `postId`? Это параметр, передаваемый методу `renderEdit`.
+Но откуда берется `id`? Это параметр, передаваемый методу `renderEdit`.
 
-Теперь вы можете добавить ссылку для изменения поста в шаблон `app/Presenters/templates/Post/show.latte`:
+Теперь вы можете добавить ссылку для изменения поста в шаблон `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Изменить пост</a>
diff --git a/quickstart/ru/home-page.texy b/quickstart/ru/home-page.texy
index d678339fd4..66abf37bcc 100644
--- a/quickstart/ru/home-page.texy
+++ b/quickstart/ru/home-page.texy
@@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
 
 Теперь, когда база данных создана и в ней есть несколько постов, самое время отобразить их на нашей новой блестящей странице.
 
-Во-первых, нам нужно сообщить нашему приложению, какую базу данных использовать. Конфигурация подключения к базе данных хранится в файле `config/local.neon`. Установите соединение DSN((Имя источника данных)) и свои учётные данные. Это должно выглядеть следующим образом:
+Во-первых, нам нужно сообщить нашему приложению, какую базу данных использовать. Конфигурация подключения к базе данных хранится в файле `config/common.neon`. Установите соединение DSN((Имя источника данных)) и свои учётные данные. Это должно выглядеть следующим образом:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *укажите здесь имя пользователя*
@@ -78,20 +78,17 @@ database:
 .[note]
 Помните об отступах при редактировании этого файла. [Формат NEON|neon:format] принимает и пробелы, и табуляцию, но не то и другое вместе! В файле конфигурации в веб-проекте по умолчанию используется табуляция.
 
-Вся конфигурация хранится в `config/` в файлах `common.neon` и `local.neon`. Файл `common.neon` содержит глобальную конфигурацию приложения, а `local.neon` содержит только параметры, специфичные для среды (например, разница между сервером разработки и рабочим сервером).
-
 
 Внедрение подключения к базе данных .[#toc-injecting-the-database-connection]
 =============================================================================
 
-Презентер (расположенный в `app/Presenters/HomePresenter.php`), который будет перечислять статьи, нуждается в подключении к базе данных. Для этого измените конструктор следующим образом:
+Презентер (расположенный в `app/UI/Home/HomePresenter.php`), который будет перечислять статьи, нуждается в подключении к базе данных. Для этого измените конструктор следующим образом:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ final class HomePresenter extends Nette\Application\UI\Presenter
 
 Теперь давайте извлечём посты из базы данных и передадим их в шаблон, который затем отобразит HTML-код. Для этого и предназначен так называемый метод *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Теперь в презентере есть один метод рендеринга `renderDefault()`, который передает данные в представление под названием `default`. Шаблоны презентера можно найти в `app/Presenters/templates/{PresenterName}/{viewName}.latte`, поэтому в данном случае шаблон будет расположен в `app/Presenters/templates/Home/default.latte`. В шаблоне теперь доступна переменная `$posts`, которая содержит посты из базы данных.
+Теперь в презентере есть один метод рендеринга `renderDefault()`, который передает данные в представление под названием `default`. Шаблоны презентера можно найти в `app/UI/{PresenterName}/{viewName}.latte`, поэтому в данном случае шаблон будет расположен в `app/UI/Home/default.latte`. В шаблоне теперь доступна переменная `$posts`, которая содержит посты из базы данных.
 
 
 Шаблон .[#toc-template]
@@ -128,17 +125,17 @@ public function renderDefault(): void
 
 Существует общий шаблон для всей страницы (называется *layout* (макет), с заголовком, таблицами стилей, нижним колонтитулом и т. д.), а также специфические шаблоны для каждого вида (например, для отображения списка записей блога), которые могут переопределять некоторые части шаблона макета.
 
-По умолчанию шаблон макета располагается в файле `app/Presenters/templates/@layout.latte`, который содержит:
+По умолчанию шаблон макета располагается в файле `app/UI/@layout.latte`, который содержит:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
 ```
 
-`{include content}` вставляет блок с именем `content` в основной шаблон. Вы можете определить его в шаблонах каждого представления. В нашем случае мы отредактируем файл `app/Presenters/templates/Home/default.latte` следующим образом:
+`{include content}` вставляет блок с именем `content` в основной шаблон. Вы можете определить его в шаблонах каждого представления. В нашем случае мы отредактируем файл `app/UI/Home/default.latte` следующим образом:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Привет, мир!
 {/block}
@@ -148,7 +145,7 @@ public function renderDefault(): void
 
 Давайте отобразим записи блога — для этого отредактируем шаблон следующим образом:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1 n:block="title">Мой блог</h1>
 
@@ -166,7 +163,7 @@ public function renderDefault(): void
 
 Если вы обновите браузер, вы увидите список записей вашего блога. Список не очень причудлив или красочен, поэтому не стесняйтесь добавить немного [блестящего CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] в `www/css/style.css`, а затем вставьте ссылку на этот файл в макет (файл `@layout.latte`):
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ public function renderDefault(): void
 
 И ещё одно. Мы можем сделать код немного короче и, следовательно, проще. Мы можем заменить *теги Latte* на *n:attributes* следующим образом:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/ru/model.texy b/quickstart/ru/model.texy
index 7f0e1c4224..07612de887 100644
--- a/quickstart/ru/model.texy
+++ b/quickstart/ru/model.texy
@@ -36,9 +36,9 @@ final class PostFacade
 
 Перейдем к файлу `HomePresenter.php`, который мы отредактируем так, чтобы избавиться от зависимости от `Nette\Database\Explorer`, заменив её новой зависимостью от нашего созданного класса.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/ru/single-post.texy b/quickstart/ru/single-post.texy
index c031837962..a4529bc779 100644
--- a/quickstart/ru/single-post.texy
+++ b/quickstart/ru/single-post.texy
@@ -5,13 +5,13 @@
 Давайте добавим в наш блог еще одну страницу, на которой будет отображаться содержимое одной конкретной записи блога.
 
 
-Нам нужно создать новый метод render, который будет получать одну конкретную запись блога и передавать её в шаблон. Иметь это представление в `HomePresenter` не очень приятно, потому что речь идёт о записи в блоге, а не о главной странице. Итак, давайте создадим новый класс `PostPresenter` и поместим его в `app/Presenters`. Ему потребуется соединение с базой данных, поэтому снова поместите туда код *внедрения зависимости*.
+Нам нужно создать новый метод render, который будет получать одну конкретную запись блога и передавать её в шаблон. Иметь это представление в `HomePresenter` не очень приятно, потому что речь идёт о записи в блоге, а не о главной странице. Итак, давайте создадим новый класс `PostPresenter` и поместим его в `app/UI/Post/`. Ему потребуется соединение с базой данных, поэтому снова поместите туда код *внедрения зависимости*.
 
 `PostPresenter` должен выглядеть следующим образом:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Мы должны установить правильное пространство имен `App\Presenters` для нашего презентера. Это зависит от [presenter mapping |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Мы должны установить правильное пространство имен `App\UI\Post` для нашего презентера. Это зависит от [presenter mapping |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Метод `renderShow` требует один аргумент — ID отображаемого поста. Затем он загружает этот пост из базы данных и передает результат в шаблон.
 
 В шаблоне `Home/default.latte` мы добавляем ссылку на действие `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 То же самое мы можем написать коротко, используя n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -59,11 +59,11 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 
 
-Шаблон для действия `Post:show` ещё не существует. Мы можем открыть ссылку на этот пост. [Tracy |tracy:] покажет ошибку о том, что `app/Presenters/templates/Post/show.latte` не существует. Если вы видите любой другой отчёт об ошибке, вероятно, вам нужно включить mod_rewrite в вашем веб-сервере.
+Шаблон для действия `Post:show` ещё не существует. Мы можем открыть ссылку на этот пост. [Tracy |tracy:] покажет ошибку о том, что `app/UI/Post/show.latte` не существует. Если вы видите любой другой отчёт об ошибке, вероятно, вам нужно включить mod_rewrite в вашем веб-сервере.
 
 Поэтому мы создадим `Post/show.latte` с таким содержанием:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← вернуться к списку постов</a></p>
@@ -89,7 +89,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Проще говоря, он *переопределяет* блок под названием `title`. Блок определен в *шаблоне макета* (`/app/Presenters/templates/@layout.latte:11`) и, как и в случае с переопределением ООП, он переопределяется здесь. Поэтому `<title>` страницы будет содержать заголовок отображаемого поста. Мы переопределили заголовок страницы, и всё, что нам было нужно, это `n:block="title"`. Здорово, да?
+Проще говоря, он *переопределяет* блок под названием `title`. Блок определен в *шаблоне макета* (`/app/UI/@layout.latte:11`) и, как и в случае с переопределением ООП, он переопределяется здесь. Поэтому `<title>` страницы будет содержать заголовок отображаемого поста. Мы переопределили заголовок страницы, и всё, что нам было нужно, это `n:block="title"`. Здорово, да?
 
 Пятая и последняя строка шаблона отображает полное содержание вашего поста.
 
@@ -97,14 +97,14 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 Проверка идентификатора поста .[#toc-checking-post-id]
 ======================================================
 
-Что произойдет, если кто-то изменит URL и вставит несуществующий `postId`? Мы должны предоставить пользователю красивую страницу ошибки «страница не найдена». Давайте обновим метод `render` в файле `PostPresenter.php`:
+Что произойдет, если кто-то изменит URL и вставит несуществующий `id`? Мы должны предоставить пользователю красивую страницу ошибки «страница не найдена». Давайте обновим метод `render` в файле `PostPresenter.php`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Страница не найдена!');
 	}
diff --git a/quickstart/sl/@home.texy b/quickstart/sl/@home.texy
index d12b28f7a0..de950f0bcc 100644
--- a/quickstart/sl/@home.texy
+++ b/quickstart/sl/@home.texy
@@ -7,7 +7,7 @@ Spoznajte ogrodje Nette in ustvarite preprost blog s komentarji. Začnimo!
 Po prvih dveh poglavjih boste imeli svoj delujoči blog in pripravljeni boste objavljati svoje odlične objave, čeprav bodo funkcije po zaključku teh dveh poglavij precej omejene. Da bi bile stvari za vaše uporabnike prijetnejše, preberite tudi naslednja poglavja in še naprej izboljšujte svojo aplikacijo.
 
 .[tip]
-Ta vadnica predpostavlja, da ste dokončali dokument [Namestitev |nette:installation] in uspešno nastavili svoje orodje.
+Ta vadnica predpostavlja, da ste dokončali dokument [Namestitev |nette:installation] in uspešno nastavili svoje orodje. Prav tako predpostavlja, da razumete [objektno usmerjeno programiranje v PHP |nette:introduction-to-object-oriented-programming].
 
 Uporabite PHP 8.1 ali novejšo različico. Celotno aplikacijo lahko najdete [na GitHubu |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ Spletni projekt ima naslednjo strukturo:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← osnovni potrebni razredi
+│   ├── <b>UI/</b>           ← predstavniki, predloge in podobno.
+│   │   └── <b>Home/</b>     ← Domači imenik predstavnikov
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ Najpomembnejši imenik za vas je `app/`. V njem najdete datoteko `Bootstrap.php`
 Očistite .[#toc-cleanup]
 ========================
 
-Spletni projekt vsebuje pozdravno stran, ki jo lahko odstranimo - odstranite datoteko `app/Presenters/templates/Home/default.latte` in jo nadomestite z besedilom "Hello world!".
+Spletni projekt vsebuje pozdravno stran, ki jo lahko odstranimo - odstranite datoteko `app/UI/Home/default.latte` in jo nadomestite z besedilom "Hello world!".
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Spletni projekt vsebuje pozdravno stran, ki jo lahko odstranimo - odstranite dat
 Tracy (Debugger) .[#toc-tracy-debugger]
 =======================================
 
-Izjemno pomembno orodje za razvoj je [razhroščevalnik Tracy. |tracy:] Poskusite narediti nekaj napak v svoji datoteki `app/Presenters/HomePresenter.php` (npr. odstranite oglati oklepaj iz definicije razreda HomePresenter) in si oglejte, kaj se bo zgodilo. Pojavila se bo stran z rdečim zaslonom in razumljivim opisom napake.
+Izjemno pomembno orodje za razvoj je [razhroščevalnik Tracy. |tracy:] Poskusite narediti nekaj napak v svoji datoteki `app/UI/Home/HomePresenter.php` (npr. odstranite oglati oklepaj iz definicije razreda HomePresenter) in si oglejte, kaj se bo zgodilo. Pojavila se bo stran z rdečim zaslonom in razumljivim opisom napake.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy vam bo bistveno pomagal pri lovljenju napak. Upoštevajte tudi plavajočo vrstico Tracy v spodnjem desnem kotu, ki vas obvešča o pomembnih podatkih v času izvajanja.
 
@@ -88,8 +88,7 @@ V produkcijskem načinu je Tracy seveda onemogočen in ne razkriva nobenih obču
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/sl/authentication.texy b/quickstart/sl/authentication.texy
index fd313a01b8..8844d3408f 100644
--- a/quickstart/sl/authentication.texy
+++ b/quickstart/sl/authentication.texy
@@ -28,9 +28,9 @@ Zdaj imamo pripravljen zaledni del avtentikacije, zagotoviti pa moramo uporabni
 
 Začnimo z obrazcem za prijavo. Že veste, kako delujejo obrazci v predstavitvenem programu. Ustvarite `SignPresenter` in metodo `createComponentSignInForm`. Izgledati morata takole:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Predloga .[#toc-template]
 
 Obrazec bo prikazan v predlogi `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Dodamo tudi *obdelovalnik obrazca* za prijavo uporabnika, ki se sproži takoj po
 
 Obvladovalnik bo samo prevzel uporabniško ime in geslo, ki ju je vnesel uporabnik, ter ju posredoval prej opredeljenemu avtentifikatorju. Ko se uporabnik prijavi, ga bomo preusmerili na domačo stran.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Zagotovili bomo obrazec za dodajanje in urejanje objav. Opredeljen je v predstav
 
 Ustvarimo metodo `startup()`, ki se zažene takoj na začetku [življenjskega cikla predstavnika |application:presenters#life-cycle-of-presenter]. Ta uporabnike, ki niso prijavljeni, preusmeri na obrazec za prijavo.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Skrij povezave .[#toc-hide-links]
 ---------------------------------
 
-Uporabnik brez avtentikacije ne more več videti strani *ustvari* in *revidiraj*, še vedno pa lahko vidi povezave, ki kažejo nanju. Skrijmo tudi te. Ena takšnih povezav je na naslovu `app/Presenters/templates/Home/default.latte`, vidna pa mora biti le, če je uporabnik prijavljen.
+Uporabnik brez avtentikacije ne more več videti strani *ustvari* in *revidiraj*, še vedno pa lahko vidi povezave, ki kažejo nanju. Skrijmo tudi te. Ena takšnih povezav je na naslovu `app/UI/Home/default.latte`, vidna pa mora biti le, če je uporabnik prijavljen.
 
 Skrijemo jo lahko z uporabo *n:atributa*, imenovanega `n:if`. Če je izjava v njem `false`, se celotna `<a>` oznaka in njena vsebina ne bosta prikazani:
 
@@ -131,7 +131,7 @@ To je bližnjica za (ne zamenjujte s `tag-if`):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-Na podoben način morate skriti povezavo za urejanje, ki se nahaja na naslovu `app/Presenters/templates/Post/show.latte`.
+Na podoben način morate skriti povezavo za urejanje, ki se nahaja na naslovu `app/UI/Post/show.latte`.
 
 
 Povezava na prijavni obrazec .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Povezava na prijavni obrazec .[#toc-login-form-link]
 
 Hej, ampak kako pridemo do prijavne strani? Ni nobene povezave, ki bi kazala nanjo. Dodajmo jo v datoteko predloge `@layout.latte`. Poskusi najti lepo mesto, lahko je kjerkoli, kjer ti je najbolj všeč.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Hej, ampak kako pridemo do prijavne strani? Ni nobene povezave, ki bi kazala nan
 
 Akcija odjave je videti takole, in ker uporabnika takoj preusmerimo, ne potrebujemo predloge za prikaz.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/sl/comments.texy b/quickstart/sl/comments.texy
index ae8ba901bc..029604c0e1 100644
--- a/quickstart/sl/comments.texy
+++ b/quickstart/sl/comments.texy
@@ -44,7 +44,7 @@ Najprej moramo ustvariti obrazec, ki bo uporabnikom omogočal komentiranje na na
 
 Nette Framework ima koncept *komponent*. Komponenta** je razred ali del kode, ki ga je mogoče ponovno uporabiti in ga je mogoče priključiti na drugo komponento. Tudi predstavnik je komponenta. Vsaka komponenta je ustvarjena s pomočjo tovarne komponent. Zato definirajmo tovarno obrazca za komentarje v `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // pomeni Nette\Application\UI\Form
@@ -67,7 +67,7 @@ Malo jo razložimo. Prva vrstica ustvari nov primerek komponente `Form`. Nasledn
 
 Ko je komponenta obrazca opredeljena v predstavniku, jo lahko upodobimo (prikažemo) v predlogi. To storite tako, da postavite oznako `{control}` na konec predloge podrobnosti prispevka, v `Post/show.latte`. Ker je ime komponente `commentForm` (izhaja iz imena metode `createComponentCommentForm`), bo oznaka videti takole
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Pomeni "po uspešni oddaji obrazca pokliči metodo `commentFormSucceeded` trenutnega predstavnika". Ta metoda še ne obstaja, zato jo ustvarimo.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ Nova metoda ima en argument, ki je primerek obrazca, ki se pošilja in ga je ust
 
 Razložiti je treba še dva klica metod. Preusmeritev dobesedno preusmeri na trenutno stran. To morate storiti vsakič, ko je obrazec oddan, veljaven in je operacija povratnega klica naredila, kar bi morala. Prav tako pri preusmeritvi strani po oddaji obrazca ne boste videli znanega sporočila `Would you like to submit the post data again?`, ki se včasih pojavi v brskalniku. (Na splošno morate po oddaji obrazca z metodo `POST` uporabnika vedno preusmeriti na dejanje `GET`.)
 
-Sporočilo `flashMessage` je namenjeno obveščanju uporabnika o rezultatu neke operacije. Ker gre za preusmeritev, sporočila ni mogoče neposredno posredovati predlogi in ga izrisati. Zato je tu ta metoda, ki ga bo shranila in dala na voljo ob naslednjem nalaganju strani. Sporočila flash so prikazana v privzeti datoteki `app/Presenters/templates/@layout.latte` in so videti takole:
+Sporočilo `flashMessage` je namenjeno obveščanju uporabnika o rezultatu neke operacije. Ker gre za preusmeritev, sporočila ni mogoče neposredno posredovati predlogi in ga izrisati. Zato je tu ta metoda, ki ga bo shranila in dala na voljo ob naslednjem nalaganju strani. Sporočila flash so prikazana v privzeti datoteki `app/UI/@layout.latte` in so videti takole:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer uporablja tuje ključe za reševanje razmerij med tabela
 
 Kot se morda spomnite, smo spremenljivko `$post` posredovali predlogi v `PostPresenter::renderShow()`, zdaj pa želimo iterirati po vseh komentarjih, ki imajo stolpec `post_id` enak našemu `$post->id`. To lahko storite tako, da pokličete `$post->related('comments')`. Tako preprosto je. Oglejte si nastalo kodo.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 In predlogo:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/sl/creating-posts.texy b/quickstart/sl/creating-posts.texy
index 35c01fe754..c539705faf 100644
--- a/quickstart/sl/creating-posts.texy
+++ b/quickstart/sl/creating-posts.texy
@@ -20,11 +20,11 @@ Pozneje bomo dodali tudi preverjanje pristnosti in omogočili dodajanje novih ob
 Nov predvajalnik .[#toc-new-presenter]
 ======================================
 
-Novemu predvajalniku damo ime `EditPresenter` in ga shranimo v `app/Presenters/EditPresenter.php`. Prav tako se mora povezati s podatkovno bazo, zato tudi tu napišemo konstruktor, ki bo zahteval povezavo s podatkovno bazo:
+Novemu predvajalniku damo ime `EditPresenter` in ga shranimo v `app/UI/Edit/`. Prav tako se mora povezati s podatkovno bazo, zato tudi tu napišemo konstruktor, ki bo zahteval povezavo s podatkovno bazo:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Obrazce in komponente smo že obravnavali, ko smo dodajali podporo za komentarje
 
 Zdaj dodajte to metodo v `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Shranjevanje nove objave iz obrazca .[#toc-saving-new-post-from-form]
 
 Nadaljujte z dodajanjem metode Handler.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Stran za ustvarjanje nove objave .[#toc-page-for-creating-a-new-post]
 
 Ustvarimo samo predlogo `Edit/create.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Povezava za ustvarjanje objav .[#toc-link-for-creating-posts]
 
 Verjetno že veste, kako dodati povezavo na `EditPresenter` in njeno akcijo `create`. Preizkusite jo.
 
-Preprosto dodajte v datoteko `app/Presenters/templates/Home/default.latte`:
+Preprosto dodajte v datoteko `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Dodajmo tudi možnost urejanja obstoječih objav. To bo precej preprosto - že i
 
 Na spletno stran `EditPresenter` bomo dodali novo stran `edit`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 In ustvarili predlogo `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ In ustvarili predlogo `Edit/edit.latte`:
 
 In posodobite metodo `postFormSucceeded`, s katero bo mogoče dodati novo objavo (kot zdaj) ali urediti obstoječo:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Če je podan parameter `postId`, to pomeni, da se prispevek ureja. V takem primeru bomo preverili, ali objava res obstaja, in če je tako, jo bomo posodobili v zbirki podatkov. Če parameter `postId` ni naveden, to pomeni, da bo dodana nova objava.
+Če je podan parameter `id`, to pomeni, da se prispevek ureja. V takem primeru bomo preverili, ali objava res obstaja, in če je tako, jo bomo posodobili v zbirki podatkov. Če parameter `id` ni naveden, to pomeni, da bo dodana nova objava.
 
-Toda od kod prihaja podatek `postId`? To je parameter, ki ga posredujemo metodi `renderEdit`.
+Toda od kod prihaja podatek `id`? To je parameter, ki ga posredujemo metodi `renderEdit`.
 
-Zdaj lahko dodate povezavo do predloge `app/Presenters/templates/Post/show.latte`:
+Zdaj lahko dodate povezavo do predloge `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/sl/home-page.texy b/quickstart/sl/home-page.texy
index 64e508ca40..f454aa8c6a 100644
--- a/quickstart/sl/home-page.texy
+++ b/quickstart/sl/home-page.texy
@@ -66,9 +66,9 @@ Povezovanje s podatkovno bazo .[#toc-connecting-to-the-database]
 
 Ko je zbirka podatkov ustvarjena in imamo v njej nekaj objav, je zdaj pravi čas, da jih prikažemo na naši novi svetleči strani.
 
-Najprej moramo našemu programu povedati, katero podatkovno zbirko naj uporabi. Konfiguracija povezave s podatkovno bazo je shranjena v `config/local.neon`. Nastavite povezavo DSN((Data Source Name)) in svoje poverilnice. Izgledati mora takole:
+Najprej moramo našemu programu povedati, katero podatkovno zbirko naj uporabi. Konfiguracija povezave s podatkovno bazo je shranjena v `config/common.neon`. Nastavite povezavo DSN((Data Source Name)) in svoje poverilnice. Izgledati mora takole:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Pri urejanju te datoteke bodite pozorni na alineje. [Oblika NEON |neon:format] sprejema tako presledke kot tabulatorje, vendar ne obojega skupaj! Konfiguracijska datoteka v spletnem projektu privzeto uporablja tabulatorje.
 
-Celotna konfiguracija je shranjena v `config/` v datotekah `common.neon` in `local.neon`. Datoteka `common.neon` vsebuje globalno konfiguracijo aplikacije, datoteka `local.neon` pa samo parametre, ki so značilni za okolje (npr. razlika med razvojnim in produkcijskim strežnikom).
-
 
 Vbrizgavanje povezave s podatkovno bazo .[#toc-injecting-the-database-connection]
 =================================================================================
 
 Predstavitveni program `HomePresenter`, ki bo objavil seznam člankov, potrebuje povezavo s podatkovno bazo. Če jo želite prejeti, napišite konstruktor, kot je ta:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Nalaganje objav iz zbirke podatkov .[#toc-loading-posts-from-the-database]
 
 Zdaj prenesimo objave iz zbirke podatkov in jih posredujemo predlogi, ki bo nato prikazala kodo HTML. Za to je namenjena tako imenovana metoda *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Predstavitev ima zdaj eno metodo upodabljanja `renderDefault()`, ki posreduje podatke pogledu z imenom `default`. Predloge predstavnikov se nahajajo v `app/Presenters/templates/{PresenterName}/{viewName}.latte`, zato se bo v tem primeru predloga nahajala v `app/Presenters/templates/Home/default.latte`. V predlogi je zdaj na voljo spremenljivka z imenom `$posts`, ki vsebuje objave iz podatkovne zbirke.
+Predstavitev ima zdaj eno metodo upodabljanja `renderDefault()`, ki posreduje podatke pogledu z imenom `default`. Predloge predstavnikov se nahajajo v `app/UI/{PresenterName}/{viewName}.latte`, zato se bo v tem primeru predloga nahajala v `app/UI/Home/default.latte`. V predlogi je zdaj na voljo spremenljivka z imenom `$posts`, ki vsebuje objave iz podatkovne zbirke.
 
 
 Predloga .[#toc-template]
@@ -128,9 +125,9 @@ Predloga .[#toc-template]
 
 Obstaja splošna predloga za celotno stran (imenovana *layout*, z glavo, slogovnimi listi, nogo, ...) in nato posebne predloge za vsak pogled (npr. za prikaz seznama blogovskih objav), ki lahko prekrijejo nekatere dele predloge layout.
 
-Privzeto se predloga postavitve nahaja v spletnem mestu `templates/@layout.latte`, ki vsebuje:
+Privzeto se predloga postavitve nahaja v spletnem mestu `app/UI/@layout.latte`, ki vsebuje:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Privzeto se predloga postavitve nahaja v spletnem mestu `templates/@layout.latte
 
 `{include content}` v glavno predlogo vstavi blok z imenom `content`. Določite ga lahko v predlogah vsakega pogleda. V tem primeru bomo tako uredili datoteko `Home/default.latte`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ V njej je opredeljen [blok |latte:tags#block]*vsebina*, ki bo vstavljen v postav
 
 Prikažimo blogovske objave - predlogo bomo uredili takole:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Prikažimo blogovske objave - predlogo bomo uredili takole:
 
 Če osvežite brskalnik, se bo prikazal seznam vaših blogovskih objav. Seznam ni preveč domišljen ali barvit, zato lahko na `www/css/style.css` dodate nekaj [bleščečih CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] in ga povežete v postavitev:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Ta `|date` se imenuje filter. Filtri se uporabljajo za oblikovanje izpisa. Ta fi
 
 Še ena stvar. Kodo lahko še nekoliko skrajšamo in s tem poenostavimo. Oznake *Latte* lahko nadomestimo z *n:atributi*, kot sledi:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/sl/model.texy b/quickstart/sl/model.texy
index f712ec3e85..1d2e52c93d 100644
--- a/quickstart/sl/model.texy
+++ b/quickstart/sl/model.texy
@@ -36,9 +36,9 @@ V razredu posredujemo podatkovno zbirko Explorer:[api:Nette\Database\Explorer].
 
 Preklopili bomo na `HomePresenter`, ki ga bomo uredili tako, da se bomo znebili odvisnosti od `Nette\Database\Explorer` in jo nadomestili z novo odvisnostjo od našega novega razreda.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/sl/single-post.texy b/quickstart/sl/single-post.texy
index 0720d19809..303475203a 100644
--- a/quickstart/sl/single-post.texy
+++ b/quickstart/sl/single-post.texy
@@ -5,13 +5,13 @@ Stran z eno objavo
 Dodajmo še eno stran na naš blog, ki bo prikazovala vsebino ene posamezne objave.
 
 
-Ustvariti moramo novo metodo izrisa, ki bo pobrala eno določeno objavo na blogu in jo posredovala predlogi. Imeti ta pogled v naslovu `HomePresenter` ni lepo, saj gre za blogovsko objavo in ne za domačo stran. Zato ustvarimo nov razred `PostPresenter` in ga postavimo v `app/Presenters`. Potreboval bo povezavo s podatkovno bazo, zato tja ponovno postavimo kodo *database injection*.
+Ustvariti moramo novo metodo izrisa, ki bo pobrala eno določeno objavo na blogu in jo posredovala predlogi. Imeti ta pogled v naslovu `HomePresenter` ni lepo, saj gre za blogovsko objavo in ne za domačo stran. Zato ustvarimo nov razred `PostPresenter` in ga postavimo v `app/UI/Post/`. Potreboval bo povezavo s podatkovno bazo, zato tja ponovno postavimo kodo *database injection*.
 
 Razred `PostPresenter` naj bo videti takole:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Nastaviti moramo pravilen imenski prostor `App\Presenters` za našega predstavnika. To je odvisno od [preslikave predstavnika |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Nastaviti moramo pravilen imenski prostor `App\UI\Post` za našega predstavnika. To je odvisno od [preslikave predstavnika |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Metoda `renderShow` zahteva en argument - ID prispevka, ki ga je treba prikazati. Nato objavo naloži iz podatkovne zbirke in rezultat posreduje predlogi.
 
 V predlogi `Home/default.latte` dodamo povezavo do akcije `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Oznaka `{link}` ustvari naslov URL, ki kaže na akcijo `Post:show`. Ta oznaka ko
 
 Enako lahko na kratko zapišemo z uporabo atributa n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Predloga za akcijo `Post:show` še ne obstaja. Odpremo lahko povezavo do tega pr
 
 Tako bomo ustvarili spletno stran `Post/show.latte` s to vsebino:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ Tretja vrstica oblikuje časovni žig objave s filtrom, kot že vemo.
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Preprosto povedano, *na novo definira* blok z imenom `title`. Blok je opredeljen v *šabloni za postavitev* (`/app/Presenters/templates/@layout.latte:11`) in tako kot pri OOP overriding, je tudi tukaj prepisan. Zato se na strani `<title>` bo vsebovala naslov prikazane objave. Prekrili smo naslov strani in vse, kar smo potrebovali, je bilo `n:block="title"`. Super, kajne?
+Preprosto povedano, *na novo definira* blok z imenom `title`. Blok je opredeljen v *šabloni za postavitev* (`/app/UI/@layout.latte:11`) in tako kot pri OOP overriding, je tudi tukaj prepisan. Zato se na strani `<title>` bo vsebovala naslov prikazane objave. Prekrili smo naslov strani in vse, kar smo potrebovali, je bilo `n:block="title"`. Super, kajne?
 
 V peti in zadnji vrstici predloge je prikazana celotna vsebina vašega prispevka.
 
@@ -97,14 +97,14 @@ V peti in zadnji vrstici predloge je prikazana celotna vsebina vašega prispevka
 Preverjanje ID objave .[#toc-checking-post-id]
 ==============================================
 
-Kaj se zgodi, če nekdo spremeni naslov URL in vstavi `postId`, ki ne obstaja? Uporabniku moramo zagotoviti lepo napako "stran ni bila najdena". Posodobimo metodo upodabljanja v `PostPresenter`:
+Kaj se zgodi, če nekdo spremeni naslov URL in vstavi `id`, ki ne obstaja? Uporabniku moramo zagotoviti lepo napako "stran ni bila najdena". Posodobimo metodo upodabljanja v `PostPresenter`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/tr/@home.texy b/quickstart/tr/@home.texy
index 8b7b9947c9..96f177f22a 100644
--- a/quickstart/tr/@home.texy
+++ b/quickstart/tr/@home.texy
@@ -7,7 +7,7 @@ Yorumlarla basit bir blog oluştururken Nette Framework'ü tanıyın. Hadi başl
 İlk iki bölümden sonra, kendi çalışan blogunuza sahip olacaksınız ve harika gönderilerinizi yayınlamaya hazır olacaksınız, ancak bu iki bölümü tamamladıktan sonra özellikler oldukça sınırlı olacaktır. Kullanıcılarınız için işleri daha güzel hale getirmek için sonraki bölümleri de okumalı ve uygulamanızı geliştirmeye devam etmelisiniz.
 
 .[tip]
-Bu eğitimde [Kurulum |nette:installation] belgesini tamamladığınız ve araçlarınızı başarıyla kurduğunuz varsayılmaktadır.
+Bu öğretici, [Kurulum |nette:installation] belgesini tamamladığınızı ve araçlarınızı başarıyla kurduğunuzu varsayar. Ayrıca [PHP'de nesne yönelimli programlamayı |nette:introduction-to-object-oriented-programming] anladığınızı varsayar.
 
 Lütfen PHP 8.1 veya üstünü kullanın. Uygulamanın tamamını [GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]'da bulabilirsiniz.
 
@@ -45,9 +45,9 @@ Web Projesi aşağıdaki yapıya sahiptir:
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← application directory
-│   ├── <b>Presenters/</b>   ← presenter classes
-│   │   └── <b>templates/</b>← templates
-│   ├── <b>Router/</b>       ← configuration of URL addresses
+│   ├── <b>Core/</b>         ← temel gerekli sınıflar
+│   ├── <b>UI/</b>           ← presenters, templates & co.
+│   │   └── <b>Home/</b>     ← Home sunucu dizini
 │   └── <b>Bootstrap.php</b> ← booting class Bootstrap
 ├── <b>bin/</b>              ← scripts for the command line
 ├── <b>config/</b>           ← configuration files
@@ -67,7 +67,7 @@ Sizin için en önemli dizin `app/`. Orada `Bootstrap.php` dosyasını bulabilir
 Temizlik .[#toc-cleanup]
 ========================
 
-Web Projesi, kaldırabileceğimiz bir karşılama sayfası içerir - `app/Presenters/templates/Home/default.latte` dosyasını silmekten ve "Merhaba dünya!" metniyle değiştirmekten çekinmeyin.
+Web Projesi, kaldırabileceğimiz bir karşılama sayfası içerir - `app/UI/Home/default.latte` dosyasını silmekten ve "Merhaba dünya!" metniyle değiştirmekten çekinmeyin.
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ Web Projesi, kaldırabileceğimiz bir karşılama sayfası içerir - `app/Presen
 Tracy (Hata Ayıklayıcı) .[#toc-tracy-debugger]
 ==============================================
 
-Geliştirme için son derece önemli bir araç [Tracy adlı bir hata ayıklayıcıdır |tracy:]. `app/Presenters/HomePresenter.php` dosyanızda bazı hatalar yapmaya çalışın (örneğin HomePresenter sınıfının tanımından bir küme parantezini kaldırın) ve ne olacağını görün. Anlaşılabilir bir hata açıklamasıyla birlikte kırmızı ekranlı bir sayfa açılacaktır.
+Geliştirme için son derece önemli bir araç [Tracy adlı bir hata ayıklayıcıdır |tracy:]. `app/UI/Home/HomePresenter.php` dosyanızda bazı hatalar yapmaya çalışın (örneğin HomePresenter sınıfının tanımından bir küme parantezini kaldırın) ve ne olacağını görün. Anlaşılabilir bir hata açıklamasıyla birlikte kırmızı ekranlı bir sayfa açılacaktır.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy, hataları ararken size önemli ölçüde yardımcı olacaktır. Ayrıca, önemli çalışma zamanı verileri hakkında sizi bilgilendiren sağ alt köşedeki yüzen Tracy Çubuğuna da dikkat edin.
 
@@ -88,8 +88,7 @@ Tracy, hataları ararken size önemli ölçüde yardımcı olacaktır. Ayrıca,
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/tr/authentication.texy b/quickstart/tr/authentication.texy
index abee754ad7..bf6d8c02da 100644
--- a/quickstart/tr/authentication.texy
+++ b/quickstart/tr/authentication.texy
@@ -28,9 +28,9 @@ Artık kimlik doğrulamanın arka uç kısmını hazır hale getirdik ve kullan
 
 Giriş formu ile başlayalım. Sunucuda formların nasıl çalıştığını zaten biliyorsunuz. `SignPresenter` ve `createComponentSignInForm` yöntemini oluşturun. Bu şekilde görünmelidir:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -62,7 +62,7 @@ Kullanıcı adı ve şifre için bir giriş vardır.
 
 Form şablonda oluşturulacaktır `in.latte`
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Sign in</h1>
 
@@ -77,7 +77,7 @@ Ayrıca, kullanıcının oturum açması için form gönderildikten hemen sonra
 
 İşleyici sadece kullanıcının girdiği kullanıcı adı ve şifreyi alacak ve daha önce tanımlanan kimlik doğrulayıcıya aktaracaktır. Kullanıcı giriş yaptıktan sonra, onu ana sayfaya yönlendireceğiz.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ Gönderi eklemek ve düzenlemek için bir form oluşturacağız. Sunucuda tanım
 
 [Sunum yapan kişinin yaşam döngüsünün |application:presenters#life-cycle-of-presenter] hemen başında başlatılan bir `startup()` yöntemi oluşturuyoruz. Bu, oturum açmamış kullanıcıları oturum açma formuna yönlendirir.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Bağlantıları Gizle .[#toc-hide-links]
 -------------------------------------
 
-Kimliği doğrulanmamış bir kullanıcı artık *oluştur* veya *sayfa düzenle* sayfalarını göremez, ancak bunlara işaret eden bağlantıları hala görebilir. Bunları da gizleyelim. Böyle bir bağlantı `app/Presenters/templates/Home/default.latte` adresindedir ve yalnızca kullanıcı oturum açtığında görünür olmalıdır.
+Kimliği doğrulanmamış bir kullanıcı artık *oluştur* veya *sayfa düzenle* sayfalarını göremez, ancak bunlara işaret eden bağlantıları hala görebilir. Bunları da gizleyelim. Böyle bir bağlantı `app/UI/Home/default.latte` adresindedir ve yalnızca kullanıcı oturum açtığında görünür olmalıdır.
 
 Bunu `n:if` adlı *n:attribute* kullanarak gizleyebiliriz. Eğer içindeki ifade `false` ise, tüm `<a>` etiketi ve içeriği görüntülenmeyecektir:
 
@@ -131,7 +131,7 @@ için bir kısayoldur ( `tag-if` ile karıştırmayın):
 {if $user->isLoggedIn()}<a n:href="Edit:create">Create post</a>{/if}
 ```
 
-`app/Presenters/templates/Post/show.latte` adresinde bulunan düzenleme bağlantısını da benzer şekilde gizlemelisiniz.
+`app/UI/Post/show.latte` adresinde bulunan düzenleme bağlantısını da benzer şekilde gizlemelisiniz.
 
 
 Giriş Formu Bağlantısı .[#toc-login-form-link]
@@ -139,7 +139,7 @@ Giriş Formu Bağlantısı .[#toc-login-form-link]
 
 Hey, ama giriş sayfasına nasıl ulaşacağız? Onu işaret eden bir bağlantı yok. `@layout.latte` şablon dosyasına bir tane ekleyelim. Güzel bir yer bulmaya çalışın, en çok sevdiğiniz herhangi bir yer olabilir.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Home</a></li>
@@ -156,7 +156,7 @@ Kullanıcı henüz oturum açmamışsa, "Oturum aç" bağlantısını gösterece
 
 Oturumu kapatma eylemi şu şekilde görünür ve kullanıcıyı hemen yeniden yönlendirdiğimiz için bir görünüm şablonuna gerek yoktur.
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/tr/comments.texy b/quickstart/tr/comments.texy
index 46487d8f4c..214660744a 100644
--- a/quickstart/tr/comments.texy
+++ b/quickstart/tr/comments.texy
@@ -44,7 +44,7 @@ Yorum Yapma Formu .[#toc-form-for-commenting]
 
 Nette Framework *bileşenler* kavramına sahiptir. Bir **bileşen**, başka bir bileşene eklenebilen yeniden kullanılabilir bir sınıf veya kod parçasıdır. Sunucu bile bir bileşendir. Her bileşen, bileşen fabrikası kullanılarak oluşturulur. Öyleyse `PostPresenter` adresinde yorum formu fabrikasını tanımlayalım.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // Nette\Application\UI\Form anlamına gelir
@@ -67,7 +67,7 @@ Bunu biraz açıklayalım. İlk satır `Form` bileşeninin yeni bir örneğini o
 
 Form bileşeni bir sunucuda tanımlandıktan sonra, onu bir şablonda oluşturabiliriz (görüntüleyebiliriz). Bunu yapmak için, `{control}` etiketini yazı ayrıntısı şablonunun sonuna, `Post/show.latte` içine yerleştirin. Bileşenin adı `commentForm` olduğundan ( `createComponentCommentForm` yönteminin adından türetilmiştir), etiket aşağıdaki gibi görünecektir
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Post new comment</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 "Form başarıyla gönderildikten sonra, geçerli sunum yapan kişinin `commentFormSucceeded` yöntemini çağır" anlamına gelir. Bu yöntem henüz mevcut değil, bu yüzden onu oluşturalım.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ new metodunun bir argümanı vardır; bu argüman, bileşen fabrikası tarafınd
 
 Açıklanması gereken iki yöntem çağrısı daha vardır. Yönlendirme, kelimenin tam anlamıyla geçerli sayfaya yönlendirir. Form gönderildiğinde, geçerli olduğunda ve geri arama işlemi yapması gerekeni yaptığında bunu her seferinde yapmalısınız. Ayrıca, formu gönderdikten sonra sayfayı yeniden yönlendirdiğinizde, bazen tarayıcıda görebileceğiniz iyi bilinen `Would you like to submit the post data again?` mesajını görmezsiniz. (Genel olarak, `POST` yöntemiyle bir form gönderdikten sonra, kullanıcıyı her zaman bir `GET` eylemine yönlendirmelisiniz).
 
-`flashMessage`, kullanıcıyı bir işlemin sonucu hakkında bilgilendirmek içindir. Yönlendirme yaptığımız için, mesaj doğrudan şablona aktarılamaz ve işlenemez. Bu yüzden, onu saklayacak ve bir sonraki sayfa yüklemesinde kullanılabilir hale getirecek bu yöntem vardır. Flash mesajları varsayılan `app/Presenters/templates/@layout.latte` dosyasında oluşturulur ve aşağıdaki gibi görünür:
+`flashMessage`, kullanıcıyı bir işlemin sonucu hakkında bilgilendirmek içindir. Yönlendirme yaptığımız için, mesaj doğrudan şablona aktarılamaz ve işlenemez. Bu yüzden, onu saklayacak ve bir sonraki sayfa yüklemesinde kullanılabilir hale getirecek bu yöntem vardır. Flash mesajları varsayılan `app/UI/@layout.latte` dosyasında oluşturulur ve aşağıdaki gibi görünür:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer, tablolar arasındaki ilişkileri çözmek için yabanc
 
 Hatırlayabileceğiniz gibi, `$post` değişkenini `PostPresenter::renderShow()` adresindeki şablona aktardık ve şimdi `post_id` sütunu `$post->id` sütunumuza eşit olan tüm yorumları yinelemek istiyoruz. Bunu `$post->related('comments')` adresini çağırarak yapabilirsiniz. Bu kadar basit. Ortaya çıkan koda bakın.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 Ve şablon:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Comments</h2>
 
diff --git a/quickstart/tr/creating-posts.texy b/quickstart/tr/creating-posts.texy
index d15aa57f08..f64470ab9f 100644
--- a/quickstart/tr/creating-posts.texy
+++ b/quickstart/tr/creating-posts.texy
@@ -20,11 +20,11 @@ Daha sonra kimlik doğrulama da ekleyeceğiz ve yalnızca oturum açmış kullan
 Yeni Sunucu .[#toc-new-presenter]
 =================================
 
-Yeni sunucuya `EditPresenter` adını verin ve `app/Presenters/EditPresenter.php` adresine kaydedin. Ayrıca veritabanına bağlanması gerekir, bu nedenle burada yine bir veritabanı bağlantısı gerektirecek bir kurucu yazıyoruz:
+Yeni sunucuya `EditPresenter` adını verin ve `app/UI/Edit/` adresine kaydedin. Ayrıca veritabanına bağlanması gerekir, bu nedenle burada yine bir veritabanı bağlantısı gerektirecek bir kurucu yazıyoruz:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ Formlar ve bileşenler, yorumlar için destek eklediğimizde zaten ele alındı.
 
 Şimdi bu yöntemi `EditPresenter` adresine ekleyin:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ Yeni Gönderiyi Formdan Kaydetme .[#toc-saving-new-post-from-form]
 
 Bir işleyici yöntemi ekleyerek devam edin.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -88,7 +88,7 @@ Yeni Gönderi Oluşturma Sayfası .[#toc-page-for-creating-a-new-post]
 
 Sadece `Edit/create.latte` şablonunu oluşturalım:
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>New post</h1>
 
@@ -105,7 +105,7 @@ Gönderi Oluşturma Bağlantısı .[#toc-link-for-creating-posts]
 
 Muhtemelen `EditPresenter` adresine ve `create` eylemine nasıl bağlantı ekleyeceğinizi zaten biliyorsunuzdur. Deneyin bakalım.
 
-Sadece `app/Presenters/templates/Home/default.latte` dosyasına ekleyin:
+Sadece `app/UI/Home/default.latte` dosyasına ekleyin:
 
 ```latte
 <a n:href="Edit:create">Write new post</a>
@@ -119,12 +119,12 @@ Mevcut gönderileri düzenleme özelliğini de ekleyelim. Oldukça basit olacak
 
 `EditPresenter` adresine yeni bir `edit` sayfası ekleyeceğiz:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Post not found');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 Ve `Edit/edit.latte` şablonunu oluşturun:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Edit post</h1>
 
@@ -146,15 +146,15 @@ Ve `Edit/edit.latte` şablonunu oluşturun:
 
 Ve yeni bir gönderi ekleyebilecek (şimdi olduğu gibi) veya mevcut olanları düzenleyebilecek olan `postFormSucceeded` yöntemini güncelleyin:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-`postId` parametresi sağlandığında, bir gönderinin düzenlenmekte olduğu anlamına gelir. Böyle bir durumda, gönderinin gerçekten var olup olmadığını kontrol edeceğiz ve eğer varsa, veritabanında güncelleyeceğiz. `postId` parametresi sağlanmazsa, yeni bir yazı ekleneceği anlamına gelir.
+`id` parametresi sağlandığında, bir gönderinin düzenlenmekte olduğu anlamına gelir. Böyle bir durumda, gönderinin gerçekten var olup olmadığını kontrol edeceğiz ve eğer varsa, veritabanında güncelleyeceğiz. `id` parametresi sağlanmazsa, yeni bir yazı ekleneceği anlamına gelir.
 
-Peki `postId` nereden geliyor? `renderEdit` yöntemine aktarılan parametredir.
+Peki `id` nereden geliyor? `renderEdit` yöntemine aktarılan parametredir.
 
-Artık `app/Presenters/templates/Post/show.latte` şablonuna bir bağlantı ekleyebilirsiniz:
+Artık `app/UI/Post/show.latte` şablonuna bir bağlantı ekleyebilirsiniz:
 
 ```latte
 <a n:href="Edit:edit $post->id">Edit this post</a>
diff --git a/quickstart/tr/home-page.texy b/quickstart/tr/home-page.texy
index a6711306d3..b624989d2c 100644
--- a/quickstart/tr/home-page.texy
+++ b/quickstart/tr/home-page.texy
@@ -66,9 +66,9 @@ Veritabanına Bağlanma .[#toc-connecting-to-the-database]
 
 Şimdi, veritabanı oluşturulduğunda ve içinde bazı gönderilerimiz olduğunda, bunları yeni parlak sayfamızda görüntülemenin tam zamanıdır.
 
-İlk olarak, uygulamamıza hangi veritabanını kullanacağını söylememiz gerekir. Veritabanı bağlantı yapılandırması `config/local.neon` adresinde saklanır. DSN((Veri Kaynağı Adı)) bağlantısını ve kimlik bilgilerinizi ayarlayın. Bu şekilde görünmelidir:
+İlk olarak, uygulamamıza hangi veritabanını kullanacağını söylememiz gerekir. Veritabanı bağlantı yapılandırması `config/common.neon` adresinde saklanır. DSN((Veri Kaynağı Adı)) bağlantısını ve kimlik bilgilerinizi ayarlayın. Bu şekilde görünmelidir:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *enter user name*
@@ -78,20 +78,17 @@ database:
 .[note]
 Bu dosyayı düzenlerken girintilere dikkat edin. [NEON formatı |neon:format] hem boşlukları hem de sekmeleri kabul eder ancak ikisini birlikte kabul etmez! Web Projesindeki yapılandırma dosyası varsayılan olarak sekmeleri kullanır.
 
-Tüm yapılandırma `config/` adresinde `common.neon` ve `local.neon` dosyalarında saklanır. `common.neon` dosyası uygulamanın genel yapılandırmasını içerirken, `local.neon` dosyası yalnızca ortama özgü parametreleri (örneğin geliştirme ve üretim sunucusu arasındaki fark) içerir.
-
 
 Veritabanı Bağlantısının Enjekte Edilmesi .[#toc-injecting-the-database-connection]
 ===================================================================================
 
 Makaleleri listeleyecek olan `HomePresenter` sunucusunun bir veritabanı bağlantısına ihtiyacı vardır. Bunu almak için aşağıdaki gibi bir kurucu yazın:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ Veritabanından Gönderileri Yükleme .[#toc-loading-posts-from-the-database]
 
 Şimdi gönderileri veritabanından alalım ve HTML kodunu oluşturacak olan şablona aktaralım. İşte *render* metodu bunun içindir:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Sunucu artık `default` adlı bir görünüme veri aktaran bir `renderDefault()` render yöntemine sahiptir. Sunucu şablonları `app/Presenters/templates/{PresenterName}/{viewName}.latte` adresinde bulunabilir, bu nedenle bu durumda şablon `app/Presenters/templates/Home/default.latte` adresinde yer alacaktır. Şablonda, veritabanındaki gönderileri içeren `$posts` adlı bir değişken artık mevcuttur.
+Sunucu artık `default` adlı bir görünüme veri aktaran bir `renderDefault()` render yöntemine sahiptir. Sunucu şablonları `app/UI/{PresenterName}/{viewName}.latte` adresinde bulunabilir, bu nedenle bu durumda şablon `app/UI/Home/default.latte` adresinde yer alacaktır. Şablonda, veritabanındaki gönderileri içeren `$posts` adlı bir değişken artık mevcuttur.
 
 
 Şablon .[#toc-template]
@@ -128,9 +125,9 @@ Sunucu artık `default` adlı bir görünüme veri aktaran bir `renderDefault()`
 
 Tüm sayfa için genel bir şablon (üstbilgi, stil sayfaları, altbilgi, ... ile *düzen* olarak adlandırılır) ve ardından her görünüm için (örneğin blog yazılarının listesini görüntülemek için) düzen şablonunun bazı bölümlerini geçersiz kılabilen özel şablonlar vardır.
 
-Varsayılan olarak, düzen şablonu `templates/@layout.latte` adresinde bulunur:
+Varsayılan olarak, düzen şablonu `app/UI/@layout.latte` adresinde bulunur:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
@@ -138,7 +135,7 @@ Varsayılan olarak, düzen şablonu `templates/@layout.latte` adresinde bulunur:
 
 `{include content}` ana şablona `content` adında bir blok ekler. Bunu her görünümün şablonlarında tanımlayabilirsiniz. Bu durumda `Home/default.latte` dosyasını şu şekilde düzenleyeceğiz:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Hello World
 {/block}
@@ -148,7 +145,7 @@ Düzene eklenecek olan *içerik* [bloğunu |latte:tags#block] tanımlar. Tarayı
 
 Blog yazılarını görüntüleyelim - şablonu şu şekilde düzenleyeceğiz:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
@@ -166,7 +163,7 @@ Blog yazılarını görüntüleyelim - şablonu şu şekilde düzenleyeceğiz:
 
 Tarayıcınızı yenilediğinizde blog yazılarınızın listesini göreceksiniz. Liste çok süslü veya renkli değildir, bu nedenle `www/css/style.css` adresine biraz [parlak CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] eklemekten ve bir düzene bağlamaktan çekinmeyin:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ Tarayıcınızı yenilediğinizde blog yazılarınızın listesini göreceksiniz
 
 Bir şey daha var. Kodu biraz daha kısaltabilir ve böylece daha basit hale getirebiliriz. Latte etiketlerini* aşağıdaki gibi *n:attributes* ile değiştirebiliriz:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/tr/model.texy b/quickstart/tr/model.texy
index a0b3ddf58f..0987f01e56 100644
--- a/quickstart/tr/model.texy
+++ b/quickstart/tr/model.texy
@@ -36,9 +36,9 @@ Sınıfta veritabanı Explorer'ını geçiyoruz:[api:Nette\Database\Explorer]. B
 
 Düzenleyeceğimiz `HomePresenter` adresine geçeceğiz, böylece `Nette\Database\Explorer` bağımlılığından kurtulacağız ve bunun yerine yeni sınıfımıza yeni bir bağımlılık oluşturacağız.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/tr/single-post.texy b/quickstart/tr/single-post.texy
index eab3d7a9d1..7d88554b48 100644
--- a/quickstart/tr/single-post.texy
+++ b/quickstart/tr/single-post.texy
@@ -5,13 +5,13 @@ Tek Gönderi Sayfası
 Blogumuza, belirli bir blog gönderisinin içeriğini görüntüleyecek başka bir sayfa ekleyelim.
 
 
-Belirli bir blog gönderisini getirip şablona aktaracak yeni bir render yöntemi oluşturmamız gerekiyor. Bu görünümün `HomePresenter` adresinde olması hoş değil çünkü bu bir blog yazısı ile ilgili, ana sayfa ile değil. Bu nedenle, yeni bir `PostPresenter` sınıfı oluşturalım ve `app/Presenters` adresine yerleştirelim. Bir veritabanı bağlantısına ihtiyaç duyacaktır, bu nedenle *veritabanı enjeksiyonu* kodunu tekrar oraya koyun.
+Belirli bir blog gönderisini getirip şablona aktaracak yeni bir render yöntemi oluşturmamız gerekiyor. Bu görünümün `HomePresenter` adresinde olması hoş değil çünkü bu bir blog yazısı ile ilgili, ana sayfa ile değil. Bu nedenle, yeni bir `PostPresenter` sınıfı oluşturalım ve `app/UI/Post/` adresine yerleştirelim. Bir veritabanı bağlantısına ihtiyaç duyacaktır, bu nedenle *veritabanı enjeksiyonu* kodunu tekrar oraya koyun.
 
 `PostPresenter` bu şekilde görünmelidir:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Sunucumuz için doğru ad alanlarını `App\Presenters` ayarlamamız gerekir. Sunucu [eşlemesine |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] bağlıdır.
+Sunucumuz için doğru ad alanlarını `App\UI\Post` ayarlamamız gerekir. Sunucu [eşlemesine |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] bağlıdır.
 
 `renderShow` yöntemi tek bir bağımsız değişken gerektirir - görüntülenecek gönderinin kimliği. Ardından, gönderiyi veritabanından yükler ve sonucu şablona aktarır.
 
 `Home/default.latte` şablonunda `Post:show` eylemine bir bağlantı ekliyoruz:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ Sunucumuz için doğru ad alanlarını `App\Presenters` ayarlamamız gerekir. Su
 
 Aynı şeyi n:attribute kullanarak da kısaca yazabiliriz:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -63,7 +63,7 @@ Aynı şeyi n:attribute kullanarak da kısaca yazabiliriz:
 
 Bu içerikle `Post/show.latte` adresini oluşturacağız:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← back to posts list</a></p>
@@ -89,7 +89,7 @@ Dördüncü satır, blog yazısının *başlığını* bir `<h1>` Başlık. Aşi
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Basit bir ifadeyle, `title` adlı bir bloğu *yeniden tanımlar*. Bu blok *düzen şablonunda* (`/app/Presenters/templates/@layout.latte:11`) tanımlanmıştır ve OOP geçersiz kılmada olduğu gibi burada da geçersiz kılınır. Bu nedenle, sayfanın `<title>` görüntülenen gönderinin başlığını içerecektir. Sayfanın başlığını geçersiz kıldık ve tek ihtiyacımız olan `n:block="title"` idi. Harika, değil mi?
+Basit bir ifadeyle, `title` adlı bir bloğu *yeniden tanımlar*. Bu blok *düzen şablonunda* (`/app/UI/@layout.latte:11`) tanımlanmıştır ve OOP geçersiz kılmada olduğu gibi burada da geçersiz kılınır. Bu nedenle, sayfanın `<title>` görüntülenen gönderinin başlığını içerecektir. Sayfanın başlığını geçersiz kıldık ve tek ihtiyacımız olan `n:block="title"` idi. Harika, değil mi?
 
 Şablonun beşinci ve son satırında gönderinizin tüm içeriği görüntülenir.
 
@@ -97,14 +97,14 @@ Basit bir ifadeyle, `title` adlı bir bloğu *yeniden tanımlar*. Bu blok *düze
 Gönderi Kimliğini Kontrol Etme .[#toc-checking-post-id]
 =======================================================
 
-Birisi URL'yi değiştirir ve mevcut olmayan `postId` adresini eklerse ne olur? Kullanıcıya güzel bir "sayfa bulunamadı" hatası vermeliyiz. `PostPresenter` adresindeki render yöntemini güncelleyelim:
+Birisi URL'yi değiştirir ve mevcut olmayan `id` adresini eklerse ne olur? Kullanıcıya güzel bir "sayfa bulunamadı" hatası vermeliyiz. `PostPresenter` adresindeki render yöntemini güncelleyelim:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Post not found');
 	}
diff --git a/quickstart/uk/@home.texy b/quickstart/uk/@home.texy
index 3514fbacc0..916b207e10 100644
--- a/quickstart/uk/@home.texy
+++ b/quickstart/uk/@home.texy
@@ -7,7 +7,7 @@
 Після перших двох розділів у вас буде власний робочий блог, і ви будете готові публікувати свої чудові пости, хоча після завершення цих двох розділів функції будуть досить обмежені. Щоб зробити життя ваших користувачів приємнішим, ви також повинні прочитати наступні розділи і продовжувати вдосконалювати свій додаток.
 
 .[tip]
-Цей посібник передбачає, що ви заповнили документ " [Інсталяція |nette:installation] " і успішно налаштували свої інструменти.
+Цей посібник припускає, що ви заповнили [інсталяційний |nette:installation] документ і успішно налаштували ваш інструментарій. Також передбачається, що ви розумієте [об'єктно-орієнтоване програмування на PHP |nette:introduction-to-object-oriented-programming].
 
 Будь ласка, використовуйте PHP 8.1 або новішу версію. Ви можете знайти повну версію програми [на GitHub |https://github.com/nette-examples/quickstart/tree/v4.0].
 
@@ -45,9 +45,9 @@ http://localhost/nette-blog/www/
 /--pre
 <b>nette-blog/</b>
 ├── <b>app/</b>              ← каталог приложения
-│   ├── <b>Presenters/</b>   ← классы презентеров
-│   │   └── <b>templates/</b>← шаблоны
-│   ├── <b>Router/</b>       ← конфигурация адресов URL
+│   ├── <b>Core/</b>         ← основні необхідні класи
+│   ├── <b>UI/</b>           ← доповідачі, шаблони та ін.
+│   │   └── <b>Home/</b>     ← головний каталог доповідачів
 │   └── <b>Bootstrap.php</b> ← загрузочный класс Bootstrap
 ├── <b>bin/</b>              ← скрипты для командной строки
 ├── <b>config/</b>           ← конфигурационные файлы
@@ -67,7 +67,7 @@ http://localhost/nette-blog/www/
 Очищення .[#toc-cleanup]
 ========================
 
-Веб-проект містить сторінку привітання, яку ми можемо видалити - сміливо замініть вміст файлу `app/Presenters/templates/Home/default.latte` текстом `Hello world!`.
+Веб-проект містить сторінку привітання, яку ми можемо видалити - сміливо замініть вміст файлу `app/UI/Home/default.latte` текстом `Hello world!`.
 
 
 [* qs-hello.webp .{url:-} *]
@@ -76,9 +76,9 @@ http://localhost/nette-blog/www/
 Tracy (відладчик) .[#toc-tracy-debugger]
 ========================================
 
-Надзвичайно важливим інструментом для розробки є [відладчик під назвою Tracy |tracy:]. Спробуйте зробити кілька помилок у вашому файлі `app/Presenters/HomePresenter.php` (наприклад, видаліть фігурну дужку з визначення класу HomePresenter) і подивіться, що станеться. З'явиться сторінка з червоним екраном і зрозумілим описом помилки.
+Надзвичайно важливим інструментом для розробки є [відладчик під назвою Tracy |tracy:]. Спробуйте зробити кілька помилок у вашому файлі `app/UI/Home/HomePresenter.php` (наприклад, видаліть фігурну дужку з визначення класу HomePresenter) і подивіться, що станеться. З'явиться сторінка з червоним екраном і зрозумілим описом помилки.
 
-[* qs-tracy.webp .{url:-}(debugger screen) *]
+[* qs-tracy.avif .{url:-}(debugger screen) *]
 
 Tracy суттєво допоможе вам у пошуку помилок. Також зверніть увагу на плаваючу панель Tracy Bar у правому нижньому кутку, яка інформує вас про важливі дані під час виконання.
 
@@ -88,8 +88,7 @@ Tracy суттєво допоможе вам у пошуку помилок. Т
 
 ```php .{file:app/Bootstrap.php}
 ...
-$configurator->setDebugMode(false);
-$configurator->enableTracy(__DIR__ . '/../log');
+$this->configurator->setDebugMode(false);
 ...
 ```
 
diff --git a/quickstart/uk/authentication.texy b/quickstart/uk/authentication.texy
index f7c75c8cf7..52878997bf 100644
--- a/quickstart/uk/authentication.texy
+++ b/quickstart/uk/authentication.texy
@@ -28,9 +28,9 @@ Nette автоматично створить службу в контейнер
 
 Давайте почнемо з форми входу в систему. Ви вже знаєте, як працюють форми в презентері. Створіть `SignPresenter` і метод `createComponentSignInForm`. Це має виглядати таким чином:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Sign;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -60,9 +60,9 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 Шаблон .[#toc-template]
 -----------------------
 
-Форма відображатиметься в шаблоні `app/Presenters/templates/Sign/in.latte`.
+Форма відображатиметься в шаблоні `app/UI/Sign/in.latte`.
 
-```latte .{file:app/Presenters/templates/Sign/in.latte}
+```latte .{file:app/UI/Sign/in.latte}
 {block content}
 <h1 n:block=title>Войти</h1>
 
@@ -77,7 +77,7 @@ final class SignPresenter extends Nette\Application\UI\Presenter
 
 Обробник просто приймає ім'я користувача та пароль, які користувач ввів, і передає їх аутентифікатору. Після входу в систему ми перенаправимо вас на головну сторінку:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 private function signInFormSucceeded(Form $form, \stdClass $data): void
 {
 	try {
@@ -102,7 +102,7 @@ private function signInFormSucceeded(Form $form, \stdClass $data): void
 
 Створимо метод `startup()`, який запускається відразу на початку [життєвого циклу презентера |application:presenters#Life-Cycle-of-Presenter]. Це перенаправляє незареєстрованих користувачів на форму входу в систему.
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 public function startup(): void
 {
 	parent::startup();
@@ -117,7 +117,7 @@ public function startup(): void
 Приховуємо посилання .[#toc-hide-links]
 ---------------------------------------
 
-Неавторизований користувач більше не може бачити сторінки створення і редагування, але він все ще може бачити посилання, що вказують на них. Давайте сховаємо і їх. Одне з таких посилань міститься в `app/Presenters/templates/Home/default.latte`, і його має бути видно, тільки якщо користувач увійшов у систему.
+Неавторизований користувач більше не може бачити сторінки створення і редагування, але він все ще може бачити посилання, що вказують на них. Давайте сховаємо і їх. Одне з таких посилань міститься в `app/UI/Home/default.latte`, і його має бути видно, тільки якщо користувач увійшов у систему.
 
 Ми можемо приховати його за допомогою *n:атрибута* під назвою `n:if`. Якщо твердження всередині нього `false`, то весь тег `<a>` і його вміст не відображатимуться:
 
@@ -131,15 +131,15 @@ public function startup(): void
 {if $user->isLoggedIn()}<a n:href="Edit:create">Создать пост</a>{/if}
 ```
 
-Аналогічним чином слід приховати посилання редагування, розташоване в `app/Presenters/templates/Post/show.latte`.
+Аналогічним чином слід приховати посилання редагування, розташоване в `app/UI/Post/show.latte`.
 
 
 Посилання на форму входу .[#toc-login-form-link]
 ================================================
 
-Гей, але як нам потрапити на сторінку входу в систему? Немає посилання, що вказує на неї. Давайте додамо його у файл шаблону `app/Presenters/templates/@layout.latte`. Спробуйте знайти гарне місце, це може бути будь-яке місце, яке вам найбільше подобається.
+Гей, але як нам потрапити на сторінку входу в систему? Немає посилання, що вказує на неї. Давайте додамо його у файл шаблону `app/UI/@layout.latte`. Спробуйте знайти гарне місце, це може бути будь-яке місце, яке вам найбільше подобається.
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 <ul class="navig">
 	<li><a n:href="Home:">Главная</a></li>
@@ -156,7 +156,7 @@ public function startup(): void
 
 Дія виходу з системи виглядає наступним чином, і оскільки ми перенаправляємо користувача негайно, немає необхідності в шаблоні подання:
 
-```php .{file:app/Presenters/SignPresenter.php}
+```php .{file:app/UI/Sign/SignPresenter.php}
 public function actionOut(): void
 {
 	$this->getUser()->logout();
diff --git a/quickstart/uk/comments.texy b/quickstart/uk/comments.texy
index ce0001ba88..7fb670496e 100644
--- a/quickstart/uk/comments.texy
+++ b/quickstart/uk/comments.texy
@@ -44,7 +44,7 @@ CREATE TABLE `comments` (
 
 У Nette є поняття *компоненти*. **Компонент** - це багаторазово використовуваний клас або фрагмент коду, який може бути приєднаний до іншого компонента. Навіть презентер є компонентом. Кожен компонент створюється за допомогою фабрики компонентів. Отже, давайте визначимо фабрику форми коментарів у `PostPresenter`.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 protected function createComponentCommentForm(): Form
 {
 	$form = new Form; // означає Nette\Application\UI\Form
@@ -65,9 +65,9 @@ protected function createComponentCommentForm(): Form
 
 Давайте трохи пояснимо це. Перший рядок створює новий екземпляр компонента `Form`. Методи, які вказані нижче, розміщують HTML-елементи *input* всередині форми. `->addText` буде відображатися як `<input type=text name=name>`, с `<label>Ваше имя:</label>`. Як ви вже здогадалися, `->addTextArea` прикріплює `<textarea>`, а `->addSubmit` додає `<input type=submit>`. Подібних методів більше, але це все, що вам потрібно знати просто зараз. Ви можете [дізнатися більше в документації |forms:].
 
-Після того як компонент форми визначено в презентері, ми можемо відобразити його в шаблоні. Для цього помістіть тег `{control}` в кінець шаблону деталізації поста в `app/Presenters/templates/Post/show.latte`. Оскільки ім'я компонента - `commentForm` (воно походить від назви методу `createComponentCommentForm`), тег матиме такий вигляд:
+Після того як компонент форми визначено в презентері, ми можемо відобразити його в шаблоні. Для цього помістіть тег `{control}` в кінець шаблону деталізації поста в `app/UI/Post/show.latte`. Оскільки ім'я компонента - `commentForm` (воно походить від назви методу `createComponentCommentForm`), тег матиме такий вигляд:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Оставить комментарий</h2>
 
@@ -90,13 +90,13 @@ $form->onSuccess[] = $this->commentFormSucceeded(...);
 
 Це означає "після успішного надсилання форми викликати метод `commentFormSucceeded` поточного презентера". Цього методу ще не існує, тому давайте створимо його.
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 private function commentFormSucceeded(\stdClass $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
 	$this->database->table('comments')->insert([
-		'post_id' => $postId,
+		'post_id' => $id,
 		'name' => $data->name,
 		'email' => $data->email,
 		'content' => $data->content,
@@ -113,7 +113,7 @@ private function commentFormSucceeded(\stdClass $data): void
 
 Необхідно пояснити ще два виклики методу. `$this->redirect('this')` буквально перенаправляє на поточну сторінку. Ви повинні робити це кожного разу, коли форма відправлена, дійсна, і операція зворотного виклику зробила те, що повинна була зробити. Крім того, коли ви перенаправляєте сторінку після надсилання форми, ви не побачите добре відомого повідомлення `Вы хотите отправить данные сообщения снова?`, яке іноді можна побачити в браузері. (Загалом, після надсилання форми методом `POST`, ви завжди повинні перенаправляти користувача на дію `GET`).
 
-`$this->flashMessage` призначений для інформування користувача про результат деякої операції. Оскільки ми перенаправляємо, повідомлення не може бути безпосередньо передано в шаблон і відображено. Тому існує метод, який збереже його і зробить доступним при наступному завантаженні сторінки. Флеш-повідомлення відображаються в стандартному файлі `app/Presenters/templates/@layout.latte`, і виглядають вони так:
+`$this->flashMessage` призначений для інформування користувача про результат деякої операції. Оскільки ми перенаправляємо, повідомлення не може бути безпосередньо передано в шаблон і відображено. Тому існує метод, який збереже його і зробить доступним при наступному завантаженні сторінки. Флеш-повідомлення відображаються в стандартному файлі `app/UI/@layout.latte`, і виглядають вони так:
 
 ```latte
 <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
@@ -133,8 +133,8 @@ Nette Database Explorer використовує зовнішні ключі д
 
 Як ви пам'ятаєте, ми передали змінну `$post` шаблону в `PostPresenter::renderShow()` і тепер хочемо перебрати всі коментарі, у яких стовпець `post_id` дорівнює нашому `$post->id`. Ви можете зробити це, викликавши `$post->related('comments')`. Це так просто. Подивіться на отриманий код.
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	...
 	$this->template->post = $post;
@@ -144,7 +144,7 @@ public function renderShow(int $postId): void
 
 У шаблоні:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 ...
 <h2>Комментарии</h2>
 
diff --git a/quickstart/uk/creating-posts.texy b/quickstart/uk/creating-posts.texy
index 14476f772e..b74174d402 100644
--- a/quickstart/uk/creating-posts.texy
+++ b/quickstart/uk/creating-posts.texy
@@ -20,11 +20,11 @@
 Новий презентер .[#toc-new-presenter]
 =====================================
 
-Назвіть новий презентер `EditPresenter` і збережіть його в `app/Presenters/EditPresenter.php`. Йому також необхідно під'єднатися до бази даних, тому тут ми знову пишемо конструктор, який потребуватиме під'єднання до бази даних:
+Назвіть новий презентер `EditPresenter` і збережіть його в `app/UI/Edit/`. Йому також необхідно під'єднатися до бази даних, тому тут ми знову пишемо конструктор, який потребуватиме під'єднання до бази даних:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Edit;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -46,7 +46,7 @@ final class EditPresenter extends Nette\Application\UI\Presenter
 
 Тепер додайте цей метод у `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 protected function createComponentPostForm(): Form
 {
 	$form = new Form;
@@ -68,7 +68,7 @@ protected function createComponentPostForm(): Form
 
 Додамо метод обробника:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
 	$post = $this->database
@@ -86,9 +86,9 @@ private function postFormSucceeded(array $data): void
 Сторінка для створення нового поста .[#toc-page-for-creating-a-new-post]
 ========================================================================
 
-Давайте просто створимо шаблон (`app/Presenters/templates/Edit/create.latte`):
+Давайте просто створимо шаблон (`app/UI/Edit/create.latte`):
 
-```latte .{file:app/Presenters/templates/Edit/create.latte}
+```latte .{file:app/UI/Edit/create.latte}
 {block content}
 <h1>Новый пост</h1>
 
@@ -105,7 +105,7 @@ private function postFormSucceeded(array $data): void
 
 Ви, ймовірно, вже знаєте, як додати посилання на `EditPresenter` та його дію `create`. Спробуйте.
 
-Просто додайте у файл `app/Presenters/templates/Home/default.latte`:
+Просто додайте у файл `app/UI/Home/default.latte`:
 
 ```latte
 <a n:href="Edit:create">Создать пост</a>
@@ -119,12 +119,12 @@ private function postFormSucceeded(array $data): void
 
 Ми додамо нову сторінку `edit` до `EditPresenter`:
 
-```php .{file:app/Presenters/EditPresenter.php}
-public function renderEdit(int $postId): void
+```php .{file:app/UI/Edit/EditPresenter.php}
+public function renderEdit(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 
 	if (!$post) {
 		$this->error('Пост не найден');
@@ -137,7 +137,7 @@ public function renderEdit(int $postId): void
 
 І створіть шаблон `Edit/edit.latte`:
 
-```latte .{file:app/Presenters/templates/Edit/edit.latte}
+```latte .{file:app/UI/Edit/edit.latte}
 {block content}
 <h1>Редактирование поста</h1>
 
@@ -146,15 +146,15 @@ public function renderEdit(int $postId): void
 
 І поновіть метод `postFormSucceeded`, який зможе або додавати новий пост (як зараз), або редагувати наявні:
 
-```php .{file:app/Presenters/EditPresenter.php}
+```php .{file:app/UI/Edit/EditPresenter.php}
 private function postFormSucceeded(array $data): void
 {
-	$postId = $this->getParameter('postId');
+	$id = $this->getParameter('id');
 
-	if ($postId) {
+	if ($id) {
 		$post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 		$post->update($data);
 
 	} else {
@@ -168,11 +168,11 @@ private function postFormSucceeded(array $data): void
 }
 ```
 
-Якщо вказано параметр `postId`, це означає, що пост редагується. У цьому випадку ми перевіримо, чи дійсно пост існує, і якщо так, то оновимо його в базі даних. Якщо `postId` не вказано, це означає, що буде додано новий пост.
+Якщо вказано параметр `id`, це означає, що пост редагується. У цьому випадку ми перевіримо, чи дійсно пост існує, і якщо так, то оновимо його в базі даних. Якщо `id` не вказано, це означає, що буде додано новий пост.
 
-Але звідки береться `postId`? Це параметр, що передається методу `renderEdit`.
+Але звідки береться `id`? Це параметр, що передається методу `renderEdit`.
 
-Тепер ви можете додати посилання для зміни поста в шаблон `app/Presenters/templates/Post/show.latte`:
+Тепер ви можете додати посилання для зміни поста в шаблон `app/UI/Post/show.latte`:
 
 ```latte
 <a n:href="Edit:edit $post->id">Изменить пост</a>
diff --git a/quickstart/uk/home-page.texy b/quickstart/uk/home-page.texy
index d93ad3e9ca..c7a2c42d20 100644
--- a/quickstart/uk/home-page.texy
+++ b/quickstart/uk/home-page.texy
@@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
 
 Тепер, коли база даних створена і в ній є кілька постів, саме час відобразити їх на нашій новій блискучій сторінці.
 
-По-перше, нам потрібно повідомити нашому додатку, яку базу даних використовувати. Конфігурація підключення до бази даних зберігається у файлі `config/local.neon`. Встановіть з'єднання DSN((Ім'я джерела даних)) і свої облікові дані. Це має виглядати так:
+По-перше, нам потрібно повідомити нашому додатку, яку базу даних використовувати. Конфігурація підключення до бази даних зберігається у файлі `config/common.neon`. Встановіть з'єднання DSN((Ім'я джерела даних)) і свої облікові дані. Це має виглядати так:
 
-```neon .{file:config/local.neon}
+```neon .{file:config/common.neon}
 database:
 	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
 	user: *укажите здесь имя пользователя*
@@ -78,20 +78,17 @@ database:
 .[note]
 Пам'ятайте про відступи під час редагування цього файлу. [Формат NEON |neon:format] приймає і пробіли, і табуляцію, але не те й інше разом! У файлі конфігурації у веб-проекті за замовчуванням використовується табуляція.
 
-Уся конфігурація зберігається в `config/` у файлах `common.neon` і `local.neon`. Файл `common.neon` містить глобальну конфігурацію додатка, а `local.neon` містить тільки параметри, специфічні для середовища (наприклад, різниця між сервером розробки та робочим сервером).
-
 
 Впровадження підключення до бази даних .[#toc-injecting-the-database-connection]
 ================================================================================
 
-Презентер (розташований у `app/Presenters/HomePresenter.php`), який буде перераховувати статті, потребує підключення до бази даних. Для цього змініть конструктор таким чином:
+Презентер (розташований у `app/UI/Home/HomePresenter.php`), який буде перераховувати статті, потребує підключення до бази даних. Для цього змініть конструктор таким чином:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use Nette;
-use Nette\Application\UI\Form;
 
 final class HomePresenter extends Nette\Application\UI\Presenter
 {
@@ -110,7 +107,7 @@ final class HomePresenter extends Nette\Application\UI\Presenter
 
 Тепер давайте витягнемо пости з бази даних і передамо їх у шаблон, який потім відобразить HTML-код. Для цього і призначений так званий метод *render*:
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 public function renderDefault(): void
 {
 	$this->template->posts = $this->database
@@ -120,7 +117,7 @@ public function renderDefault(): void
 }
 ```
 
-Тепер у презентері є один метод рендерингу `renderDefault()`, який передає дані в подання під назвою `default`. Шаблони презентера можна знайти в `app/Presenters/templates/{PresenterName}/{viewName}.latte`, тому в даному випадку шаблон буде розташований в `app/Presenters/templates/Home/default.latte`. У шаблоні тепер доступна змінна `$posts`, яка містить пости з бази даних.
+Тепер у презентері є один метод рендерингу `renderDefault()`, який передає дані в подання під назвою `default`. Шаблони презентера можна знайти в `app/UI/{PresenterName}/{viewName}.latte`, тому в даному випадку шаблон буде розташований в `app/UI/Home/default.latte`. У шаблоні тепер доступна змінна `$posts`, яка містить пости з бази даних.
 
 
 Шаблон .[#toc-template]
@@ -128,17 +125,17 @@ public function renderDefault(): void
 
 Існує загальний шаблон для всієї сторінки (називається *layout* (макет), із заголовком, таблицями стилів, нижнім колонтитулом тощо), а також специфічні шаблони для кожного виду (наприклад, для відображення списку записів блогу), які можуть перевизначати деякі частини шаблону макета.
 
-За замовчуванням шаблон макета розташовується у файлі `app/Presenters/templates/@layout.latte`, який містить:
+За замовчуванням шаблон макета розташовується у файлі `app/UI/@layout.latte`, який містить:
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 ...
 {include content}
 ...
 ```
 
-`{include content}` вставляє блок з ім'ям `content` в основний шаблон. Ви можете визначити його в шаблонах кожного подання. У нашому випадку ми відредагуємо файл `app/Presenters/templates/Home/default.latte` таким чином:
+`{include content}` вставляє блок з ім'ям `content` в основний шаблон. Ви можете визначити його в шаблонах кожного подання. У нашому випадку ми відредагуємо файл `app/UI/Home/default.latte` таким чином:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	Привет, мир!
 {/block}
@@ -148,7 +145,7 @@ public function renderDefault(): void
 
 Давайте відобразимо записи блогу - для цього відредагуємо шаблон таким чином:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1 n:block="title">Мой блог</h1>
 
@@ -166,7 +163,7 @@ public function renderDefault(): void
 
 Якщо ви оновите браузер, ви побачите список записів вашого блогу. Список не дуже вигадливий або барвистий, тому не соромтеся додати трохи [блискучого CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] у `www/css/style.css`, а потім вставте посилання на цей файл у макет (файл `@layout.latte`):
 
-```latte .{file:app/Presenters/templates/@layout.latte}
+```latte .{file:app/UI/@layout.latte}
 	...
 	<link rel="stylesheet" href="{$basePath}/css/style.css">
 </head>
@@ -179,7 +176,7 @@ public function renderDefault(): void
 
 І ще одне. Ми можемо зробити код трохи коротшим і, отже, простішим. Ми можемо замінити *теги Latte* на *n:attributes* таким чином:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 {block content}
 	<h1>My blog</h1>
 
diff --git a/quickstart/uk/model.texy b/quickstart/uk/model.texy
index 68b42474ba..c665c6fec0 100644
--- a/quickstart/uk/model.texy
+++ b/quickstart/uk/model.texy
@@ -36,9 +36,9 @@ final class PostFacade
 
 Перейдемо до файлу `HomePresenter.php`, який ми відредагуємо так, щоб позбутися залежності від `Nette\Database\Explorer`, замінивши її новою залежністю від нашого створеного класу.
 
-```php .{file:app/Presenters/HomePresenter.php}
+```php .{file:app/UI/Home/HomePresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Home;
 
 use App\Model\PostFacade;
 use Nette;
diff --git a/quickstart/uk/single-post.texy b/quickstart/uk/single-post.texy
index 2602e035ab..1434782539 100644
--- a/quickstart/uk/single-post.texy
+++ b/quickstart/uk/single-post.texy
@@ -5,13 +5,13 @@
 Давайте додамо в наш блог ще одну сторінку, на якій відображатиметься вміст одного конкретного запису блогу.
 
 
-Нам потрібно створити новий метод render, який буде отримувати один конкретний запис блогу і передавати його в шаблон. Мати це подання в `HomePresenter` не дуже приємно, тому що йдеться про запис у блозі, а не про головну сторінку. Отже, давайте створимо новий клас `PostPresenter` і помістимо його в `app/Presenters`. Йому знадобиться з'єднання з базою даних, тому знову помістіть туди код *впровадження залежності*.
+Нам потрібно створити новий метод render, який буде отримувати один конкретний запис блогу і передавати його в шаблон. Мати це подання в `HomePresenter` не дуже приємно, тому що йдеться про запис у блозі, а не про головну сторінку. Отже, давайте створимо новий клас `PostPresenter` і помістимо його в `app/UI/Post/`. Йому знадобиться з'єднання з базою даних, тому знову помістіть туди код *впровадження залежності*.
 
 `PostPresenter` має виглядати наступним чином:
 
-```php .{file:app/Presenters/PostPresenter.php}
+```php .{file:app/UI/Post/PostPresenter.php}
 <?php
-namespace App\Presenters;
+namespace App\UI\Post;
 
 use Nette;
 use Nette\Application\UI\Form;
@@ -23,22 +23,22 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 	) {
 	}
 
-	public function renderShow(int $postId): void
+	public function renderShow(int $id): void
 	{
 		$this->template->post = $this->database
 			->table('posts')
-			->get($postId);
+			->get($id);
 	}
 }
 ```
 
-Ми повинні встановити правильний простір імен `App\Presenters` для нашого презентера. Це залежить від [mapping presenter |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
+Ми повинні встановити правильний простір імен `App\UI\Post` для нашого презентера. Це залежить від [mapping presenter |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7].
 
 Метод `renderShow` вимагає один аргумент - ID відображуваного поста. Потім він завантажує цей пост із бази даних і передає результат у шаблон.
 
 У шаблоні `Home/default.latte` ми додаємо посилання на дію `Post:show`:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
 ...
@@ -49,7 +49,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 Те ж саме ми можемо написати коротко, використовуючи n:attribute:
 
-```latte .{file:app/Presenters/templates/Home/default.latte}
+```latte .{file:app/UI/Home/default.latte}
 ...
 <h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
 ...
@@ -59,11 +59,11 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 
 
 
-Шаблон для дії `Post:show` ще не існує. Ми можемо відкрити посилання на цей пост. [Tracy |tracy:] покаже помилку про те, що `app/Presenters/templates/Post/show.latte` не існує. Якщо ви бачите будь-який інший звіт про помилку, ймовірно, вам потрібно увімкнути mod_rewrite у вашому веб-сервері.
+Шаблон для дії `Post:show` ще не існує. Ми можемо відкрити посилання на цей пост. [Tracy |tracy:] покаже помилку про те, що `app/UI/Post/show.latte` не існує. Якщо ви бачите будь-який інший звіт про помилку, ймовірно, вам потрібно увімкнути mod_rewrite у вашому веб-сервері.
 
 Тому ми створимо `Post/show.latte` з таким змістом:
 
-```latte .{file:app/Presenters/templates/Post/show.latte}
+```latte .{file:app/UI/Post/show.latte}
 {block content}
 
 <p><a n:href="Home:default">← вернуться к списку постов</a></p>
@@ -89,7 +89,7 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 {block title}<h1>{$post->title}</h1>{/block}
 ```
 
-Простіше кажучи, він *перевизначає* блок під назвою `title`. Блок визначено в *шаблоні макета* (`/app/Presenters/templates/@layout.latte:11`) і, як і у випадку з перевизначенням ООП, він перевизначається тут. Тому `<title>` сторінки буде містити заголовок відображуваного поста. Ми перевизначили заголовок сторінки, і все, що нам було потрібно, це `n:block="title"`. Чудово, чи не так?
+Простіше кажучи, він *перевизначає* блок під назвою `title`. Блок визначено в *шаблоні макета* (`/app/UI/@layout.latte:11`) і, як і у випадку з перевизначенням ООП, він перевизначається тут. Тому `<title>` сторінки буде містити заголовок відображуваного поста. Ми перевизначили заголовок сторінки, і все, що нам було потрібно, це `n:block="title"`. Чудово, чи не так?
 
 П'ятий і останній рядок шаблону відображає повний зміст вашого поста.
 
@@ -97,14 +97,14 @@ final class PostPresenter extends Nette\Application\UI\Presenter
 Перевірка ідентифікатора поста .[#toc-checking-post-id]
 =======================================================
 
-Що станеться, якщо хтось змінить URL і вставить неіснуючий `postId`? Ми повинні надати користувачеві красиву сторінку помилки "сторінку не знайдено". Давайте оновимо метод `render` у файлі `PostPresenter.php`:
+Що станеться, якщо хтось змінить URL і вставить неіснуючий `id`? Ми повинні надати користувачеві красиву сторінку помилки "сторінку не знайдено". Давайте оновимо метод `render` у файлі `PostPresenter.php`:
 
-```php .{file:app/Presenters/PostPresenter.php}
-public function renderShow(int $postId): void
+```php .{file:app/UI/Post/PostPresenter.php}
+public function renderShow(int $id): void
 {
 	$post = $this->database
 		->table('posts')
-		->get($postId);
+		->get($id);
 	if (!$post) {
 		$this->error('Страница не найдена!');
 	}
diff --git a/robot-loader/bg/@home.texy b/robot-loader/bg/@home.texy
index 2fdf709047..88b4382fe2 100644
--- a/robot-loader/bg/@home.texy
+++ b/robot-loader/bg/@home.texy
@@ -1,70 +1,82 @@
-RobotLoader: клас Autoloader
-****************************
+RobotLoader: Автоматично зареждане на класове
+*********************************************
 
 <div class=perex>
 
-RobotLoader е инструмент, който осигурява автоматично зареждане на класове за цялото приложение, включително библиотеки на трети страни.
+RobotLoader е инструмент, който ви дава възможност за автоматизирано зареждане на класове за цялото ви приложение, включително библиотеки на трети страни.
 
-- да се отървете от всички `require`
-- зареждат се само необходимите скриптове
-- не изисква строги конвенции за именуване на директориите или файловете.
+- Елиминирайте всички изявления `require`
+- Ще бъдат заредени само необходимите скриптове
+- Не изисква строги конвенции за именуване на директории или файлове
+- Изключително бързо
+- Няма ръчни актуализации на кеша, всичко се изпълнява автоматично
+- Зряла, стабилна и широко използвана библиотека
 
 </div>
 
-Така че можем да забравим за известните блокове от код:
+Така можем да забравим за тези познати блокове код:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
-Инсталиране на .[#toc-installation]
------------------------------------
+Инсталация .[#toc-installation]
+-------------------------------
 
-Изтеглете и инсталирайте пакета, като използвате [Composer|best-practices:composer]:
+Можете да изтеглите RobotLoader като [един самостоятелен файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], който да включите с помощта на `require` в скрипта си, и веднага да се насладите на удобно автоматично зареждане за цялото приложение.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Ако изграждате приложение с помощта на [Composer |best-practices:composer], можете да го инсталирате чрез:
 
 ```shell
 composer require nette/robot-loader
 ```
 
 
-Използване на .[#toc-usage]
----------------------------
+Употреба .[#toc-usage]
+----------------------
 
-По същия начин, по който Google претърсва и индексира уебсайтове, [RobotLoader |api:Nette\Loaders\RobotLoader] преглежда всички PHP скриптове и записва кои класове и интерфейси са открити в тях. След това тези записи се кешират и се използват при всяко следващо търсене. Трябва само да посочите кои директории да се индексират и къде да се съхранява кешът:
+Подобно на начина, по който роботът на Google обхожда и индексира уеб страници, [RobotLoader |api:Nette\Loaders\RobotLoader] преминава през всички PHP скриптове и отбелязва кои класове, интерфейси, черти и енуми е намерил. След това той съхранява резултатите в кеш за използване при следващи заявки. Необходимо е само да посочите кои директории трябва да прегледа и къде да се съхранява кешът:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// директории, които да бъдат индексирани от RobotLoader (включително поддиректории)
+// Директории, които RobotLoader да индексира (включително поддиректории)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// използвайте директория 'temp' за кеша
+// Задаване на кеширане в директорията 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Стартиране на RobotLoader
+$loader->register(); // Активиране на RobotLoader
 ```
 
-И това е всичко. Отсега нататък не е необходимо да използвате `require`. Чудесно, нали?
+И това е всичко, от този момент нататък не е необходимо да използваме `require`. Страхотно!
 
-Когато RobotLoader срещне дублирано име на клас по време на индексирането, той хвърля изключение и ви уведомява за това. RobotLoader също така автоматично актуализира кеша си, когато трябва да зареди клас, който не познава. Препоръчваме да забраните това на производствени сървъри, вижте раздел [Кеширане |#Кэширование].
+Ако RobotLoader срещне дублиращо се име на клас по време на индексирането, той ще хвърли изключение и ще ви уведоми. RobotLoader също така автоматично актуализира кеша, когато трябва да зареди непознат клас. Препоръчваме да изключите тази функция на производствени сървъри, вижте " [Кеширане" |#Caching].
 
-Ако искате RobotLoader да пропусне някои директории, използвайте `$loader->excludeDirectory('temp')` (може да се извика многократно или да се предадат няколко директории).
+Ако искате RobotLoader да прескача определени директории, използвайте `$loader->excludeDirectory('temp')` (може да се извика многократно или да се предадат няколко директории).
 
-По подразбиране RobotLoader съобщава за грешки в PHP файловете, като хвърля изключение `ParseError`. Това може да бъде деактивирано с помощта на `$loader->reportParseErrors(false)`.
+По подразбиране RobotLoader съобщава за грешки в PHP файлове, като хвърля изключение `ParseError`. Това може да се потисне с помощта на `$loader->reportParseErrors(false)`.
 
 
-Приложение Nette .[#toc-nette-application]
+Нетно приложение .[#toc-nette-application]
 ------------------------------------------
 
-В рамките на приложението Nette, където `$configurator` се използва в `Bootstrap.php`, можете да конфигурирате RobotLoader по този начин:
+Вътре в Nette Application, където `$configurator` се използва в `Bootstrap.php`, можете да настроите RobotLoader по този начин:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -73,30 +85,32 @@ $configurator->createRobotLoader()
 ```
 
 
-PHP файлов анализатор .[#toc-php-files-analyzer]
-------------------------------------------------
+Анализатор на PHP файлове .[#toc-php-files-analyzer]
+----------------------------------------------------
 
-RobotLoader може да се използва и само за намиране на класове, интерфейси и черти в PHP файлове **без да се използва функцията за автоматично зареждане:
+RobotLoader може да се използва и само за намиране на класове, интерфейси, черти и енуми в PHP файлове, без да се използва функцията за автоматично зареждане:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Търсене на директории за класове / интерфейси / черти
+// Търсене на директории за класове/интерфейси/характеристики/енуми
 $loader->rebuild();
 
-//връща масив от двойки клас => име на файл
+// Връща масив от двойки клас => име на файл
 $res = $loader->getIndexedClasses();
 ```
 
-Дори и при тази употреба можете да използвате кеша. В резултат на това немодифицираните файлове няма да бъдат анализирани отново при повторно сканиране:
+Дори при такава употреба можете да използвате кеширане. Това гарантира, че непроменените файлове няма да бъдат сканирани отново:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Задаване на кеширане в директорията 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Сканиране на директории с кеш
+// Претърсване на директориите с помощта на кеша
 $loader->refresh();
 
 // Връща масив от двойки клас => име на файл
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Кеширане .[#toc-caching]
 ------------------------
 
-RobotLoader е много бърз, защото използва кеша интелигентно.
+RobotLoader е много бърз, защото умело използва кеширане.
 
-Когато разработвате с него, почти не забелязвате, че работи във фонов режим. Той постоянно актуализира кеша, защото знае, че класовете и файловете могат да бъдат създавани, изтривани, преименувани и т.н. И не сканира повторно немодифицирани файлове.
+По време на разработката почти не забелязвате, че той работи във фонов режим. Той непрекъснато обновява кеша си, като се има предвид, че класовете и файловете могат да бъдат създавани, изтривани, преименувани и т.н. И не сканира отново непроменените файлове.
 
-От друга страна, когато се използва в производствен сървър, препоръчваме да забраните актуализирането на кеша с `$loader->setAutoRefresh(false)` (това се прави автоматично в приложението Nette), тъй като файловете не се модифицират. В същото време трябва да **изчистите кеша**, когато качвате нова версия на хоста.
+В производствен сървър, от друга страна, препоръчваме да изключите обновяването на кеша с помощта на `$loader->setAutoRefresh(false)` (в приложение на Nette това става автоматично), тъй като файловете не се променят. В същото време е необходимо **изчистване на кеша** при качване на нова версия на хостинг.
 
-Разбира се, първоначалното сканиране на файловете, когато кешът все още не съществува, може да отнеме няколко секунди при по-големи приложения. RobotLoader разполага с вградена защита срещу "препускане на кеша":https://en.wikipedia.org/wiki/Cache_stampede.
-Това е ситуация, в която производствен сървър получава голям брой едновременни заявки и тъй като кешът на RobotLoader все още не съществува, всички те започват да сканират за файлове. Това увеличава натоварването на процесора и файловата система.
-За щастие RobotLoader работи по такъв начин, че ако има няколко едновременни заявки, само първата нишка индексира файловете, създава кеш, а останалите изчакват, след което използват кеша.
+Първоначалното сканиране на файловете, когато кешът все още не съществува, естествено може да отнеме известно време за по-големи приложения. RobotLoader разполага с вградена превенция срещу "прецакване на кеша:https://en.wikipedia.org/wiki/Cache_stampede".
+Това е ситуация, при която голям брой едновременни заявки на производствен сървър ще задействат RobotLoader и тъй като кешът все още не съществува, всички те ще започнат да сканират файлове, което ще претовари сървъра.
+За щастие RobotLoader работи по такъв начин, че само първата нишка индексира файловете, създава кеша, а останалите изчакват и след това използват кеша.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Днес Composer може да се използва за [автоматично зареждане в |best-practices:composer#Autoloading] съответствие с PSR-4. Казано по-просто, това е система, в която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, т.е. `App\Router\RouterFactory` е във файла `/path/to/App/Router/RouterFactory.php`.
+В днешно време можете да използвате [Composer за автоматично зареждане |best-practices:composer#autoloading], като се придържате към PSR-4. Казано по-просто, това е система, при която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, например `App\Core\RouterFactory` ще бъде във файла `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader не е обвързан с никаква фиксирана структура, така че е полезен в ситуации, в които не искате структурата на директориите да бъде представена от пространствата от имена на PHP или когато разработвате приложение, което в миналото не е използвало тези конвенции. Можете също така да използвате и двете зареждащи устройства заедно.
+RobotLoader не е обвързан с никаква фиксирана структура, така че е полезен в ситуации, в които не искате структурата на директорията да е проектирана точно като пространствата от имена на PHP, или когато разработвате приложение, което исторически не използва такива конвенции. Възможно е също така да се използват и двата зареждащи механизма заедно.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/cs/@home.texy b/robot-loader/cs/@home.texy
index 13acd5b3e3..f27cb7beed 100644
--- a/robot-loader/cs/@home.texy
+++ b/robot-loader/cs/@home.texy
@@ -8,6 +8,9 @@ RobotLoader je nástroj, který vám zajistí komfort automatického načítán
 - zbavíme se všech `require`
 - budou se načítat jen potřebné skripty
 - nevyžaduje striktní konvence pojmenování adresářů či souborů
+- extrémně rychlé
+- žádné ruční aktualizace mezipaměti, vše probíhá automaticky
+- zralá, stabilní a široce používaná knihovna
 
 </div>
 
@@ -24,7 +27,16 @@ require_once 'Utils/Paginator.php';
 Instalace
 ---------
 
-Knihovnu stáhěte a nainstalujete pomocí nástroje [Composer|best-practices:composer]:
+RobotLoader si můžete stáhnout jako [jeden samostatný soubor `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], který vložíte pomocí `require` do svého skriptu a hned máte k dispozici komfortní autoloading pro celou aplikaci.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+// ...
+```
+
+Pokud stavíte aplikaci využívající [Composer|best-practices:composer], můžete jej nainstalovat pomocí něj:
 
 ```shell
 composer require nette/robot-loader
@@ -34,7 +46,7 @@ composer require nette/robot-loader
 Použití
 -------
 
-Podobně, jako Google robot prochází a indexuje webové stránky, tak i [RobotLoader |api:Nette\Loaders\RobotLoader] prochází všechny PHP skripty a zaznamenává si, které třídy, rozhraní a traity v nich našel. Výsledky bádání si poté uloží do cache a použije při dalším požadavku. Stačí tedy určit, které adresáře má procházet a kam ukládat cache:
+Podobně, jako Google robot prochází a indexuje webové stránky, tak i [RobotLoader |api:Nette\Loaders\RobotLoader] prochází všechny PHP skripty a zaznamenává si, které třídy, rozhraní, traity a enumy v nich našel. Výsledky bádání si poté uloží do cache a použije při dalším požadavku. Stačí tedy určit, které adresáře má procházet a kam ukládat cache:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
@@ -76,13 +88,13 @@ $configurator->createRobotLoader()
 Analyzátor PHP souborů
 ----------------------
 
-RobotLoader lze také použít čistě k vyhledávání tříd, rozhraní a trait v souborech PHP **bez** využívání funkce autoloadingu:
+RobotLoader lze také použít čistě k vyhledávání tříd, rozhraní, trait a enumů v souborech PHP **bez** využívání funkce autoloadingu:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// prohledá adresáře na třídy / rozhraní / traity
+// prohledá adresáře na třídy / rozhraní / traity / enumy
 $loader->rebuild();
 
 // vrací pole dvojic třída => název souboru
@@ -94,6 +106,8 @@ I při takovém použití můžete využít cache. Díky tomu při opětovném s
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// nastavíme cachování do adresáře 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
 // prohledá adresáře s využitím cache
@@ -121,7 +135,7 @@ Naštěstí RobotLoader funguje tak, že při více souběžných požadavcích
 PSR-4
 -----
 
-Dnes lze pro [autoloading používat Composer|best-practices:composer#autoloading] při dodržení PSR-4. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a názvům souborů, tedy např. `App\Router\RouterFactory` bude v souboru `/path/to/App/Router/RouterFactory.php`.
+Dnes lze pro [autoloading používat Composer|best-practices:composer#autoloading] při dodržení PSR-4. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a názvům souborů, tedy např. `App\Core\RouterFactory` bude v souboru `/path/to/App/Core/RouterFactory.php`.
 
 RobotLoader není s žádnou pevnou strukturou spjat, proto se hodí v situacích, kdy vám úplně nevyhovuje mít stejně navrženou adresářovou strukturu jako jmenné prostory v PHP, nebo když vyvíjíte aplikaci, která historicky takové konvence nevyužívá. Je možné také používat oba loadery dohromady.
 
diff --git a/robot-loader/de/@home.texy b/robot-loader/de/@home.texy
index 71dda5a3cb..03f0cb400a 100644
--- a/robot-loader/de/@home.texy
+++ b/robot-loader/de/@home.texy
@@ -5,26 +5,38 @@ RobotLoader: Klasse Autoloading
 
 RobotLoader ist ein Tool, das Ihnen den Komfort des automatischen Ladens von Klassen für Ihre gesamte Anwendung einschließlich der Bibliotheken von Drittanbietern bietet.
 
-- alle loswerden `require`
-- nur notwendige Skripte werden geladen
-- erfordert keine strengen Verzeichnis- oder Dateinamenskonventionen
+- Eliminieren Sie alle `require` Anweisungen
+- Nur notwendige Skripte werden geladen
+- Erfordert keine strengen Namenskonventionen für Verzeichnisse oder Dateien
+- Äußerst schnell
+- Keine manuellen Cache-Updates, alles läuft automatisch ab
+- Ausgereifte, stabile und weit verbreitete Bibliothek
 
 </div>
 
-Wir können also diese berühmten Codeblöcke vergessen:
+Wir können also diese vertrauten Codeblöcke vergessen:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
-Installation .[#toc-installation]
----------------------------------
+Einrichtung .[#toc-installation]
+--------------------------------
+
+Sie können RobotLoader als [einzelne Standalone-Datei `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] herunterladen, die Sie mit `require` in Ihr Skript einbinden, und sofort das komfortable automatische Laden für die gesamte Anwendung nutzen.
 
-Laden Sie das Paket herunter und installieren Sie es mit [Composer |best-practices:composer]:
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Wenn Sie eine Anwendung mit [Composer |best-practices:composer] erstellen, können Sie ihn über installieren:
 
 ```shell
 composer require nette/robot-loader
@@ -34,37 +46,37 @@ composer require nette/robot-loader
 Verwendung .[#toc-usage]
 ------------------------
 
-Ähnlich wie der Google-Roboter Webseiten crawlt und indiziert, crawlt [RobotLoader |api:Nette\Loaders\RobotLoader] alle PHP-Skripte und zeichnet auf, welche Klassen und Schnittstellen in ihnen gefunden wurden. Diese Aufzeichnungen werden dann im Cache gespeichert und bei allen nachfolgenden Anfragen verwendet. Sie müssen nur angeben, welche Verzeichnisse indiziert werden sollen und wo der Cache gespeichert werden soll:
+Ähnlich wie der Google-Roboter Webseiten crawlt und indiziert, geht der [RobotLoader |api:Nette\Loaders\RobotLoader] durch alle PHP-Skripte und notiert, welche Klassen, Schnittstellen, Traits und Enums er gefunden hat. Anschließend speichert er die Ergebnisse im Cache, um sie bei nachfolgenden Anfragen zu verwenden. Sie müssen nur angeben, welche Verzeichnisse er durchsuchen soll und wo der Cache gespeichert werden soll:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// Verzeichnisse, die von RobotLoader indiziert werden sollen (einschließlich Unterverzeichnisse)
+// Verzeichnisse, die RobotLoader indizieren soll (einschließlich Unterverzeichnisse)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// 'temp' Verzeichnis für Cache verwenden
+// Zwischenspeicherung auf das Verzeichnis "temp" einstellen
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Starten Sie den RobotLoader
+$loader->register(); // RobotLoader aktivieren
 ```
 
-Und das ist alles. Von nun an brauchen Sie `require` nicht mehr zu verwenden. Toll, nicht wahr?
+Und das war's, von nun an brauchen wir `require` nicht mehr zu verwenden. Großartig!
 
-Wenn RobotLoader bei der Indizierung auf doppelte Klassennamen stößt, löst er eine Ausnahme aus und informiert Sie darüber. RobotLoader aktualisiert auch automatisch den Cache, wenn er eine Klasse laden muss, die er nicht kennt. Wir empfehlen, dies auf Produktionsservern zu deaktivieren, siehe [Caching |#Caching].
+Wenn RobotLoader während der Indizierung auf einen doppelten Klassennamen stößt, wird eine Ausnahme ausgelöst und Sie werden benachrichtigt. RobotLoader aktualisiert auch automatisch den Cache, wenn er eine unbekannte Klasse laden muss. Wir empfehlen, dies auf Produktionsservern zu deaktivieren, siehe [Caching |#Caching].
 
-Wenn Sie möchten, dass RobotLoader einige Verzeichnisse überspringt, verwenden Sie `$loader->excludeDirectory('temp')` (es kann mehrfach aufgerufen werden oder Sie können mehrere Verzeichnisse übergeben).
+Wenn Sie möchten, dass RobotLoader bestimmte Verzeichnisse überspringt, verwenden Sie `$loader->excludeDirectory('temp')` (kann mehrfach aufgerufen werden oder mehrere Verzeichnisse übergeben).
 
-Standardmäßig meldet RobotLoader Fehler in PHP-Dateien, indem er die Ausnahme `ParseError` auslöst. Sie kann über `$loader->reportParseErrors(false)` deaktiviert werden.
+Standardmäßig meldet RobotLoader Fehler in PHP-Dateien, indem er eine `ParseError` Exception auslöst. Dies kann mit `$loader->reportParseErrors(false)` unterdrückt werden.
 
 
 Nette Anwendung .[#toc-nette-application]
 -----------------------------------------
 
-Innerhalb der Nette-Anwendung, wo `$configurator` in `Bootstrap.php` verwendet wird, können Sie RobotLoader auf diese Weise einrichten:
+Innerhalb von Nette Application, wo `$configurator` in `Bootstrap.php` verwendet wird, können Sie RobotLoader auf diese Weise einrichten:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,54 +88,56 @@ $configurator->createRobotLoader()
 PHP-Dateianalysator .[#toc-php-files-analyzer]
 ----------------------------------------------
 
-RobotLoader kann auch verwendet werden, um Klassen, Interfaces und Traits in PHP-Dateien zu finden **ohne** die Autoloading-Funktion zu verwenden:
+RobotLoader kann auch nur zum Auffinden von Klassen, Interfaces, Traits und Enums in PHP-Dateien **ohne** Verwendung der Autoloading-Funktion verwendet werden:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Durchsucht Verzeichnisse nach Klassen / Schnittstellen / Traits
+// Durchsucht Verzeichnisse nach Klassen/Schnittstellen/Traits/Enums
 $loader->rebuild();
 
-// Gibt Array von Klasse => Dateinamenpaaren zurück
+// Gibt ein Array von Klasse => Dateinamenpaaren zurück
 $res = $loader->getIndexedClasses();
 ```
 
-Auch bei einer solchen Verwendung können Sie den Cache nutzen. Dadurch werden unveränderte Dateien beim erneuten Scannen nicht wiederholt analysiert:
+Auch bei einer solchen Verwendung können Sie das Caching nutzen. Dadurch wird sichergestellt, dass unveränderte Dateien nicht erneut gescannt werden:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Zwischenspeicherung auf das Verzeichnis 'temp' einstellen
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Scannt Verzeichnisse mit Hilfe eines Caches
+// Scannt Verzeichnisse unter Verwendung des Caches
 $loader->refresh();
 
-// Rückgabe eines Arrays von Klasse => Dateinamenpaaren
+// Gibt ein Array von Klasse => Dateinamenpaaren zurück
 $res = $loader->getIndexedClasses();
 ```
 
 
-Caching .[#toc-caching]
------------------------
+Zwischenspeichern .[#toc-caching]
+---------------------------------
 
-RobotLoader ist sehr schnell, weil er den Cache geschickt nutzt.
+RobotLoader ist sehr schnell, weil er geschickt die Zwischenspeicherung nutzt.
 
-Wenn Sie mit ihm entwickeln, bemerken Sie praktisch nicht, dass er im Hintergrund läuft. Der Cache wird ständig aktualisiert, da er weiß, dass Klassen und Dateien erstellt, gelöscht, umbenannt usw. werden können. Und es scannt nicht wiederholt unveränderte Dateien.
+Während der Entwicklung bemerken Sie kaum, dass er im Hintergrund läuft. Der Cache wird ständig aktualisiert, da Klassen und Dateien erstellt, gelöscht, umbenannt usw. werden können. Und er scannt unveränderte Dateien nicht erneut.
 
-Beim Einsatz auf einem Produktionsserver empfiehlt es sich hingegen, die Cache-Aktualisierung mit `$loader->setAutoRefresh(false)` zu deaktivieren (dies geschieht automatisch in der Nette-Anwendung), da sich die Dateien nicht ändern. Gleichzeitig ist es notwendig, den Cache zu **leeren**, wenn eine neue Version auf das Hosting hochgeladen wird.
+Auf einem Produktionsserver hingegen empfehlen wir, die Cache-Aktualisierung mit `$loader->setAutoRefresh(false)` zu deaktivieren (in einer Nette-Anwendung geschieht dies automatisch), da sich die Dateien nicht ändern. Gleichzeitig ist es notwendig, den Cache zu **leeren**, wenn eine neue Version zum Hosting hochgeladen wird.
 
-Natürlich kann das anfängliche Scannen von Dateien, wenn der Cache noch nicht vorhanden ist, bei größeren Anwendungen einige Sekunden dauern. RobotLoader verfügt über einen eingebauten Schutz gegen "Cache-Stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-Dabei handelt es sich um eine Situation, in der der Produktionsserver eine große Anzahl gleichzeitiger Anfragen erhält, und da der Cache von RobotLoader noch nicht vorhanden ist, würden alle mit dem Scannen der Dateien beginnen. Dies führt zu einer hohen CPU- und Dateisystemauslastung.
-Glücklicherweise funktioniert RobotLoader so, dass bei mehreren gleichzeitigen Anfragen nur der erste Thread die Dateien indiziert und einen Cache erstellt, die anderen warten und verwenden dann den Cache.
+Das anfängliche Scannen der Dateien, wenn der Cache noch nicht vorhanden ist, kann bei größeren Anwendungen natürlich einen Moment dauern. RobotLoader hat einen eingebauten Schutz gegen "Cache-Stampede":https://en.wikipedia.org/wiki/Cache_stampede.
+Dies ist eine Situation, in der eine große Anzahl gleichzeitiger Anfragen auf einem Produktionsserver RobotLoader auslösen würde, und da der Cache noch nicht existiert, würden sie alle mit dem Scannen von Dateien beginnen, was den Server überlasten würde.
+Glücklicherweise arbeitet RobotLoader so, dass nur der erste Thread die Dateien indiziert und den Cache erstellt, während die anderen warten und dann den Cache verwenden.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Heute kann Composer für das [Autoloading |best-practices:composer#autoloading] gemäß PSR-4 verwendet werden. Einfach gesagt handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, d.h. `App\Router\RouterFactory` befindet sich in der Datei `/path/to/App/Router/RouterFactory.php`.
+Heutzutage können Sie [Composer für das automatische Laden |best-practices:composer#autoloading] unter Einhaltung von PSR-4 verwenden. Einfach ausgedrückt, handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, z. B. `App\Core\RouterFactory` in der Datei `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader ist nicht an eine feste Struktur gebunden und ist daher in Situationen nützlich, in denen die Verzeichnisstruktur in PHP nicht als Namespaces ausgelegt ist, oder wenn Sie eine Anwendung entwickeln, die solche Konventionen historisch nicht verwendet hat. Es ist auch möglich, beide Loader zusammen zu verwenden.
+RobotLoader ist nicht an eine feste Struktur gebunden, so dass es in Situationen nützlich ist, in denen Sie die Verzeichnisstruktur nicht genau wie die PHP-Namensräume gestalten wollen, oder wenn Sie eine Anwendung entwickeln, die historisch gesehen keine solchen Konventionen verwendet. Es ist auch möglich, beide Lader zusammen zu verwenden.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/el/@home.texy b/robot-loader/el/@home.texy
index 4f037f2c0e..c24a52d1a0 100644
--- a/robot-loader/el/@home.texy
+++ b/robot-loader/el/@home.texy
@@ -5,26 +5,38 @@ RobotLoader: Αυτόματη φόρτωση κλάσης
 
 Το RobotLoader είναι ένα εργαλείο που σας δίνει την άνεση της αυτοματοποιημένης φόρτωσης κλάσεων για ολόκληρη την εφαρμογή σας, συμπεριλαμβανομένων των βιβλιοθηκών τρίτων κατασκευαστών.
 
-- απαλλαγείτε από όλα `require`
-- φορτώνονται μόνο τα απαραίτητα σενάρια
-- δεν απαιτεί αυστηρές συμβάσεις ονοματοδοσίας καταλόγων ή αρχείων
+- Εξαλείψτε όλες τις δηλώσεις `require`
+- Θα φορτώνονται μόνο τα απαραίτητα σενάρια
+- Δεν απαιτεί αυστηρές συμβάσεις ονοματοδοσίας για καταλόγους ή αρχεία
+- Εξαιρετικά γρήγορο
+- Καμία χειροκίνητη ενημέρωση της προσωρινής μνήμης, όλα εκτελούνται αυτόματα
+- Ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη
 
 </div>
 
-Μπορούμε λοιπόν να ξεχάσουμε αυτά τα περίφημα μπλοκ κώδικα:
+Έτσι, μπορούμε να ξεχάσουμε αυτά τα γνωστά μπλοκ κώδικα:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Εγκατάσταση .[#toc-installation]
 --------------------------------
 
-Κατεβάστε και εγκαταστήστε το πακέτο χρησιμοποιώντας το [Composer |best-practices:composer]:
+Μπορείτε να κατεβάσετε το RobotLoader ως ένα μεμονωμένο [αρχείο `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], το οποίο θα συμπεριλάβετε χρησιμοποιώντας το `require` στο σενάριό σας και θα απολαύσετε αμέσως άνετη αυτόματη φόρτωση για ολόκληρη την εφαρμογή.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Αν κατασκευάζετε μια εφαρμογή χρησιμοποιώντας το [Composer |best-practices:composer], μπορείτε να το εγκαταστήσετε μέσω:
 
 ```shell
 composer require nette/robot-loader
@@ -34,27 +46,27 @@ composer require nette/robot-loader
 Χρήση .[#toc-usage]
 -------------------
 
-Όπως το ρομπότ της Google ανιχνεύει και ευρετηριάζει ιστότοπους, το [RobotLoader |api:Nette\Loaders\RobotLoader] ανιχνεύει όλα τα σενάρια PHP και καταγράφει ποιες κλάσεις και διεπαφές βρέθηκαν σε αυτά. Αυτές οι εγγραφές αποθηκεύονται στη συνέχεια στην κρυφή μνήμη και χρησιμοποιούνται κατά τη διάρκεια όλων των επόμενων αιτήσεων. Απλά πρέπει να καθορίσετε ποιοι κατάλογοι θα ευρετηριαστούν και πού θα αποθηκευτεί η κρυφή μνήμη:
+Παρόμοια με τον τρόπο με τον οποίο το ρομπότ της Google ανιχνεύει και ευρετηριάζει ιστοσελίδες, ο [RobotLoader |api:Nette\Loaders\RobotLoader] περνάει από όλα τα σενάρια PHP και σημειώνει ποιες κλάσεις, διεπαφές, γνωρίσματα και enums βρήκε. Στη συνέχεια αποθηκεύει τα αποτελέσματα στην κρυφή μνήμη για χρήση σε επόμενες αιτήσεις. Απλά πρέπει να καθορίσετε ποιους καταλόγους θα πρέπει να περάσει και πού θα αποθηκεύσει την κρυφή μνήμη:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// κατάλογοι που θα ευρετηριαστεί από το RobotLoader (συμπεριλαμβανομένων των υποκαταλόγων)
+// Κατάλογοι για τον RobotLoader για ευρετηρίαση (συμπεριλαμβανομένων των υποκαταλόγων)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// χρήση του καταλόγου 'temp' για την κρυφή μνήμη
+// Ορίστε την προσωρινή αποθήκευση στον κατάλογο 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Εκτέλεση του RobotLoader
+$loader->register(); // Ενεργοποίηση του RobotLoader
 ```
 
-Και αυτό είναι όλο. Από εδώ και στο εξής, δεν χρειάζεται να χρησιμοποιείτε το `require`. Υπέροχα, έτσι δεν είναι;
+Και αυτό είναι όλο, από εδώ και πέρα, δεν χρειάζεται να χρησιμοποιήσουμε το `require`. Φοβερό!
 
-Όταν το RobotLoader συναντά διπλότυπο όνομα κλάσης κατά τη διάρκεια της ευρετηρίασης, πετάει μια εξαίρεση και σας ενημερώνει σχετικά. Ο RobotLoader ενημερώνει επίσης αυτόματα την κρυφή μνήμη όταν πρέπει να φορτώσει μια κλάση που δεν γνωρίζει. Συνιστούμε να το απενεργοποιήσετε αυτό στους διακομιστές παραγωγής, δείτε την ενότητα [Caching |#Caching].
+Εάν το RobotLoader συναντήσει ένα διπλότυπο όνομα κλάσης κατά τη διάρκεια της ευρετηρίασης, θα πετάξει μια εξαίρεση και θα σας ειδοποιήσει. Ο RobotLoader ενημερώνει επίσης αυτόματα την κρυφή μνήμη όταν χρειάζεται να φορτώσει μια άγνωστη κλάση. Συνιστούμε να το απενεργοποιήσετε αυτό στους διακομιστές παραγωγής, δείτε την ενότητα [Caching |#Caching].
 
-Αν θέλετε ο RobotLoader να παραλείψει κάποιους καταλόγους, χρησιμοποιήστε το `$loader->excludeDirectory('temp')` (μπορεί να κληθεί πολλές φορές ή μπορείτε να περάσετε πολλούς καταλόγους).
+Αν θέλετε το RobotLoader να παραλείπει ορισμένους καταλόγους, χρησιμοποιήστε το `$loader->excludeDirectory('temp')` (μπορεί να κληθεί πολλές φορές ή να περάσει πολλούς καταλόγους).
 
-Από προεπιλογή, ο RobotLoader αναφέρει σφάλματα σε αρχεία PHP με την εμφάνιση εξαιρέσεων `ParseError`. Μπορεί να απενεργοποιηθεί μέσω του `$loader->reportParseErrors(false)`.
+Από προεπιλογή, το RobotLoader αναφέρει σφάλματα σε αρχεία PHP πετώντας μια εξαίρεση `ParseError`. Αυτό μπορεί να καταστραφεί με τη χρήση του `$loader->reportParseErrors(false)`.
 
 
 Εφαρμογή Nette .[#toc-nette-application]
@@ -64,7 +76,7 @@ $loader->register(); // Εκτέλεση του RobotLoader
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -73,33 +85,35 @@ $configurator->createRobotLoader()
 ```
 
 
-PHP Files Analyzer .[#toc-php-files-analyzer]
----------------------------------------------
+Αναλυτής αρχείων PHP .[#toc-php-files-analyzer]
+-----------------------------------------------
 
-Το RobotLoader μπορεί επίσης να χρησιμοποιηθεί καθαρά για την εύρεση κλάσεων, διεπαφών και χαρακτηριστικών σε αρχεία PHP **χωρίς** να χρησιμοποιεί τη δυνατότητα αυτόματης φόρτωσης:
+Το RobotLoader μπορεί επίσης να χρησιμοποιηθεί καθαρά για την εύρεση κλάσεων, διεπαφών, χαρακτηριστικών και enums σε αρχεία PHP **χωρίς** τη χρήση της λειτουργίας αυτόματης φόρτωσης:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Σαρώνει καταλόγους για κλάσεις / διεπαφές / γνωρίσματα
+// Σαρώνει καταλόγους για κλάσεις/διεπαφές/traits/enums
 $loader->rebuild();
 
-// Επιστρέφει πίνακα με ζεύγη κλάσεων => ονόματα αρχείων
+// Επιστρέφει έναν πίνακα από ζεύγη κλάσεων => ονόματα αρχείων
 $res = $loader->getIndexedClasses();
 ```
 
-Ακόμα και με μια τέτοια χρήση, μπορείτε να χρησιμοποιήσετε την κρυφή μνήμη. Ως αποτέλεσμα, τα μη τροποποιημένα αρχεία δεν θα αναλύονται επανειλημμένα κατά την εκ νέου σάρωση:
+Ακόμα και με μια τέτοια χρήση, μπορείτε να χρησιμοποιήσετε την προσωρινή αποθήκευση. Αυτό διασφαλίζει ότι τα αμετάβλητα αρχεία δεν θα σαρωθούν εκ νέου:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Ορίστε την προσωρινή αποθήκευση στον κατάλογο 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Σαρώνει καταλόγους χρησιμοποιώντας μια κρυφή μνήμη
+// Σαρώνει καταλόγους χρησιμοποιώντας την κρυφή μνήμη
 $loader->refresh();
 
-// Επιστρέφει πίνακα ζευγών κλάσης => όνομα αρχείου
+// Επιστρέφει έναν πίνακα από ζεύγη κλάσης => όνομα αρχείου
 $res = $loader->getIndexedClasses();
 ```
 
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Caching .[#toc-caching]
 -----------------------
 
-Το RobotLoader είναι πολύ γρήγορο επειδή χρησιμοποιεί έξυπνα την κρυφή μνήμη.
+Το RobotLoader είναι πολύ γρήγορο επειδή χρησιμοποιεί έξυπνα την προσωρινή αποθήκευση.
 
-Όταν αναπτύσσετε με αυτό, δεν έχετε σχεδόν καμία ιδέα ότι εκτελείται στο παρασκήνιο. Ενημερώνει συνεχώς την κρυφή μνήμη επειδή γνωρίζει ότι κλάσεις και αρχεία μπορούν να δημιουργηθούν, να διαγραφούν, να μετονομαστούν κ.λπ. Και δεν σαρώνει επανειλημμένα μη τροποποιημένα αρχεία.
+Κατά τη διάρκεια της ανάπτυξης, δύσκολα θα παρατηρήσετε ότι εκτελείται στο παρασκήνιο. Ενημερώνει συνεχώς την κρυφή μνήμη του, λαμβάνοντας υπόψη ότι κλάσεις και αρχεία μπορούν να δημιουργηθούν, να διαγραφούν, να μετονομαστούν κ.λπ. Και δεν πραγματοποιεί εκ νέου σάρωση αμετάβλητων αρχείων.
 
-Όταν χρησιμοποιείται σε έναν διακομιστή παραγωγής, από την άλλη πλευρά, συνιστούμε να απενεργοποιήσετε την ενημέρωση της κρυφής μνήμης χρησιμοποιώντας το `$loader->setAutoRefresh(false)` (αυτό γίνεται αυτόματα στην εφαρμογή Nette), επειδή τα αρχεία δεν αλλάζουν. Ταυτόχρονα, είναι απαραίτητο να **καθαρίσετε την προσωρινή μνήμη cache** όταν ανεβάζετε μια νέα έκδοση στη φιλοξενία.
+Σε έναν διακομιστή παραγωγής, από την άλλη πλευρά, συνιστούμε να απενεργοποιήσετε τις ενημερώσεις της προσωρινής μνήμης με τη χρήση του `$loader->setAutoRefresh(false)` (σε μια εφαρμογή Nette, αυτό συμβαίνει αυτόματα), επειδή τα αρχεία δεν αλλάζουν. Ταυτόχρονα, είναι απαραίτητο να **καθαρίσετε την προσωρινή μνήμη cache** όταν ανεβάζετε μια νέα έκδοση στη φιλοξενία.
 
-Φυσικά, η αρχική σάρωση των αρχείων, όταν η προσωρινή μνήμη δεν υπάρχει ήδη, μπορεί να διαρκέσει μερικά δευτερόλεπτα για μεγαλύτερες εφαρμογές. Το RobotLoader διαθέτει ενσωματωμένη πρόληψη κατά του "αφηνιασμού της κρυφής μνήμης":https://en.wikipedia.org/wiki/Cache_stampede.
-Πρόκειται για μια κατάσταση κατά την οποία ο διακομιστής παραγωγής λαμβάνει μεγάλο αριθμό ταυτόχρονων αιτήσεων και επειδή η προσωρινή μνήμη cache του RobotLoader δεν υπάρχει ακόμη, θα ξεκινούσαν όλες να σαρώνουν τα αρχεία. Πράγμα που αυξάνει τη χρήση της CPU και του συστήματος αρχείων.
-Ευτυχώς, το RobotLoader λειτουργεί με τέτοιο τρόπο ώστε για πολλαπλές ταυτόχρονες αιτήσεις, μόνο το πρώτο νήμα ευρετηριάζει τα αρχεία, δημιουργεί μια κρυφή μνήμη, οι υπόλοιποι περιμένουν και στη συνέχεια χρησιμοποιούν την κρυφή μνήμη.
+Η αρχική σάρωση των αρχείων, όταν η κρυφή μνήμη δεν υπάρχει ακόμα, μπορεί φυσικά να πάρει λίγο χρόνο για μεγαλύτερες εφαρμογές. Το RobotLoader έχει ενσωματωμένη πρόληψη κατά της "αδημονία της cache":https://en.wikipedia.org/wiki/Cache_stampede.
+Πρόκειται για μια κατάσταση όπου ένας μεγάλος αριθμός ταυτόχρονων αιτήσεων σε έναν διακομιστή παραγωγής θα ενεργοποιούσε το RobotLoader και, εφόσον η προσωρινή μνήμη δεν υπάρχει ακόμη, θα άρχιζαν όλες να σαρώνουν αρχεία, γεγονός που θα υπερφόρτωνε τον διακομιστή.
+Ευτυχώς, το RobotLoader λειτουργεί με τέτοιο τρόπο ώστε μόνο το πρώτο νήμα να ευρετηριάζει τα αρχεία, να δημιουργεί την κρυφή μνήμη και τα υπόλοιπα να περιμένουν και στη συνέχεια να χρησιμοποιούν την κρυφή μνήμη.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Σήμερα, το Composer μπορεί να χρησιμοποιηθεί για [αυτόματη φόρτωση |best-practices:composer#autoloading] σύμφωνα με το PSR-4. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και των ονομάτων των αρχείων, δηλαδή το `App\Router\RouterFactory` βρίσκεται στο αρχείο `/path/to/App/Router/RouterFactory.php`.
+Σήμερα, μπορείτε να χρησιμοποιήσετε το [Composer για αυτόματη φόρτωση |best-practices:composer#autoloading] τηρώντας το PSR-4. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και τα ονόματα των αρχείων, π.χ. το `App\Core\RouterFactory` θα βρίσκεται στο αρχείο `/path/to/App/Core/RouterFactory.php`.
 
-Το RobotLoader δεν συνδέεται με καμία σταθερή δομή, επομένως, είναι χρήσιμο σε περιπτώσεις όπου δεν σας βολεύει να έχετε τη δομή καταλόγου σχεδιασμένη ως namespaces στην PHP, ή όταν αναπτύσσετε μια εφαρμογή που ιστορικά δεν έχει χρησιμοποιήσει τέτοιες συμβάσεις. Είναι επίσης δυνατό να χρησιμοποιήσετε και τους δύο φορτωτές μαζί.
+Το RobotLoader δεν δεσμεύεται από καμία σταθερή δομή, οπότε είναι χρήσιμο σε περιπτώσεις όπου δεν θέλετε να έχετε τη δομή καταλόγου σχεδιασμένη ακριβώς όπως τα namespaces της PHP, ή όταν αναπτύσσετε μια εφαρμογή που ιστορικά δεν χρησιμοποιεί τέτοιες συμβάσεις. Είναι επίσης δυνατό να χρησιμοποιήσετε και τους δύο φορτωτές μαζί.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/en/@home.texy b/robot-loader/en/@home.texy
index 028013bf86..4a779fcfd0 100644
--- a/robot-loader/en/@home.texy
+++ b/robot-loader/en/@home.texy
@@ -5,13 +5,16 @@ RobotLoader: Class Autoloading
 
 RobotLoader is a tool that gives you comfort of automated class loading for your entire application including third-party libraries.
 
-- get rid of all `require`
-- only necessary scripts are loaded
-- does not require strict directory or file naming conventions
+- Eliminate all `require` statements
+- Only necessary scripts will be loaded
+- Doesn't require strict naming conventions for directories or files
+- Extremely fast
+- No manual cache updates, everything runs automatically
+- Mature, stable and widely used library
 
 </div>
 
-So we can forget about those famous code blocks:
+Thus, we can forget about these familiar code blocks:
 
 ```php
 require_once 'Utils/Page.php';
@@ -24,7 +27,16 @@ require_once 'Utils/Paginator.php';
 Installation
 ------------
 
-Download and install the package using [Composer|best-practices:composer]:
+You can download RobotLoader as a [single standalone file `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], which you include using `require` in your script, and instantly enjoy comfortable autoloading for the entire application.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+// ...
+```
+
+If you're building an application using [Composer|best-practices:composer], you can install it via:
 
 ```shell
 composer require nette/robot-loader
@@ -34,33 +46,33 @@ composer require nette/robot-loader
 Usage
 -----
 
-Like the Google robot crawls and indexes websites, [RobotLoader |api:Nette\Loaders\RobotLoader] crawls all PHP scripts and records what classes and interfaces were found in them. These records are then saved in cache and used during all subsequent requests. You just need to specify what directories to index and where to save the cache:
+Similar to how the Google robot crawls and indexes web pages, the [RobotLoader |api:Nette\Loaders\RobotLoader] goes through all PHP scripts and notes which classes, interfaces, traits and enums it found. It then stores the results in cache for use in subsequent requests. You just need to specify which directories it should go through and where to store the cache:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// directories to be indexed by RobotLoader (including subdirectories)
+// Directories for RobotLoader to index (including subdirectories)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// use 'temp' directory for cache
+// Set caching to the 'temp' directory
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Run the RobotLoader
+$loader->register(); // Activate RobotLoader
 ```
 
-And that's all. From now on, you don't need to use `require`. Great, isn't it?
+And that's it, from this point on, we don't need to use `require`. Awesome!
 
-When RobotLoader encounters duplicate class name during indexing, it throws an exception and informs you about it. RobotLoader also automatically updates the cache when it has to load a class it doesn't know. We recommend disabling this on production servers, see [#Caching].
+If RobotLoader encounters a duplicate class name during indexing, it will throw an exception and notify you. RobotLoader also automatically updates the cache when it needs to load an unknown class. We recommend turning this off on production servers, see [#Caching].
 
-If you want RobotLoader to skip some directories, use `$loader->excludeDirectory('temp')` (it can be called multiple times or you can pass multiple directories).
+If you want RobotLoader to skip certain directories, use `$loader->excludeDirectory('temp')` (can be called multiple times or pass multiple directories).
 
-By default, RobotLoader reports errors in PHP files by throwing exception `ParseError`. It can be disabled via `$loader->reportParseErrors(false)`.
+By default, RobotLoader reports errors in PHP files by throwing a `ParseError` exception. This can be suppressed using `$loader->reportParseErrors(false)`.
 
 
 Nette Application
 -----------------
 
-Inside Nette application, where `$configurator` is used in `Bootstrap.php`, you can setup RobotLoader this way:
+Inside Nette Application, where `$configurator` is used in `Bootstrap.php`, you can setup RobotLoader this way:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
@@ -76,30 +88,32 @@ $configurator->createRobotLoader()
 PHP Files Analyzer
 ------------------
 
-RobotLoader can also be used purely to find classes, interfaces, and trait in PHP files **without** using the autoloading feature:
+RobotLoader can also be used purely for finding classes, interfaces, traits and enums in PHP files **without** using the autoloading function:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Scans directories for classes / interfaces / traits
+// Scans directories for classes/interfaces/traits/enums
 $loader->rebuild();
 
-// Returns array of class => filename pairs
+// Returns an array of class => filename pairs
 $res = $loader->getIndexedClasses();
 ```
 
-Even with such use, you can use the cache. As a result, unmodified files will not be repeatedly analyzed when rescanning:
+Even with such usage, you can utilize caching. This ensures that unchanged files won't be rescanned:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Set caching to the 'temp' directory
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Scans directories using a cache
+// Scans directories using cache
 $loader->refresh();
 
-// Returns array of class => filename pairs
+// Returns an array of class => filename pairs
 $res = $loader->getIndexedClasses();
 ```
 
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Caching
 -------
 
-RobotLoader is very fast because it cleverly uses the cache.
+RobotLoader is very fast because it cleverly uses caching.
 
-When developing with it, you have practically no idea that it runs on the background. It continuously updates the cache because it knows that classes and files can be created, deleted, renamed, etc. And it doesn't repeatedly scan unmodified files.
+During development, you hardly notice it running in the background. It continuously updates its cache, considering that classes and files can be created, deleted, renamed, etc. And it doesn't rescan unchanged files.
 
-When used on a production server, on the other hand, we recommend disabling the cache update using `$loader->setAutoRefresh(false)` (this is done automatically in the Nette Application), because the files are not changing. At the same time, it is necessary to **clear the cache** when uploading a new version on the hosting.
+On a production server, on the other hand, we recommend turning off cache updates using `$loader->setAutoRefresh(false)` (in a Nette Application, this happens automatically), because files don't change. At the same time, it's necessary to **clear the cache** when uploading a new version to hosting.
 
-Of course, the initial scanning of files, when the cache does not already exist, may take a few seconds for larger applications. RobotLoader has built-in prevention against "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-This is a situation where production server receives a large number of concurrent requests and because RobotLoader's cache does not yet exist, they would all start scanning the files. Which spikes CPU and filesystem usage.
-Fortunately, RobotLoader works in such a way that for multiple concurrent requests, only the first thread indexes the files, creates a cache, the others wait, and then use the cache.
+The initial file scanning, when the cache doesn't exist yet, can naturally take a moment for larger applications. RobotLoader has built-in prevention against "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
+This is a situation where a large number of concurrent requests on a production server would trigger RobotLoader, and since the cache doesn't exist yet, they would all start scanning files, which would overload the server.
+Fortunately, RobotLoader works in such a way that only the first thread indexes the files, creates the cache, and the rest wait and then use the cache.
 
 
 PSR-4
 -----
 
-Today, Composer can be used for [autoloading|best-practices:composer#autoloading] in compliance with PSR-4. Simply saying, it is a system where the namespaces and class names correspond to the directory structure and file names, ie `App\Router\RouterFactory` is located in the file `/path/to/App/Router/RouterFactory.php`.
+Nowadays, you can use [Composer for autoloading|best-practices:composer#autoloading] while adhering to PSR-4. Simply put, it's a system where namespaces and class names correspond to the directory structure and file names, e.g., `App\Core\RouterFactory` will be in the file `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader is not tied to any fixed structure, therefore, it is useful in situations where it does not suit you to have the directory structure designed as namespaces in PHP, or when you are developing an application that has historically not used such conventions. It is also possible to use both loaders together.
+RobotLoader isn't tied to any fixed structure, so it's useful in situations where you don't want to have the directory structure designed exactly like the PHP namespaces, or when developing an application that historically doesn't use such conventions. It's also possible to use both loaders together.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/es/@home.texy b/robot-loader/es/@home.texy
index 365dd5c96f..2297b2fda5 100644
--- a/robot-loader/es/@home.texy
+++ b/robot-loader/es/@home.texy
@@ -5,26 +5,38 @@ RobotLoader: Carga automática de clases
 
 RobotLoader es una herramienta que le ofrece la comodidad de la carga automática de clases para toda su aplicación, incluidas las bibliotecas de terceros.
 
-- deshacerse de todos `require`
-- sólo se cargan los scripts necesarios
-- no requiere estrictas convenciones de nomenclatura de directorios o archivos
+- Elimina todas las sentencias `require`
+- Sólo se cargarán los scripts necesarios
+- No requiere convenciones de nomenclatura estrictas para directorios o archivos
+- Extremadamente rápido
+- Sin actualizaciones manuales de la caché, todo se ejecuta automáticamente
+- Biblioteca madura, estable y ampliamente utilizada
 
 </div>
 
-Así que podemos olvidarnos de los famosos bloques de código:
+Así, podemos olvidarnos de estos bloques de código tan familiares:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Instalación .[#toc-installation]
 --------------------------------
 
-Descargue e instale el paquete utilizando [Composer |best-practices:composer]:
+Puede descargar RobotLoader como un [único archivo independiente `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que incluirá utilizando `require` en su script, y disfrutar al instante de una cómoda carga automática para toda la aplicación.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Si estás construyendo una aplicación usando [Composer |best-practices:composer], puedes instalarlo a través de:
 
 ```shell
 composer require nette/robot-loader
@@ -34,37 +46,37 @@ composer require nette/robot-loader
 Utilización .[#toc-usage]
 -------------------------
 
-Al igual que el robot de Google rastrea e indexa sitios web, [RobotLoader |api:Nette\Loaders\RobotLoader] rastrea todos los scripts PHP y registra qué clases e interfaces se encontraron en ellos. Estos registros se guardan en la caché y se utilizan durante todas las solicitudes posteriores. Sólo necesita especificar qué directorios indexar y dónde guardar la caché:
+De forma similar a como el robot de Google rastrea e indexa páginas web, el [RobotLoader |api:Nette\Loaders\RobotLoader] recorre todos los scripts PHP y anota las clases, interfaces, traits y enums que encuentra. A continuación, almacena los resultados en la caché para su uso en solicitudes posteriores. Sólo tienes que especificar qué directorios debe recorrer y dónde almacenar la caché:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// directorios a indexar por RobotLoader (incluyendo subdirectorios)
+// Directorios que RobotLoader debe indexar (incluidos los subdirectorios)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// usar directorio 'temp' para caché
+// Establecer la caché en el directorio 'temp
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Ejecutar el RobotLoader
+$loader->register(); // Activar RobotLoader
 ```
 
-Y eso es todo. A partir de ahora, no necesitará utilizar `require`. Estupendo, ¿verdad?
+Y ya está, a partir de este momento no necesitamos usar `require`. ¡Impresionante!
 
-Cuando RobotLoader encuentra un nombre de clase duplicado durante la indexación, lanza una excepción y te informa de ello. RobotLoader también actualiza automáticamente la caché cuando tiene que cargar una clase que no conoce. Recomendamos desactivar esto en los servidores de producción, ver [Caché |#Caching].
+Si RobotLoader encuentra un nombre de clase duplicado durante la indexación, lanzará una excepción y te lo notificará. RobotLoader también actualiza automáticamente la caché cuando necesita cargar una clase desconocida. Recomendamos desactivar esta opción en servidores de producción, ver [Caché |#Caching].
 
-Si quieres que RobotLoader se salte algunos directorios, utiliza `$loader->excludeDirectory('temp')` (se puede llamar varias veces o puedes pasar varios directorios).
+Si desea que RobotLoader omita ciertos directorios, utilice `$loader->excludeDirectory('temp')` (puede llamarse varias veces o pasar varios directorios).
 
-Por defecto, RobotLoader informa de errores en archivos PHP lanzando la excepción `ParseError`. Se puede desactivar a través de `$loader->reportParseErrors(false)`.
+Por defecto, RobotLoader informa de errores en archivos PHP lanzando una excepción `ParseError`. Esto puede suprimirse usando `$loader->reportParseErrors(false)`.
 
 
 Aplicación Nette .[#toc-nette-application]
 ------------------------------------------
 
-Dentro de la aplicación Nette, donde `$configurator` se utiliza en `Bootstrap.php`, puede configurar RobotLoader de esta manera:
+Dentro de la Aplicación Nette, donde `$configurator` se utiliza en `Bootstrap.php`, puede configurar RobotLoader de esta manera:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,27 +88,29 @@ $configurator->createRobotLoader()
 Analizador de archivos PHP .[#toc-php-files-analyzer]
 -----------------------------------------------------
 
-RobotLoader también puede ser usado puramente para encontrar clases, interfaces y traits en archivos PHP **sin** usar la característica de autocarga:
+RobotLoader también puede ser usado puramente para encontrar clases, interfaces, traits y enums en archivos PHP **sin** usar la función de autocarga:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Busca clases / interfaces / traits en los directorios
+// Escanea directorios en busca de clases/interfaces/traits/enums
 $loader->rebuild();
 
 // Devuelve un array de pares clase => nombre de fichero
 $res = $loader->getIndexedClasses();
 ```
 
-Incluso con tal uso, puede utilizar la caché. Como resultado, los archivos no modificados no serán analizados repetidamente al volver a escanear:
+Incluso con este uso, puede utilizar el almacenamiento en caché. Esto asegura que los archivos no modificados no serán escaneados de nuevo:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Establece la caché en el directorio 'temp
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Escanea directorios usando una caché
+// Escanea los directorios usando la caché
 $loader->refresh();
 
 // Devuelve un array de pares clase => nombre de fichero
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Almacenamiento en caché .[#toc-caching]
 ---------------------------------------
 
-RobotLoader es muy rápido porque utiliza inteligentemente la caché.
+RobotLoader es muy rápido porque utiliza inteligentemente el almacenamiento en caché.
 
-Cuando desarrollas con él, prácticamente no tienes ni idea de que se ejecuta en segundo plano. Actualiza continuamente la caché porque sabe que las clases y archivos pueden ser creados, borrados, renombrados, etc. Y no escanea repetidamente archivos no modificados.
+Durante el desarrollo, apenas se nota que está funcionando en segundo plano. Actualiza continuamente su caché, teniendo en cuenta que las clases y archivos pueden ser creados, borrados, renombrados, etc. Y no vuelve a escanear los archivos no modificados.
 
-En cambio, cuando se utiliza en un servidor de producción, se recomienda desactivar la actualización de la caché mediante `$loader->setAutoRefresh(false)` (esto se hace automáticamente en la aplicación Nette), porque los ficheros no cambian. Al mismo tiempo, es necesario **limpiar la caché** al subir una nueva versión al hosting.
+En un servidor de producción, en cambio, recomendamos desactivar las actualizaciones de la caché mediante `$loader->setAutoRefresh(false)` (en una aplicación Nette, esto sucede automáticamente), porque los archivos no cambian. Al mismo tiempo, es necesario **limpiar la caché** cuando se sube una nueva versión al hosting.
 
-Por supuesto, el escaneo inicial de los archivos, cuando la caché no existe ya, puede tardar unos segundos para las aplicaciones más grandes. RobotLoader tiene incorporada una prevención contra la "estampida de:https://en.wikipedia.org/wiki/Cache_stampede caché".
-Se trata de una situación en la que el servidor de producción recibe un gran número de peticiones simultáneas y, debido a que la caché de RobotLoader aún no existe, todas ellas comenzarían a escanear los archivos. Lo que dispara el uso de la CPU y del sistema de archivos.
-Afortunadamente, RobotLoader funciona de tal manera que para múltiples peticiones concurrentes, sólo el primer hilo indexa los archivos, crea una caché, los demás esperan, y luego utilizan la caché.
+El escaneo inicial de archivos, cuando la caché aún no existe, puede tardar un momento en las aplicaciones más grandes. RobotLoader tiene incorporada una prevención contra la "estampida de:https://en.wikipedia.org/wiki/Cache_stampede caché".
+Esta es una situación en la que un gran número de peticiones concurrentes en un servidor de producción activaría RobotLoader, y puesto que la caché no existe todavía, todos empezarían a escanear archivos, lo que sobrecargaría el servidor.
+Afortunadamente, RobotLoader funciona de tal manera que sólo el primer hilo indexa los archivos, crea la caché, y el resto espera y luego utiliza la caché.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-En la actualidad, Composer puede utilizarse para la [autolectura |best-practices:composer#autoloading] de conformidad con PSR-4. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos, es decir, `App\Router\RouterFactory` se encuentra en el archivo `/path/to/App/Router/RouterFactory.php`.
+Hoy en día, se puede utilizar [Composer para la autocarga |best-practices:composer#autoloading] respetando PSR-4. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos; por ejemplo, `App\Core\RouterFactory` estará en el archivo `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader no está atado a ninguna estructura fija, por lo tanto, es útil en situaciones donde no le conviene tener la estructura de directorios diseñada como namespaces en PHP, o cuando está desarrollando una aplicación que históricamente no ha usado tales convenciones. También es posible usar ambos cargadores juntos.
+RobotLoader no está atado a ninguna estructura fija, por lo que es útil en situaciones en las que no se desea tener la estructura de directorios diseñada exactamente como los espacios de nombres de PHP, o cuando se desarrolla una aplicación que históricamente no utiliza tales convenciones. También es posible usar ambos cargadores juntos.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/fr/@home.texy b/robot-loader/fr/@home.texy
index 89109f8308..99a1968db9 100644
--- a/robot-loader/fr/@home.texy
+++ b/robot-loader/fr/@home.texy
@@ -1,30 +1,42 @@
-RobotLoader : Auto-chargement des classes
-*****************************************
+RobotLoader : Autoloading de classe
+***********************************
 
 <div class=perex>
 
-RobotLoader est un outil qui vous offre le confort du chargement automatique des classes pour l'ensemble de votre application, y compris les bibliothèques tierces.
+RobotLoader est un outil qui vous permet de charger automatiquement des classes pour l'ensemble de votre application, y compris les bibliothèques tierces.
 
-- se débarrasser de tout `require`
-- seuls les scripts nécessaires sont chargés
-- ne nécessite pas de conventions strictes en matière de nom de répertoire ou de fichier
+- Éliminez toutes les déclarations `require`
+- Seuls les scripts nécessaires seront chargés
+- Ne nécessite pas de conventions de nommage strictes pour les répertoires ou les fichiers
+- Extrêmement rapide
+- Pas de mise à jour manuelle du cache, tout s'exécute automatiquement
+- Bibliothèque mature, stable et largement utilisée
 
 </div>
 
-On peut donc oublier ces fameux blocs de code :
+Nous pouvons donc oublier ces blocs de code familiers :
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Installation .[#toc-installation]
 ---------------------------------
 
-Téléchargez et installez le paquet en utilisant [Composer |best-practices:composer]:
+Vous pouvez télécharger RobotLoader sous la forme d'un [seul fichier autonome `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que vous incluez à l'aide de `require` dans votre script, et profiter instantanément d'un chargement automatique confortable pour l'ensemble de l'application.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Si vous construisez une application à l'aide de [Composer |best-practices:composer], vous pouvez l'installer via :
 
 ```shell
 composer require nette/robot-loader
@@ -34,27 +46,27 @@ composer require nette/robot-loader
 Utilisation .[#toc-usage]
 -------------------------
 
-Tout comme le robot Google explore et indexe les sites Web, [RobotLoader |api:Nette\Loaders\RobotLoader] explore tous les scripts PHP et enregistre les classes et les interfaces qu'ils contiennent. Ces enregistrements sont ensuite sauvegardés dans le cache et utilisés lors de toutes les requêtes ultérieures. Il vous suffit de spécifier les répertoires à indexer et l'endroit où sauvegarder le cache :
+De la même manière que le robot Google parcourt et indexe les pages web, [RobotLoader |api:Nette\Loaders\RobotLoader] parcourt tous les scripts PHP et note les classes, interfaces, traits et enums qu'il a trouvés. Il stocke ensuite les résultats dans le cache pour les utiliser lors de requêtes ultérieures. Il vous suffit de spécifier les répertoires qu'il doit parcourir et l'endroit où il doit stocker le cache :
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// répertoires à indexer par RobotLoader (y compris les sous-répertoires)
+// Répertoires à indexer par RobotLoader (y compris les sous-répertoires)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// utiliser le répertoire 'temp' pour le cache
+// Définir la mise en cache dans le répertoire "temp".
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Exécution du RobotLoader
+$loader->register(); // Activer RobotLoader
 ```
 
-Et c'est tout. A partir de maintenant, vous n'avez plus besoin d'utiliser `require`. Super, n'est-ce pas ?
+Et c'est tout, à partir de maintenant, nous n'avons plus besoin d'utiliser `require`. Génial !
 
-Lorsque RobotLoader rencontre un nom de classe en double pendant l'indexation, il lève une exception et vous en informe. RobotLoader met aussi automatiquement à jour le cache lorsqu'il doit charger une classe qu'il ne connaît pas. Nous recommandons de désactiver cette fonction sur les serveurs de production, voir [Mise en cache |#Caching].
+Si RobotLoader rencontre un nom de classe dupliqué pendant l'indexation, il lèvera une exception et vous en informera. RobotLoader met également à jour automatiquement le cache lorsqu'il doit charger une classe inconnue. Nous recommandons de désactiver cette fonction sur les serveurs de production, voir [Caching |#Caching].
 
-Si vous voulez que RobotLoader saute certains répertoires, utilisez `$loader->excludeDirectory('temp')` (il peut être appelé plusieurs fois ou vous pouvez passer plusieurs répertoires).
+Si vous souhaitez que RobotLoader ignore certains répertoires, utilisez `$loader->excludeDirectory('temp')` (peut être appelé plusieurs fois ou passer plusieurs répertoires).
 
-Par défaut, RobotLoader signale les erreurs dans les fichiers PHP en lançant l'exception `ParseError`. Elle peut être désactivée via `$loader->reportParseErrors(false)`.
+Par défaut, RobotLoader signale les erreurs dans les fichiers PHP en lançant une exception `ParseError`. Cette exception peut être supprimée en utilisant `$loader->reportParseErrors(false)`.
 
 
 Application Nette .[#toc-nette-application]
@@ -64,7 +76,7 @@ Dans l'application Nette, où `$configurator` est utilisé dans `Bootstrap.php`,
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,27 +88,29 @@ $configurator->createRobotLoader()
 Analyseur de fichiers PHP .[#toc-php-files-analyzer]
 ----------------------------------------------------
 
-RobotLoader peut aussi être utilisé uniquement pour trouver des classes, des interfaces et des traits dans les fichiers PHP **sans utiliser la fonction de chargement automatique :
+RobotLoader peut également être utilisé uniquement pour trouver des classes, des interfaces, des traits et des enums dans les fichiers PHP **sans** utiliser la fonction d'autoloading :
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Recherche des classes, interfaces et traits dans les répertoires.
+// Recherche les classes/interfaces/traits/enums dans les répertoires
 $loader->rebuild();
 
 // Retourne un tableau de paires classe => nom de fichier
 $res = $loader->getIndexedClasses();
 ```
 
-Même avec une telle utilisation, vous pouvez utiliser le cache. Ainsi, les fichiers non modifiés ne seront pas analysés à plusieurs reprises lors d'une nouvelle recherche :
+Même avec une telle utilisation, vous pouvez utiliser la mise en cache. Cela permet de s'assurer que les fichiers inchangés ne seront pas analysés à nouveau :
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Définit la mise en cache dans le répertoire "temp".
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Analyse des répertoires en utilisant un cache
+// Analyse les répertoires en utilisant le cache
 $loader->refresh();
 
 // Retourne un tableau de paires classe => nom de fichier
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Mise en cache .[#toc-caching]
 -----------------------------
 
-RobotLoader est très rapide car il utilise intelligemment le cache.
+RobotLoader est très rapide parce qu'il utilise intelligemment la mise en cache.
 
-Lorsque vous développez avec lui, vous n'avez pratiquement aucune idée qu'il fonctionne en arrière-plan. Il met continuellement à jour le cache car il sait que les classes et les fichiers peuvent être créés, supprimés, renommés, etc. Et il n'analyse pas de manière répétée les fichiers non modifiés.
+Pendant le développement, vous remarquez à peine qu'il fonctionne en arrière-plan. Il met continuellement à jour son cache, en tenant compte du fait que les classes et les fichiers peuvent être créés, supprimés, renommés, etc. Et il ne rescanne pas les fichiers inchangés.
 
-En revanche, lorsqu'il est utilisé sur un serveur de production, nous recommandons de désactiver la mise à jour du cache à l'aide de `$loader->setAutoRefresh(false)` (cela se fait automatiquement dans l'application Nette), car les fichiers ne changent pas. En même temps, il est nécessaire de **nettoyer le cache** lors du téléchargement d'une nouvelle version sur l'hébergement.
+Sur un serveur de production, en revanche, nous recommandons de désactiver les mises à jour du cache à l'aide de `$loader->setAutoRefresh(false)` (dans une application Nette, cela se fait automatiquement), car les fichiers ne changent pas. En même temps, il est nécessaire de **vider le cache** lors de l'envoi d'une nouvelle version à l'hébergement.
 
-Bien sûr, le balayage initial des fichiers, lorsque le cache n'existe pas encore, peut prendre quelques secondes pour les applications plus importantes. RobotLoader a une prévention intégrée contre la "ruée vers le cache":https://en.wikipedia.org/wiki/Cache_stampede.
-Il s'agit d'une situation dans laquelle le serveur de production reçoit un grand nombre de demandes simultanées et, comme le cache de RobotLoader n'existe pas encore, elles commencent toutes à analyser les fichiers. Ce qui fait monter en flèche l'utilisation du CPU et du système de fichiers.
-Heureusement, RobotLoader fonctionne de telle manière que pour plusieurs demandes simultanées, seul le premier thread indexe les fichiers, crée un cache, les autres attendent, puis utilisent le cache.
+L'analyse initiale des fichiers, lorsque le cache n'existe pas encore, peut naturellement prendre un certain temps pour les grandes applications. RobotLoader dispose d'une prévention intégrée contre la "ruée vers le cache":https://en.wikipedia.org/wiki/Cache_stampede.
+Il s'agit d'une situation dans laquelle un grand nombre de demandes simultanées sur un serveur de production déclencherait RobotLoader, et comme le cache n'existe pas encore, elles commenceraient toutes à analyser les fichiers, ce qui surchargerait le serveur.
+Heureusement, RobotLoader fonctionne de telle manière que seul le premier thread indexe les fichiers, crée le cache, et que les autres attendent et utilisent ensuite le cache.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Aujourd'hui, Composer peut être utilisé pour l'[autoloading |best-practices:composer#autoloading] en conformité avec PSR-4. En d'autres termes, il s'agit d'un système où les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, c'est-à-dire que `App\Router\RouterFactory` est situé dans le fichier `/path/to/App/Router/RouterFactory.php`.
+Aujourd'hui, vous pouvez utiliser [Composer pour l'autoloading |best-practices:composer#autoloading] tout en adhérant à PSR-4. En termes simples, il s'agit d'un système dans lequel les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, par exemple, `App\Core\RouterFactory` sera dans le fichier `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader n'est lié à aucune structure fixe, il est donc utile dans les situations où il ne vous convient pas d'avoir une structure de répertoire conçue comme des espaces de noms en PHP, ou lorsque vous développez une application qui n'a historiquement pas utilisé de telles conventions. Il est également possible d'utiliser les deux chargeurs ensemble.
+RobotLoader n'est pas lié à une structure fixe, il est donc utile dans les situations où vous ne voulez pas que la structure du répertoire soit conçue exactement comme les espaces de noms PHP, ou lorsque vous développez une application qui n'utilise pas historiquement de telles conventions. Il est également possible d'utiliser les deux chargeurs ensemble.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/hu/@home.texy b/robot-loader/hu/@home.texy
index c8538cea54..7d52995357 100644
--- a/robot-loader/hu/@home.texy
+++ b/robot-loader/hu/@home.texy
@@ -5,56 +5,68 @@ RobotLoader: Osztály automatikus betöltése
 
 A RobotLoader egy olyan eszköz, amely kényelmet biztosít az automatikus osztálybetöltés számára a teljes alkalmazásod számára, beleértve a harmadik féltől származó könyvtárakat is.
 
-- megszabadul az összes `require`
-- csak a szükséges szkriptek töltődnek be
-- nem igényel szigorú könyvtár- vagy fájlnevezési konvenciókat
+- Megszünteti az összes `require` utasítást
+- Csak a szükséges szkriptek töltődnek be
+- Nem igényel szigorú elnevezési konvenciókat a könyvtárak vagy fájlok számára
+- Rendkívül gyors
+- Nincs manuális gyorsítótár frissítés, minden automatikusan fut
+- Kiforrott, stabil és széles körben használt könyvtár
 
 </div>
 
-Tehát elfelejthetjük a híres kódblokkokat:
+Így elfelejthetjük ezeket az ismerős kódblokkokat:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Telepítés .[#toc-installation]
 ------------------------------
 
-Töltse le és telepítse a csomagot a [Composer |best-practices:composer] segítségével:
+A RobotLoader egyetlen önálló fájlként [letölthető `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], amelyet a `require` segítségével a szkriptjébe illeszthet, és azonnal élvezheti az egész alkalmazás kényelmes automatikus betöltését.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Ha [Composer |best-practices:composer] segítségével építesz alkalmazást, akkor telepítheted a:
 
 ```shell
 composer require nette/robot-loader
 ```
 
 
-Használat: .[#toc-usage]
-------------------------
+Használat .[#toc-usage]
+-----------------------
 
-Ahogy a Google robot feltérképezi és indexeli a weboldalakat, a [RobotLoader |api:Nette\Loaders\RobotLoader] is feltérképezi az összes PHP szkriptet, és rögzíti, hogy milyen osztályokat és interfészeket találtak bennük. Ezek a rekordok a gyorsítótárba kerülnek, és minden későbbi lekérdezés során felhasználásra kerülnek. Csak azt kell megadni, hogy milyen könyvtárakat indexeljen és hova mentse a gyorsítótárat:
+Hasonlóan ahhoz, ahogyan a Google robot feltérképezi és indexeli a weboldalakat, a [RobotLoader |api:Nette\Loaders\RobotLoader] végigmegy az összes PHP szkripten, és megjegyzi, hogy milyen osztályokat, interfészeket, tulajdonságokat és enumokat talált. Ezután az eredményeket a gyorsítótárban tárolja, hogy a későbbi lekérdezések során felhasználhassa. Csak azt kell megadni, hogy mely könyvtárakon menjen keresztül, és hol tárolja a gyorsítótárat:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// a RobotLoader által indexelendő könyvtárak (beleértve az alkönyvtárakat is)
+// A RobotLoader által indexelendő könyvtárak (beleértve az alkönyvtárakat is)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// 'temp' könyvtár használata a gyorsítótárhoz
+// A gyorsítótárazást a 'temp' könyvtárra állítsa be
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // RobotLoader futtatása
+$loader->register(); // RobotLoader aktiválása
 ```
 
-És ez minden. Mostantól kezdve nem kell a `require` címet használnod. Nagyszerű, nem igaz?
+És ennyi, innentől kezdve nem kell használnunk a `require` címet. Félelmetes!
 
-Ha a RobotLoader az indexelés során duplikált osztálynévvel találkozik, kivételt dob, és tájékoztatja Önt erről. A RobotLoader automatikusan frissíti a gyorsítótárat is, ha olyan osztályt kell betöltenie, amelyet nem ismer. Javasoljuk ennek kikapcsolását a produktív szervereken, lásd a [Caching |#Caching].
+Ha a RobotLoader az indexelés során duplikált osztálynévvel találkozik, akkor kivételt dob és értesítést küld. A RobotLoader automatikusan frissíti a gyorsítótárat is, ha egy ismeretlen osztályt kell betöltenie. Javasoljuk, hogy ezt kapcsolja ki a termelő szervereken, lásd [Cache |#Caching].
 
-Ha azt szeretné, hogy a RobotLoader kihagyjon néhány könyvtárat, használja a `$loader->excludeDirectory('temp')` címet (többször is meghívható, vagy több könyvtárat is átadhat).
+Ha azt szeretné, hogy a RobotLoader kihagyjon bizonyos könyvtárakat, használja a `$loader->excludeDirectory('temp')` címet (többször is hívható, vagy több könyvtárat is átadhat).
 
-Alapértelmezés szerint a RobotLoader a PHP-fájlok hibáit a `ParseError` kivétel dobásával jelzi. Ez kikapcsolható a `$loader->reportParseErrors(false)` segítségével.
+Alapértelmezés szerint a RobotLoader a PHP-fájlok hibáit a `ParseError` kivétel dobásával jelzi. Ez a `$loader->reportParseErrors(false)` használatával elnyomható.
 
 
 Nette alkalmazás .[#toc-nette-application]
@@ -64,7 +76,7 @@ A Nette alkalmazáson belül, ahol a `$configurator` a `Bootstrap.php` oldalon t
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -73,27 +85,29 @@ $configurator->createRobotLoader()
 ```
 
 
-PHP Files Analyzer .[#toc-php-files-analyzer]
----------------------------------------------
+PHP fájlok elemzője .[#toc-php-files-analyzer]
+----------------------------------------------
 
-A RobotLoader használható pusztán osztályok, interfészek és tulajdonságok keresésére is a PHP fájlokban **az automatikus betöltés funkció használata nélkül**:
+A RobotLoader használható pusztán osztályok, interfészek, tulajdonságok és enumok keresésére PHP fájlokban **az automatikus betöltés funkció használata nélkül** is:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Átvizsgálja a könyvtárakat osztályok / interfészek / tulajdonságok után.
+// Átvizsgálja a könyvtárakat osztályok/interfészek/traits/enumok után.
 $loader->rebuild();
 
 // Visszaadja az osztály => fájlnév párok tömbjét.
 $res = $loader->getIndexedClasses();
 ```
 
-Ilyen használat esetén is használhatja a gyorsítótárat. Ennek eredményeképpen a nem módosított fájlok nem kerülnek ismételten elemzésre az újbóli szkennelés során:
+Még ilyen használat esetén is kihasználhatja a gyorsítótárazást. Ez biztosítja, hogy a változatlan fájlok nem lesznek újra beolvasva:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// A gyorsítótár beállítása a 'temp' könyvtárba
 $loader->setTempDirectory(__DIR__ . '/temp');
 
 // Könyvtárak keresése a gyorsítótár segítségével
@@ -104,26 +118,26 @@ $res = $loader->getIndexedClasses();
 ```
 
 
-Tárolás .[#toc-caching]
+Caching .[#toc-caching]
 -----------------------
 
-A RobotLoader nagyon gyors, mert okosan használja a gyorsítótárat.
+A RobotLoader nagyon gyors, mert okosan használja a gyorsítótárazást.
 
-A vele való fejlesztés során gyakorlatilag fogalmad sincs arról, hogy a háttérben fut. Folyamatosan frissíti a gyorsítótárat, mert tudja, hogy osztályokat és fájlokat lehet létrehozni, törölni, átnevezni stb. És nem vizsgálja ismételten a nem módosított fájlokat.
+A fejlesztés során alig észrevehető, hogy a háttérben fut. Folyamatosan frissíti a gyorsítótárát, figyelembe véve, hogy osztályok és fájlok hozhatók létre, törölhetők, átnevezhetők stb. És nem vizsgálja újra a változatlan fájlokat.
 
-Termelőszervereken való használat esetén viszont javasoljuk, hogy a `$loader->setAutoRefresh(false)` segítségével tiltsuk le a gyorsítótár frissítését (ez automatikusan megtörténik a Nette alkalmazásban), mert a fájlok nem változnak. Ugyanakkor a tárhelyre történő új verzió feltöltésekor **tisztítani kell a gyorsítótárat**.
+Egy termelő szerveren viszont ajánlott kikapcsolni a gyorsítótár frissítését a `$loader->setAutoRefresh(false)` segítségével (egy Nette alkalmazásban ez automatikusan megtörténik), mivel a fájlok nem változnak. Ugyanakkor egy új verzió tárhelyre történő feltöltésekor **tisztítani kell a gyorsítótárat**.
 
-Természetesen a fájlok kezdeti beolvasása, ha a gyorsítótár még nem létezik, nagyobb alkalmazásoknál néhány másodpercig is eltarthat. A RobotLoader beépített megelőzéssel rendelkezik a "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede ellen.
-Ez az a helyzet, amikor a termelő szerver nagyszámú egyidejű kérést kap, és mivel a RobotLoader gyorsítótár még nem létezik, mindegyik elkezdené a fájlok beolvasását. Ami megnöveli a CPU és a fájlrendszer használatát.
-Szerencsére a RobotLoader úgy működik, hogy több egyidejű kérés esetén csak az első szál indexeli a fájlokat, létrehozza a gyorsítótárat, a többiek várnak, majd használják a gyorsítótárat.
+A kezdeti fájlszkennelés, amikor a gyorsítótár még nem létezik, nagyobb alkalmazásoknál természetesen eltarthat egy pillanatig. A RobotLoader beépített megelőzéssel rendelkezik a "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede ellen.
+Ez az a helyzet, amikor egy termelő szerveren nagyszámú egyidejű kérés indítaná el a RobotLoader-t, és mivel a gyorsítótár még nem létezik, mindegyik elkezdené a fájlok beolvasását, ami túlterhelné a szervert.
+Szerencsére a RobotLoader úgy működik, hogy csak az első szál indexeli a fájlokat, létrehozza a gyorsítótárat, a többi pedig vár, majd használja a gyorsítótárat.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-A Composer ma már a PSR-4 szabványnak megfelelően használható [automatikus betöltésre |best-practices:composer#autoloading]. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztálynevek megfelelnek a könyvtárszerkezetnek és a fájlneveknek, azaz a `App\Router\RouterFactory` a `/path/to/App/Router/RouterFactory.php` fájlban található.
+Manapság a [Composert |best-practices:composer#autoloading] használhatja [automatikus betöltésre |best-practices:composer#autoloading], miközben betartja a PSR-4-et. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztályok nevei megfelelnek a könyvtárszerkezetnek és a fájlneveknek, pl. a `App\Core\RouterFactory` a `/path/to/App/Core/RouterFactory.php` fájlban lesz.
 
-A RobotLoader nem kötődik semmilyen rögzített struktúrához, ezért hasznos olyan helyzetekben, amikor nem felel meg a PHP-ban névterekként kialakított könyvtárszerkezet, vagy amikor olyan alkalmazást fejlesztünk, amely történelmileg nem használ ilyen konvenciókat. Az is lehetséges, hogy mindkét betöltőt együtt használjuk.
+A RobotLoader nem kötődik semmilyen rögzített struktúrához, így hasznos olyan helyzetekben, amikor nem akarjuk, hogy a könyvtárstruktúra pontosan úgy legyen kialakítva, mint a PHP névterek, vagy amikor olyan alkalmazást fejlesztünk, amely történetileg nem használ ilyen konvenciókat. Az is lehetséges, hogy mindkét betöltőt együtt használjuk.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/it/@home.texy b/robot-loader/it/@home.texy
index 58c8528646..327732fbf1 100644
--- a/robot-loader/it/@home.texy
+++ b/robot-loader/it/@home.texy
@@ -5,56 +5,68 @@ RobotLoader: Caricamento automatico delle classi
 
 RobotLoader è uno strumento che consente il caricamento automatico delle classi per l'intera applicazione, comprese le librerie di terze parti.
 
-- sbarazzarsi di tutti `require`
-- vengono caricati solo gli script necessari
-- non richiede rigide convenzioni di denominazione delle directory o dei file
+- Eliminate tutte le dichiarazioni `require`
+- Vengono caricati solo gli script necessari
+- Non richiede convenzioni di denominazione rigide per le directory o i file
+- Estremamente veloce
+- Nessun aggiornamento manuale della cache, tutto viene eseguito automaticamente
+- Libreria matura, stabile e ampiamente utilizzata
 
 </div>
 
-Quindi possiamo dimenticare i famosi blocchi di codice:
+Possiamo quindi dimenticarci di questi blocchi di codice già noti:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Installazione .[#toc-installation]
 ----------------------------------
 
-Scaricare e installare il pacchetto utilizzando [Composer |best-practices:composer]:
+È possibile scaricare RobotLoader come un [singolo file standalone `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], da includere con `require` nel proprio script, e godere immediatamente di un comodo caricamento automatico per l'intera applicazione.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Se state costruendo un'applicazione usando [Composer |best-practices:composer], potete installarlo tramite:
 
 ```shell
 composer require nette/robot-loader
 ```
 
 
-Uso .[#toc-usage]
------------------
+Utilizzo .[#toc-usage]
+----------------------
 
-Come il robot di Google effettua la scansione e l'indicizzazione dei siti web, [RobotLoader |api:Nette\Loaders\RobotLoader] effettua la scansione di tutti gli script PHP e registra quali classi e interfacce sono state trovate in essi. Questi record vengono poi salvati nella cache e utilizzati durante tutte le richieste successive. È sufficiente specificare quali directory indicizzare e dove salvare la cache:
+Analogamente a come il robot di Google effettua il crawling e l'indicizzazione delle pagine web, [RobotLoader |api:Nette\Loaders\RobotLoader] esamina tutti gli script PHP e annota le classi, le interfacce, i tratti e gli enum che ha trovato. Quindi memorizza i risultati nella cache per utilizzarli nelle richieste successive. È sufficiente specificare quali directory deve attraversare e dove memorizzare la cache:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// le directory da indicizzare da RobotLoader (incluse le sottodirectory)
+// Directory da indicizzare per RobotLoader (incluse le sottodirectory)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// utilizzare la cartella 'temp' per la cache
+// Impostare la cache sulla directory "temp".
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Eseguire il RobotLoader
+$loader->register(); // Attivare RobotLoader
 ```
 
-E questo è tutto. D'ora in poi, non sarà più necessario usare `require`. Fantastico, non è vero?
+E questo è tutto, da questo momento in poi non abbiamo più bisogno di usare `require`. Fantastico!
 
-Quando RobotLoader incontra un nome di classe duplicato durante l'indicizzazione, lancia un'eccezione e informa l'utente. RobotLoader aggiorna automaticamente la cache quando deve caricare una classe che non conosce. Si consiglia di disabilitare questa funzione sui server di produzione, vedere [Cache |#Caching].
+Se RobotLoader incontra un nome di classe duplicato durante l'indicizzazione, lancerà un'eccezione e ne darà notifica. RobotLoader aggiorna automaticamente la cache quando deve caricare una classe sconosciuta. Si consiglia di disattivare questa funzione sui server di produzione, vedere [Cache |#Caching].
 
-Se si desidera che RobotLoader salti alcune directory, utilizzare `$loader->excludeDirectory('temp')` (può essere chiamato più volte o si possono passare più directory).
+Se si desidera che RobotLoader salti alcune directory, utilizzare `$loader->excludeDirectory('temp')` (può essere chiamato più volte o passare più directory).
 
-Per impostazione predefinita, RobotLoader segnala gli errori nei file PHP lanciando l'eccezione `ParseError`. Può essere disabilitato tramite `$loader->reportParseErrors(false)`.
+Per impostazione predefinita, RobotLoader segnala gli errori nei file PHP lanciando un'eccezione `ParseError`. Questa può essere soppressa usando `$loader->reportParseErrors(false)`.
 
 
 Applicazione Nette .[#toc-nette-application]
@@ -64,7 +76,7 @@ All'interno dell'applicazione Nette, dove `$configurator` è utilizzato in `Boot
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,27 +88,29 @@ $configurator->createRobotLoader()
 Analizzatore di file PHP .[#toc-php-files-analyzer]
 ---------------------------------------------------
 
-RobotLoader può essere usato anche solo per trovare classi, interfacce e tratti nei file PHP **senza** usare la funzione di caricamento automatico:
+RobotLoader può essere usato anche solo per trovare classi, interfacce, tratti ed enum nei file PHP **senza** usare la funzione di caricamento automatico:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Esegue la scansione delle directory per classi, interfacce e tratti.
+// Esegue la scansione delle directory per classi/interfacce/tratti/enum
 $loader->rebuild();
 
 // Restituisce un array di coppie classe => nome file
 $res = $loader->getIndexedClasses();
 ```
 
-Anche in questo caso, è possibile utilizzare la cache. Di conseguenza, i file non modificati non verranno analizzati ripetutamente durante la ricognizione:
+Anche con questo tipo di utilizzo, è possibile utilizzare la cache. In questo modo si garantisce che i file invariati non vengano ricanalizzati:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Imposta la cache sulla directory 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Esegue la scansione delle directory utilizzando una cache
+// Esegue la scansione delle directory utilizzando la cache
 $loader->refresh();
 
 // Restituisce un array di coppie classe => nome file
@@ -109,21 +123,21 @@ Caching .[#toc-caching]
 
 RobotLoader è molto veloce perché utilizza in modo intelligente la cache.
 
-Quando si sviluppa con esso, non si ha praticamente idea che venga eseguito in background. Aggiorna continuamente la cache perché sa che le classi e i file possono essere creati, cancellati, rinominati, ecc. E non esegue ripetutamente la scansione di file non modificati.
+Durante lo sviluppo, quasi non ci si accorge che è in esecuzione in background. Aggiorna continuamente la sua cache, considerando che le classi e i file possono essere creati, cancellati, rinominati, ecc. E non esegue una nuova scansione dei file invariati.
 
-Se si utilizza su un server di produzione, invece, si consiglia di disabilitare l'aggiornamento della cache tramite `$loader->setAutoRefresh(false)` (ciò avviene automaticamente nell'applicazione Nette), perché i file non vengono modificati. Allo stesso tempo, è necessario **pulire la cache** quando si carica una nuova versione sull'hosting.
+Su un server di produzione, invece, si consiglia di disattivare gli aggiornamenti della cache utilizzando `$loader->setAutoRefresh(false)` (in un'applicazione Nette, questo avviene automaticamente), perché i file non cambiano. Allo stesso tempo, è necessario **pulire la cache** quando si carica una nuova versione sull'hosting.
 
-Naturalmente, la scansione iniziale dei file, quando la cache non esiste già, può richiedere alcuni secondi per le applicazioni più grandi. RobotLoader ha una prevenzione integrata contro la "fuga dalla cache":https://en.wikipedia.org/wiki/Cache_stampede.
-Si tratta di una situazione in cui il server di produzione riceve un gran numero di richieste simultanee e, poiché la cache di RobotLoader non esiste ancora, tutte iniziano a scansionare i file. Il che fa impennare l'utilizzo della CPU e del filesystem.
-Fortunatamente, RobotLoader funziona in modo tale che, in caso di più richieste contemporanee, solo il primo thread indicizza i file, crea una cache, gli altri aspettano e poi utilizzano la cache.
+La scansione iniziale dei file, quando la cache non esiste ancora, può naturalmente richiedere un certo tempo per le applicazioni più grandi. RobotLoader ha una prevenzione integrata contro la "fuga dalla cache":https://en.wikipedia.org/wiki/Cache_stampede.
+Si tratta di una situazione in cui un gran numero di richieste simultanee su un server di produzione attiverebbe RobotLoader e, poiché la cache non esiste ancora, tutti inizierebbero a scansionare i file, sovraccaricando il server.
+Fortunatamente, RobotLoader funziona in modo tale che solo il primo thread indicizza i file, crea la cache e gli altri attendono e poi utilizzano la cache.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Oggi Composer può essere utilizzato per l'[autocaricamento |best-practices:composer#autoloading] in conformità al PSR-4. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, ad esempio `App\Router\RouterFactory` si trova nel file `/path/to/App/Router/RouterFactory.php`.
+Al giorno d'oggi, è possibile utilizzare [Composer per l'autocaricamento |best-practices:composer#autoloading], pur rispettando il sistema PSR-4. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, ad esempio `App\Core\RouterFactory` sarà nel file `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader non è legato a nessuna struttura fissa, quindi è utile in situazioni in cui non è opportuno avere la struttura delle directory progettata come spazi dei nomi in PHP, oppure quando si sta sviluppando un'applicazione che storicamente non ha usato tali convenzioni. È anche possibile utilizzare entrambi i caricatori insieme.
+RobotLoader non è legato a nessuna struttura fissa, quindi è utile in situazioni in cui non si vuole avere la struttura delle cartelle esattamente come gli spazi dei nomi di PHP, o quando si sviluppa un'applicazione che storicamente non usa tali convenzioni. È anche possibile utilizzare entrambi i caricatori insieme.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/pl/@home.texy b/robot-loader/pl/@home.texy
index a6fcc7f729..c71bcbe8eb 100644
--- a/robot-loader/pl/@home.texy
+++ b/robot-loader/pl/@home.texy
@@ -1,70 +1,82 @@
-RobotLoader: autoloadowanie klas
-********************************
+RobotLoader: Automatyczne ładowanie klas
+****************************************
 
 <div class=perex>
 
-RobotLoader to narzędzie, które daje wygodę automatycznego ładowania klas dla całej aplikacji, w tym bibliotek firm trzecich.
+RobotLoader to narzędzie, które zapewnia komfort automatycznego ładowania klas dla całej aplikacji, w tym bibliotek innych firm.
 
-- Pozbywamy się wszystkich `require`
-- zostaną załadowane tylko niezbędne skrypty
-- nie wymaga ścisłych konwencji nazewnictwa dla katalogów i plików
+- Wyeliminuj wszystkie instrukcje `require`
+- Załadowane zostaną tylko niezbędne skrypty
+- Nie wymaga ścisłych konwencji nazewnictwa katalogów lub plików
+- Niezwykle szybki
+- Brak ręcznych aktualizacji pamięci podręcznej, wszystko działa automatycznie
+- Dojrzała, stabilna i szeroko stosowana biblioteka
 
 </div>
 
-Możemy więc zapomnieć o tych znanych nam blokach kodu:
+Możemy więc zapomnieć o tych znanych blokach kodu:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Instalacja .[#toc-installation]
 -------------------------------
 
-Pobierz i zainstaluj bibliotekę za pomocą [Composera |best-practices:composer]:
+RobotLoader można pobrać jako [pojedynczy samodzielny plik `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], który można dołączyć za pomocą `require` do skryptu i natychmiast cieszyć się wygodnym automatycznym ładowaniem całej aplikacji.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Jeśli budujesz aplikację przy użyciu [Composera |best-practices:composer], możesz zainstalować go za pośrednictwem:
 
 ```shell
 composer require nette/robot-loader
 ```
 
 
-Korzystanie z .[#toc-usage]
----------------------------
+Użycie .[#toc-usage]
+--------------------
 
-Podobnie jak robot Google indeksuje strony internetowe, [RobotLoader |api:Nette\Loaders\RobotLoader] przeszukuje wszystkie skrypty PHP i notuje, jakie klasy, interfejsy i cechy w nich znalazł. Następnie buforuje wyniki swojej eksploracji i używa ich w następnym żądaniu. Wystarczy więc określić, które katalogi mają być indeksowane i gdzie mają być buforowane:
+Podobnie jak robot Google przeszukuje i indeksuje strony internetowe, [RobotLoader |api:Nette\Loaders\RobotLoader] przechodzi przez wszystkie skrypty PHP i odnotowuje znalezione klasy, interfejsy, cechy i wyliczenia. Następnie przechowuje wyniki w pamięci podręcznej do wykorzystania w kolejnych żądaniach. Wystarczy określić, przez które katalogi ma przechodzić i gdzie przechowywać pamięć podręczną:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// katalogi, które mają być indeksowane przez RobotLoader (łącznie z podkatalogami)
+// Katalogi do indeksowania przez RobotLoader (w tym podkatalogi)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// ustaw buforowanie w katalogu 'temp'
+// Ustaw buforowanie na katalog "temp
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // uruchom RobotLoader
+$loader->register(); // Aktywuj RobotLoader
 ```
 
-To wszystko, od tej pory nie musimy używać `require`. Świetnie!
+I to wszystko, od tego momentu nie musimy używać `require`. Super!
 
-Jeśli RobotLoader napotka zduplikowaną nazwę klasy podczas indeksowania, rzuca wyjątek i informuje o tym. RobotLoader również automatycznie aktualizuje pamięć podręczną, gdy musi załadować klasę, której nie zna. Zalecamy wyłączenie tego na serwerach produkcyjnych, zobacz [Caching |#Caching].
+Jeśli RobotLoader napotka zduplikowaną nazwę klasy podczas indeksowania, zgłosi wyjątek i powiadomi o tym użytkownika. RobotLoader automatycznie aktualizuje również pamięć podręczną, gdy musi załadować nieznaną klasę. Zalecamy wyłączenie tej opcji na serwerach produkcyjnych, patrz [Buforowanie |#Caching].
 
-Jeśli chcesz, aby RobotLoader pominął niektóre katalogi, użyj `$loader->excludeDirectory('temp')` (możesz wykonać wiele połączeń lub przekazać wiele katalogów).
+Jeśli chcesz, aby RobotLoader pomijał określone katalogi, użyj `$loader->excludeDirectory('temp')` (można wywołać wiele razy lub przekazać wiele katalogów).
 
-Domyślnie RobotLoader zgłasza błędy w plikach PHP rzucając wyjątek `ParseError`. Można to nadpisać za pomocą `$loader->reportParseErrors(false)`.
+Domyślnie RobotLoader zgłasza błędy w plikach PHP, rzucając wyjątek `ParseError`. Można to wyłączyć za pomocą `$loader->reportParseErrors(false)`.
 
 
-Aplikacje Nette .[#toc-nette-application]
+Aplikacja Nette .[#toc-nette-application]
 -----------------------------------------
 
-Wewnątrz aplikacji Nette, gdzie w pliku startowym używany jest obiekt `Bootstrap.php` `$configurator` , notacja może być uproszczona:
+Wewnątrz aplikacji Nette, gdzie `$configurator` jest używany w `Bootstrap.php`, można skonfigurować RobotLoader w ten sposób:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,54 +88,56 @@ $configurator->createRobotLoader()
 Analizator plików PHP .[#toc-php-files-analyzer]
 ------------------------------------------------
 
-RobotLoader może być również użyty do wyszukiwania klas, interfejsów i cech w plikach PHP **bez** użycia funkcji autoloadingu:
+RobotLoader może być również używany wyłącznie do wyszukiwania klas, interfejsów, cech i wyliczeń w plikach PHP **bez** korzystania z funkcji automatycznego ładowania:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// skanuje katalogi w poszukiwaniu klas/interfejsów/traitów
+// Skanuje katalogi w poszukiwaniu klas/interfejsów/traits/enums
 $loader->rebuild();
 
-// zwraca tablicę par class => filename
+// Zwraca tablicę par klasa => nazwa pliku
 $res = $loader->getIndexedClasses();
 ```
 
-W ten sposób można również wykorzystać cache. Dzięki temu niezmienione pliki nie będą ponownie analizowane przy ponownym skanowaniu:
+Nawet przy takim użyciu można wykorzystać buforowanie. Gwarantuje to, że niezmienione pliki nie będą ponownie skanowane:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Ustawia buforowanie na katalog "temp
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// skanuje katalogi używając pamięci podręcznej
+// Skanuje katalogi przy użyciu pamięci podręcznej
 $loader->refresh();
 
-// zwraca tablicę par class => filename
+// Zwraca tablicę par klasa => nazwa pliku
 $res = $loader->getIndexedClasses();
 ```
 
 
-Caching .[#toc-caching]
------------------------
+Buforowanie .[#toc-caching]
+---------------------------
 
 RobotLoader jest bardzo szybki, ponieważ sprytnie wykorzystuje buforowanie.
 
-Rozwijając się z nim, jesteś praktycznie nieświadomy, że działa on w tle. Stale aktualizuje swoją pamięć podręczną, ponieważ bierze pod uwagę, że klasy i pliki mogą być tworzone, znikać, zmieniać nazwy itp. I nie skanuje wielokrotnie plików, które nie uległy zmianie.
+Podczas programowania prawie nie widać, że działa w tle. Stale aktualizuje swoją pamięć podręczną, biorąc pod uwagę, że klasy i pliki mogą być tworzone, usuwane, zmieniane nazwy itp. I nie skanuje ponownie niezmienionych plików.
 
-Z drugiej strony, podczas wdrażania na serwerze produkcyjnym, zalecamy wyłączenie aktualizacji pamięci podręcznej za pomocą `$loader->setAutoRefresh(false)` (robi to automatycznie w aplikacji Nette), ponieważ pliki nie ulegają zmianie. Jednocześnie po wgraniu nowej wersji na hosting konieczne jest **wyczyszczenie cache**.
+Z drugiej strony na serwerze produkcyjnym zalecamy wyłączenie aktualizacji pamięci podręcznej za pomocą `$loader->setAutoRefresh(false)` (w aplikacji Nette dzieje się to automatycznie), ponieważ pliki się nie zmieniają. Jednocześnie konieczne jest **wyczyszczenie pamięci podręcznej** podczas przesyłania nowej wersji na hosting.
 
-Początkowe skanowanie plików, gdy pamięć podręczna jeszcze nie istnieje, może zająć chwilę w przypadku większych aplikacji. RobotLoader ma wbudowane zapobieganie przed "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-Jest to sytuacja, w której duża liczba współbieżnych żądań spotyka się na serwerze produkcyjnym i uruchamia RobotLoader, a ponieważ pamięć podręczna jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki. Co spowodowałoby nieproporcjonalne obciążenie serwera.
-Na szczęście sposób działania RobotLoader polega na tym, że gdy istnieje wiele współbieżnych żądań, tylko pierwszy wątek indeksuje pliki, tworzy pamięć podręczną, pozostałe czekają, a następnie używają pamięci podręcznej.
+Początkowe skanowanie plików, gdy pamięć podręczna jeszcze nie istnieje, może oczywiście zająć chwilę w przypadku większych aplikacji. RobotLoader ma wbudowaną ochronę przed "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
+Jest to sytuacja, w której duża liczba jednoczesnych żądań na serwerze produkcyjnym uruchomiłaby RobotLoader, a ponieważ pamięć podręczna jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki, co przeciążyłoby serwer.
+Na szczęście RobotLoader działa w taki sposób, że tylko pierwszy wątek indeksuje pliki, tworzy pamięć podręczną, a reszta czeka, a następnie korzysta z pamięci podręcznej.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Dziś [Composer |best-practices:composer#Autoloading] może być [używany |best-practices:composer#Autoloading] do [autoloadingu |best-practices:composer#Autoloading], jeśli przestrzega się PSR-4. Najprościej mówiąc, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów i nazwom plików, więc na przykład `App\Router\RouterFactory` będzie w pliku `/path/to/App/Router/RouterFactory.php`.
+Obecnie można używać [Composera do automatycznego ładowania |best-practices:composer#autoloading] przy jednoczesnym przestrzeganiu PSR-4. Mówiąc najprościej, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturze katalogów i nazwom plików, np. `App\Core\RouterFactory` będzie w pliku `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader nie jest przywiązany do żadnej stałej struktury, więc jest przydatny w sytuacjach, gdy nie czujesz się komfortowo z posiadaniem struktury katalogów zaprojektowanej w taki sam sposób jak przestrzenie nazw PHP, lub gdy rozwijasz aplikację, która historycznie nie używała takich konwencji. Możliwe jest również stosowanie obu ładowarek razem.
+RobotLoader nie jest powiązany z żadną stałą strukturą, więc jest przydatny w sytuacjach, w których nie chcesz, aby struktura katalogów była zaprojektowana dokładnie tak, jak przestrzenie nazw PHP, lub podczas tworzenia aplikacji, która historycznie nie używa takich konwencji. Możliwe jest również użycie obu programów ładujących razem.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/pt/@home.texy b/robot-loader/pt/@home.texy
index daf06c0cbb..82b22bb9b5 100644
--- a/robot-loader/pt/@home.texy
+++ b/robot-loader/pt/@home.texy
@@ -3,68 +3,80 @@ RobotLoader: Carregamento automático de classe
 
 <div class=perex>
 
-RobotLoader é uma ferramenta que lhe dá conforto de carregamento automatizado de classe para toda a sua aplicação, incluindo bibliotecas de terceiros.
+O RobotLoader é uma ferramenta que proporciona a você o conforto do carregamento automático de classes para todo o seu aplicativo, incluindo bibliotecas de terceiros.
 
-- se livrar de todos `require`
-- somente os scripts necessários são carregados
-- não requer convenções rigorosas de diretório ou de nomes de arquivos
+- Elimine todas as declarações `require`
+- Somente os scripts necessários serão carregados
+- Não requer convenções de nomenclatura rígidas para diretórios ou arquivos
+- Extremamente rápido
+- Sem atualizações manuais do cache, tudo é executado automaticamente
+- Biblioteca madura, estável e amplamente utilizada
 
 </div>
 
-Assim, podemos esquecer esses famosos blocos de código:
+Portanto, podemos esquecer esses blocos de código conhecidos:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Instalação .[#toc-installation]
 -------------------------------
 
-Baixe e instale o pacote usando [o Composer |best-practices:composer]:
+Você pode fazer o download do RobotLoader como um [único arquivo autônomo `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que você inclui usando `require` no seu script, e imediatamente aproveita o carregamento automático confortável para todo o aplicativo.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Se estiver criando um aplicativo usando o [Composer |best-practices:composer], poderá instalá-lo via:
 
 ```shell
 composer require nette/robot-loader
 ```
 
 
-Utilização .[#toc-usage]
-------------------------
+Uso .[#toc-usage]
+-----------------
 
-Como o robô Google rastreia e indexa websites, o [RobotLoader |api:Nette\Loaders\RobotLoader] rastreia todos os scripts PHP e registra quais classes e interfaces foram encontradas neles. Estes registros são então salvos em cache e utilizados durante todas as solicitações subseqüentes. Basta especificar quais diretórios indexar e onde salvar o cache:
+Semelhante à forma como o robô do Google rastreia e indexa as páginas da Web, o [RobotLoader |api:Nette\Loaders\RobotLoader] percorre todos os scripts PHP e anota quais classes, interfaces, características e enums encontrou. Em seguida, ele armazena os resultados no cache para uso em solicitações subsequentes. Você só precisa especificar quais diretórios ele deve percorrer e onde armazenar o cache:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// diretórios a serem indexados pelo RobotLoader (incluindo subdiretórios)
+// Diretórios para o RobotLoader indexar (incluindo subdiretórios)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// usar diretório 'temp' para cache
+// Defina o armazenamento em cache para o diretório "temp".
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Executar o RobotLoader
+$loader->register(); // Ativar o RobotLoader
 ```
 
-E isso é tudo. De agora em diante, você não precisa usar `require`. Ótimo, não é?
+E pronto, a partir de agora, não precisamos mais usar o `require`. Fantástico!
 
-Quando o RobotLoader encontra um nome de classe duplicado durante a indexação, ele lança uma exceção e o informa sobre isso. O RobotLoader também atualiza automaticamente o cache quando ele tem que carregar uma classe que não conhece. Recomendamos desativar isto nos servidores de produção, veja [Caching |#Caching].
+Se o RobotLoader encontrar um nome de classe duplicado durante a indexação, ele lançará uma exceção e o notificará. O RobotLoader também atualiza automaticamente o cache quando precisa carregar uma classe desconhecida. Recomendamos desativar isso nos servidores de produção, consulte [Cache |#Caching].
 
-Se você quiser que RobotLoader salte alguns diretórios, use `$loader->excludeDirectory('temp')` (pode ser chamado várias vezes ou você pode passar por vários diretórios).
+Se você quiser que o RobotLoader ignore determinados diretórios, use `$loader->excludeDirectory('temp')` (pode ser chamado várias vezes ou passar vários diretórios).
 
-Por padrão, o RobotLoader reporta erros em arquivos PHP lançando a exceção `ParseError`. Ele pode ser desativado via `$loader->reportParseErrors(false)`.
+Por padrão, o RobotLoader relata erros nos arquivos PHP lançando uma exceção `ParseError`. Isso pode ser suprimido usando `$loader->reportParseErrors(false)`.
 
 
-Aplicação Nette .[#toc-nette-application]
------------------------------------------
+Aplicativo Nette .[#toc-nette-application]
+------------------------------------------
 
-Dentro da aplicação Nette, onde `$configurator` é usado em `Bootstrap.php`, você pode configurar o RobotLoader desta forma:
+Dentro do aplicativo Nette, onde `$configurator` é usado em `Bootstrap.php`, você pode configurar o RobotLoader dessa forma:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,54 +88,56 @@ $configurator->createRobotLoader()
 Analisador de arquivos PHP .[#toc-php-files-analyzer]
 -----------------------------------------------------
 
-RobotLoader também pode ser usado puramente para encontrar classes, interfaces e traços em arquivos PHP **sem*** usando o recurso de auto-carregamento:
+O RobotLoader também pode ser usado exclusivamente para localizar classes, interfaces, características e enums em arquivos PHP **sem** usar a função de carregamento automático:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Escaneia diretórios de classes / interfaces / traços
+// Procura nos diretórios por classes/interfaces/traits/enums
 $loader->rebuild();
 
-// Retorna matriz de classe => pares de nomes de arquivo
+// Retorna uma matriz de pares classe => nome do arquivo
 $res = $loader->getIndexedClasses();
 ```
 
-Mesmo com tal uso, você pode usar o cache. Como resultado, os arquivos não modificados não serão analisados repetidamente durante a nova digitalização:
+Mesmo com esse uso, você pode utilizar o cache. Isso garante que os arquivos inalterados não sejam verificados novamente:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Definir o cache para o diretório "temp".
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Escaneia diretórios usando um cache
+// Examina os diretórios usando o cache
 $loader->refresh();
 
-// Retorna matriz de classe => pares de nomes de arquivo
+// Retorna uma matriz de pares classe => nome do arquivo
 $res = $loader->getIndexedClasses();
 ```
 
 
-Caching .[#toc-caching]
------------------------
+Armazenamento em cache .[#toc-caching]
+--------------------------------------
 
 O RobotLoader é muito rápido porque usa o cache de forma inteligente.
 
-Ao se desenvolver com ele, você não tem praticamente nenhuma idéia de que ele corre sobre o fundo. Ele atualiza continuamente o cache porque sabe que classes e arquivos podem ser criados, apagados, renomeados, etc. E ele não escaneia repetidamente arquivos não modificados.
+Durante o desenvolvimento, você mal percebe que ele está sendo executado em segundo plano. Ele atualiza continuamente o cache, considerando que as classes e os arquivos podem ser criados, excluídos, renomeados, etc. E ele não verifica novamente os arquivos não alterados.
 
-Quando usado em um servidor de produção, por outro lado, recomendamos desativar a atualização do cache usando `$loader->setAutoRefresh(false)` (isto é feito automaticamente na Aplicação Nette), porque os arquivos não estão mudando. Ao mesmo tempo, é necessário **clarar o cache** ao fazer o upload de uma nova versão na hospedagem.
+Em um servidor de produção, por outro lado, recomendamos desativar as atualizações de cache usando `$loader->setAutoRefresh(false)` (em um aplicativo Nette, isso acontece automaticamente), porque os arquivos não são alterados. Ao mesmo tempo, é necessário **limpar o cache** ao fazer o upload de uma nova versão para a hospedagem.
 
-Naturalmente, a digitalização inicial dos arquivos, quando o cache ainda não existe, pode levar alguns segundos para aplicações maiores. O RobotLoader tem prevenção embutida contra a "debandada do cache:https://en.wikipedia.org/wiki/Cache_stampede".
-Esta é uma situação em que o servidor de produção recebe um grande número de solicitações simultâneas e como o cache do RobotLoader ainda não existe, todos eles começariam a escanear os arquivos. O que aumenta o uso da CPU e do sistema de arquivos.
-Felizmente, o RobotLoader trabalha de tal forma que para múltiplas solicitações simultâneas, apenas o primeiro thread indexa os arquivos, cria um cache, os outros esperam, e então usam o cache.
+A verificação inicial do arquivo, quando o cache ainda não existe, pode naturalmente demorar um pouco para aplicativos maiores. O RobotLoader tem uma prevenção integrada contra a "debandada do cache":https://en.wikipedia.org/wiki/Cache_stampede.
+Essa é uma situação em que um grande número de solicitações simultâneas em um servidor de produção acionaria o RobotLoader e, como o cache ainda não existe, todos eles começariam a verificar os arquivos, o que sobrecarregaria o servidor.
+Felizmente, o RobotLoader funciona de tal forma que somente o primeiro thread indexa os arquivos, cria o cache, e os demais esperam e usam o cache.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Hoje, o Composer pode ser usado para [autocarga |best-practices:composer#autoloading] em conformidade com o PSR-4. Dito simplesmente, é um sistema onde os namespaces e nomes de classes correspondem à estrutura do diretório e nomes de arquivos, ou seja, `App\Router\RouterFactory` está localizado no arquivo `/path/to/App/Router/RouterFactory.php`.
+Atualmente, você pode usar o [Composer para carregamento automático |best-practices:composer#autoloading] enquanto adere ao PSR-4. Simplificando, é um sistema em que os namespaces e os nomes das classes correspondem à estrutura de diretórios e aos nomes de arquivos, por exemplo, `App\Core\RouterFactory` estará no arquivo `/path/to/App/Core/RouterFactory.php`.
 
-O RobotLoader não está ligado a nenhuma estrutura fixa, portanto, é útil em situações em que não lhe convém ter a estrutura de diretório projetada como namespaces em PHP, ou quando você está desenvolvendo uma aplicação que historicamente não utilizou tais convenções. Também é possível utilizar os dois carregadores em conjunto.
+O RobotLoader não está vinculado a nenhuma estrutura fixa, portanto, é útil em situações em que você não deseja que a estrutura de diretórios seja projetada exatamente como os namespaces do PHP ou ao desenvolver um aplicativo que historicamente não usa essas convenções. Também é possível usar os dois carregadores juntos.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/ro/@home.texy b/robot-loader/ro/@home.texy
index 931005f59e..d0c542edf1 100644
--- a/robot-loader/ro/@home.texy
+++ b/robot-loader/ro/@home.texy
@@ -5,26 +5,38 @@ RobotLoader: Încărcarea automată a clasei
 
 RobotLoader este un instrument care vă oferă confortul încărcării automate a claselor pentru întreaga dumneavoastră aplicație, inclusiv pentru bibliotecile de la terți.
 
-- scăpați de toate `require`
-- sunt încărcate doar scripturile necesare
-- nu necesită convenții stricte de denumire a directoarelor sau a fișierelor
+- Eliminați toate declarațiile `require`
+- Doar scripturile necesare vor fi încărcate
+- Nu necesită convenții de denumire stricte pentru directoare sau fișiere
+- Extrem de rapid
+- Fără actualizări manuale ale cache-ului, totul se execută automat
+- Bibliotecă matură, stabilă și utilizată pe scară largă
 
 </div>
 
-Așadar, putem să uităm de acele celebre blocuri de cod:
+Astfel, putem uita de aceste blocuri de cod familiare:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Instalare .[#toc-installation]
 ------------------------------
 
-Descărcați și instalați pachetul folosind [Composer |best-practices:composer]:
+Puteți descărca RobotLoader ca un [singur fișier independent `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], pe care îl includeți folosind `require` în scriptul dumneavoastră și vă bucurați instantaneu de o încărcare automată confortabilă pentru întreaga aplicație.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Dacă construiți o aplicație utilizând [Composer |best-practices:composer], îl puteți instala prin intermediul:
 
 ```shell
 composer require nette/robot-loader
@@ -34,27 +46,27 @@ composer require nette/robot-loader
 Utilizare .[#toc-usage]
 -----------------------
 
-La fel cum robotul Google răscolește și indexează site-urile web, [RobotLoader |api:Nette\Loaders\RobotLoader] răscolește toate scripturile PHP și înregistrează ce clase și interfețe au fost găsite în ele. Aceste înregistrări sunt apoi salvate în memoria cache și utilizate în timpul tuturor cererilor ulterioare. Trebuie doar să specificați ce directoare să indexați și unde să salvați memoria cache:
+Similar cu modul în care robotul Google răscolește și indexează paginile web, [RobotLoader |api:Nette\Loaders\RobotLoader] parcurge toate scripturile PHP și notează ce clase, interfețe, trăsături și enumerații a găsit. Apoi stochează rezultatele în memoria cache pentru a le utiliza în cererile ulterioare. Trebuie doar să specificați prin ce directoare trebuie să treacă și unde să stocheze memoria cache:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// directoare care urmează să fie indexate de RobotLoader (inclusiv subdirectoarele)
+// Directoare pe care RobotLoader trebuie să le indexeze (inclusiv subdirectoare)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// utilizați directorul "temp" pentru memoria cache
+// Setați memoria cache în directorul "temp".
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Rulați RobotLoader
+$loader->register(); // Activați RobotLoader
 ```
 
-Și asta e tot. De acum încolo, nu mai este nevoie să utilizați `require`. Minunat, nu-i așa?
+Și gata, din acest moment nu mai este nevoie să folosim `require`. Minunat!
 
-Atunci când RobotLoader întâlnește un nume de clasă duplicat în timpul indexării, acesta aruncă o excepție și vă informează despre aceasta. De asemenea, RobotLoader actualizează automat memoria cache atunci când trebuie să încarce o clasă pe care nu o cunoaște. Vă recomandăm să dezactivați acest lucru pe serverele de producție, consultați [Caching |#Caching].
+Dacă RobotLoader întâlnește un nume de clasă duplicat în timpul indexării, va arunca o excepție și vă va notifica. De asemenea, RobotLoader actualizează automat memoria cache atunci când trebuie să încarce o clasă necunoscută. Vă recomandăm să dezactivați acest lucru pe serverele de producție, consultați [Caching |#Caching].
 
-Dacă doriți ca RobotLoader să sară peste unele directoare, utilizați `$loader->excludeDirectory('temp')` (poate fi apelat de mai multe ori sau puteți trece mai multe directoare).
+Dacă doriți ca RobotLoader să sară peste anumite directoare, utilizați `$loader->excludeDirectory('temp')` (poate fi apelat de mai multe ori sau poate trece mai multe directoare).
 
-În mod implicit, RobotLoader raportează erorile din fișierele PHP prin aruncarea excepției `ParseError`. Aceasta poate fi dezactivată prin intermediul `$loader->reportParseErrors(false)`.
+În mod implicit, RobotLoader raportează erorile din fișierele PHP prin aruncarea unei excepții `ParseError`. Acest lucru poate fi suprimat folosind `$loader->reportParseErrors(false)`.
 
 
 Aplicația Nette .[#toc-nette-application]
@@ -64,7 +76,7 @@ Aplicația Nette .[#toc-nette-application]
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,27 +88,29 @@ $configurator->createRobotLoader()
 Analizator de fișiere PHP .[#toc-php-files-analyzer]
 ----------------------------------------------------
 
-RobotLoader poate fi, de asemenea, utilizat pur și simplu pentru a găsi clase, interfețe și trăsături în fișierele PHP **fără** a utiliza funcția de încărcare automată:
+RobotLoader poate fi, de asemenea, utilizat pur și simplu pentru a găsi clase, interfețe, trăsături și enumerații în fișierele PHP **fără** a utiliza funcția de încărcare automată:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Scanează directoarele pentru clase / interfețe / trăsături
+// Scanează directoarele pentru clase/interfețe/trăsături/enume
 $loader->rebuild();
 
 // Returnează o matrice de perechi clasă => nume de fișier
 $res = $loader->getIndexedClasses();
 ```
 
-Chiar și în cazul unei astfel de utilizări, puteți utiliza memoria cache. Ca urmare, fișierele nemodificate nu vor fi analizate în mod repetat la o nouă scanare:
+Chiar și în cazul unei astfel de utilizări, puteți utiliza memoria cache. Acest lucru asigură că fișierele neschimbate nu vor fi scanate din nou:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Setați memoria cache în directorul "temp
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Scanează directoarele folosind o memorie cache
+// Scanează directoarele folosind memoria cache
 $loader->refresh();
 
 // Returnează o matrice de perechi clasă => nume de fișier
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Caching .[#toc-caching]
 -----------------------
 
-RobotLoader este foarte rapid pentru că utilizează în mod inteligent memoria cache.
+RobotLoader este foarte rapid pentru că folosește în mod inteligent memoria cache.
 
-Atunci când dezvoltați cu el, practic nu aveți nicio idee că rulează în fundal. Actualizează continuu memoria cache deoarece știe că clasele și fișierele pot fi create, șterse, redenumite etc. Și nu scanează în mod repetat fișierele nemodificate.
+În timpul dezvoltării, abia dacă veți observa că rulează în fundal. Își actualizează continuu memoria cache, având în vedere că clasele și fișierele pot fi create, șterse, redenumite etc. Și nu scanează din nou fișierele neschimbate.
 
-Pe de altă parte, atunci când este utilizat pe un server de producție, vă recomandăm să dezactivați actualizarea cache-ului utilizând `$loader->setAutoRefresh(false)` (acest lucru se face automat în aplicația Nette), deoarece fișierele nu se modifică. În același timp, este necesar să **curățați memoria cache** atunci când încărcați o nouă versiune pe hosting.
+Pe de altă parte, pe un server de producție, vă recomandăm să dezactivați actualizările cache-ului utilizând `$loader->setAutoRefresh(false)` (într-o aplicație Nette, acest lucru se întâmplă automat), deoarece fișierele nu se modifică. În același timp, este necesar să **curățați memoria cache** atunci când încărcați o nouă versiune la găzduire.
 
-Desigur, scanarea inițială a fișierelor, atunci când memoria cache nu există deja, poate dura câteva secunde pentru aplicațiile mari. RobotLoader are încorporată o prevenire împotriva "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-Aceasta este o situație în care serverul de producție primește un număr mare de cereri concurente și, deoarece memoria cache a RobotLoader nu există încă, toate ar începe să scaneze fișierele. Ceea ce crește brusc utilizarea CPU și a sistemului de fișiere.
-Din fericire, RobotLoader funcționează în așa fel încât, pentru mai multe cereri concurente, doar primul fir indexează fișierele, creează o memorie cache, ceilalți așteaptă și apoi folosesc memoria cache.
+Scanarea inițială a fișierelor, atunci când memoria cache nu există încă, poate dura în mod natural un moment pentru aplicațiile mari. RobotLoader are încorporată o prevenire împotriva "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
+Aceasta este o situație în care un număr mare de solicitări simultane pe un server de producție ar declanșa RobotLoader și, deoarece memoria cache nu există încă, toate ar începe să scaneze fișiere, ceea ce ar supraîncărca serverul.
+Din fericire, RobotLoader funcționează în așa fel încât doar primul fir indexează fișierele, creează memoria cache, iar restul așteaptă și apoi utilizează memoria cache.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-În prezent, Composer poate fi utilizat pentru [încărcarea automată |best-practices:composer#autoloading] în conformitate cu PSR-4. Spunând simplu, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, adică `App\Router\RouterFactory` se află în fișierul `/path/to/App/Router/RouterFactory.php`.
+În prezent, puteți utiliza [Composer pentru încărcare automată |best-practices:composer#autoloading], respectând în același timp PSR-4. Pe scurt, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, de exemplu, `App\Core\RouterFactory` va fi în fișierul `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader nu este legat de nicio structură fixă, prin urmare, este util în situațiile în care nu vă convine ca structura directoarelor să fie concepută ca spații de nume în PHP sau atunci când dezvoltați o aplicație care, din punct de vedere istoric, nu a folosit astfel de convenții. De asemenea, este posibil să se utilizeze ambele încărcătoare împreună.
+RobotLoader nu este legat de nicio structură fixă, deci este util în situațiile în care nu doriți ca structura directoarelor să fie concepută exact ca spațiile de nume PHP sau atunci când dezvoltați o aplicație care, din punct de vedere istoric, nu folosește astfel de convenții. De asemenea, este posibil să folosiți ambele încărcătoare împreună.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/ru/@home.texy b/robot-loader/ru/@home.texy
index 0e2efe5380..2c8c5cb1ea 100644
--- a/robot-loader/ru/@home.texy
+++ b/robot-loader/ru/@home.texy
@@ -1,30 +1,42 @@
-RobotLoader: Класс автозагрузки
-*******************************
+RobotLoader: Автозагрузка классов
+*********************************
 
 <div class=perex>
 
-RobotLoader — это инструмент, обеспечивающий автоматическую загрузку классов для всего приложения, включая библиотеки сторонних разработчиков.
+RobotLoader - это инструмент, обеспечивающий удобство автоматической загрузки классов для всего приложения, включая библиотеки сторонних разработчиков.
 
-- избавиться от всех `require`
-- загружаются только необходимые скрипты
-- не требует строгих соглашений об именовании каталогов или файлов
+- Исключите все утверждения `require`.
+- Загружаются только необходимые скрипты
+- Не требует строгих соглашений об именовании каталогов и файлов
+- Чрезвычайно быстро
+- Не нужно вручную обновлять кэш, все выполняется автоматически
+- Зрелая, стабильная и широко используемая библиотека
 
 </div>
 
-Так что мы можем забыть об этих знаменитых блоках кода:
+Таким образом, мы можем забыть об этих привычных блоках кода:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Установка .[#toc-installation]
 ------------------------------
 
-Загрузите и установите пакет с помощью [Composer|best-practices:composer]:
+Вы можете загрузить RobotLoader в виде [отдельного файла `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], который вы включаете с помощью `require` в свой скрипт и сразу же получаете удобную автозагрузку для всего приложения.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Если вы собираете приложение с помощью [Composer |best-practices:composer], то установить его можно через:
 
 ```shell
 composer require nette/robot-loader
@@ -34,37 +46,37 @@ composer require nette/robot-loader
 Использование .[#toc-usage]
 ---------------------------
 
-Подобно тому, как робот Google просматривает и индексирует сайты, [RobotLoader |api:Nette\Loaders\RobotLoader] просматривает все PHP-скрипты и записывает, какие классы и интерфейсы были в них найдены. Затем эти записи сохраняются в кэше и используются при всех последующих запросах. Вам просто нужно указать, какие каталоги индексировать и где сохранять кэш:
+Подобно тому, как робот Google просматривает и индексирует веб-страницы, [RobotLoader |api:Nette\Loaders\RobotLoader] просматривает все PHP-скрипты и отмечает, какие классы, интерфейсы, трейты и перечисления он нашел. Затем он сохраняет результаты в кэше для использования при последующих запросах. Вам нужно только указать, по каким каталогам он должен пройти и где хранить кэш:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// каталоги, которые будут индексироваться RobotLoader (включая подкаталоги)
+// Каталоги для индексации RobotLoader (включая подкаталоги)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// использовать каталог 'temp' для кэша
+// Установите кэширование в каталог 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Run the RobotLoader
+$loader->register(); // Активировать RobotLoader
 ```
 
-И это всё. С этого момента вам не нужно использовать `require`. Здорово, не так ли?
+И все, с этого момента нам не нужно использовать `require`. Круто!
 
-Когда RobotLoader сталкивается с дублированием имени класса во время индексирования, он выбрасывает исключение и сообщает вам об этом. RobotLoader также автоматически обновляет кэш, когда ему нужно загрузить неизвестный ему класс. Мы рекомендуем отключить это на производственных серверах, см. [#Кэширование].
+Если в процессе индексирования RobotLoader столкнется с дублированием имени класса, он выбросит исключение и сообщит об этом. RobotLoader также автоматически обновляет кэш, когда ему необходимо загрузить неизвестный класс. Мы рекомендуем отключить эту функцию на рабочих серверах, см. раздел " [Кэширование |#Caching]".
 
-Если вы хотите, чтобы RobotLoader пропускал некоторые каталоги, используйте `$loader->excludeDirectory('temp')` (его можно вызвать несколько раз или передать несколько каталогов).
+Если вы хотите, чтобы RobotLoader пропускал определенные каталоги, используйте команду `$loader->excludeDirectory('temp')` (может вызываться несколько раз или передавать несколько каталогов).
 
-По умолчанию RobotLoader сообщает об ошибках в PHP-файлах, бросая исключение `ParseError`. Его можно отключить с помощью `$loader->reportParseErrors(false)`.
+По умолчанию RobotLoader сообщает об ошибках в PHP-файлах, выбрасывая исключение `ParseError`. Это может быть подавлено с помощью `$loader->reportParseErrors(false)`.
 
 
-Приложение Nette .[#toc-nette-application]
-------------------------------------------
+Nette Application .[#toc-nette-application]
+-------------------------------------------
 
-Внутри приложения Nette, где `$configurator` используется в `Bootstrap.php`, вы можете настроить RobotLoader таким образом:
+Внутри Nette Application, где `$configurator` используется в `Bootstrap.php`, можно настроить RobotLoader таким образом:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -73,27 +85,29 @@ $configurator->createRobotLoader()
 ```
 
 
-Анализатор файлов PHP .[#toc-php-files-analyzer]
+Анализатор PHP-файлов .[#toc-php-files-analyzer]
 ------------------------------------------------
 
-RobotLoader также можно использовать чисто для поиска классов, интерфейсов и трейтов в PHP-файлах **без** использования функции автозагрузки:
+RobotLoader также может быть использован чисто для поиска классов, интерфейсов, трейтов и перечислений в PHP-файлах **без** использования функции автозагрузки:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Сканирует каталоги на наличие классов / интерфейсов / трейтов
+// Сканирует каталоги на наличие классов/интерфейсов/трайтов/энумов
 $loader->rebuild();
 
 // Возвращает массив пар класс => имя файла
 $res = $loader->getIndexedClasses();
 ```
 
-Даже при таком использовании вы можете использовать кэш. В результате немодифицированные файлы не будут повторно анализироваться при повторном сканировании:
+Даже при таком использовании можно использовать кэширование. Это гарантирует, что неизмененные файлы не будут сканироваться повторно:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Установить кэширование в каталог 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
 // Сканирование каталогов с использованием кэша
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Кэширование .[#toc-caching]
 ---------------------------
 
-RobotLoader работает очень быстро, потому что он разумно использует кэш.
+RobotLoader работает очень быстро, поскольку в нем разумно используется кэширование.
 
-При разработке с ним вы практически не замечаете, что он работает в фоновом режиме. Он постоянно обновляет кэш, поскольку знает, что классы и файлы могут быть созданы, удалены, переименованы и т. д. И он не сканирует повторно немодифицированные файлы.
+Во время разработки вы едва ли заметите, что он работает в фоновом режиме. Он постоянно обновляет свой кэш, учитывая, что классы и файлы могут создаваться, удаляться, переименовываться и т.д. При этом повторное сканирование неизмененных файлов не производится.
 
-При использовании на рабочем сервере, с другой стороны, мы рекомендуем отключить обновление кэша с помощью `$loader->setAutoRefresh(false)` (это делается автоматически в приложении Nette), поскольку файлы не меняются. В то же время, необходимо **очистить кэш** при загрузке новой версии на хостинг.
+На рабочем же сервере мы рекомендуем отключить обновление кэша с помощью `$loader->setAutoRefresh(false)` (в Nette Application это происходит автоматически), поскольку файлы не меняются. В то же время при загрузке новой версии на хостинг необходимо **очищать кэш**.
 
-Конечно, первоначальное сканирование файлов, когда кэш ещё не существует, может занять несколько секунд для больших приложений. RobotLoader имеет встроенную защиту от "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-Это ситуация, когда производственный сервер получает большое количество одновременных запросов, и поскольку кэш RobotLoader ещё не существует, все они начнут сканировать файлы. Это увеличивает нагрузку на процессор и файловую систему.
-К счастью, RobotLoader работает таким образом, что при нескольких одновременных запросах только первый поток индексирует файлы, создает кэш, остальные ждут, а затем используют кэш.
+Первоначальное сканирование файлов, когда кэш еще не существует, естественно, может занять некоторое время для больших приложений. RobotLoader имеет встроенную защиту от "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
+Это ситуация, когда большое количество одновременных запросов на рабочем сервере вызовет RobotLoader, и поскольку кэш еще не существует, все они начнут сканировать файлы, что приведет к перегрузке сервера.
+К счастью, RobotLoader работает таким образом, что только первый поток индексирует файлы, создает кэш, а остальные ждут и затем используют кэш.
 
 
-PSR-4
------
+PSR-4 .[#toc-psr-4]
+-------------------
 
-Сегодня Composer можно использовать для [автозагрузки|best-practices:composer#Autoloading] в соответствии с PSR-4. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, т. е. `App\Router\RouterFactory` находится в файле `/path/to/App/Router/RouterFactory.php`.
+В настоящее время [для автозагрузки |best-practices:composer#autoloading] можно использовать [Composer |best-practices:composer#autoloading], придерживаясь при этом PSR-4. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, например, `App\Core\RouterFactory` будет находиться в файле `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader не привязан к какой-либо фиксированной структуре, поэтому он полезен в ситуациях, когда вам не подходит структура каталогов, оформленная в виде пространств имен в PHP, или когда вы разрабатываете приложение, в котором исторически не используются такие соглашения. Также можно использовать оба загрузчика вместе.
+RobotLoader не привязан к какой-либо фиксированной структуре, поэтому он полезен в ситуациях, когда не требуется, чтобы структура каталогов была оформлена в точном соответствии с пространствами имен PHP, или при разработке приложения, в котором исторически не используются подобные соглашения. Также возможно совместное использование обоих загрузчиков.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/sl/@home.texy b/robot-loader/sl/@home.texy
index 47d3bab6ec..801747f7fb 100644
--- a/robot-loader/sl/@home.texy
+++ b/robot-loader/sl/@home.texy
@@ -5,26 +5,38 @@ RobotLoader: Samodejno nalaganje razreda
 
 RobotLoader je orodje, ki omogoča samodejno nalaganje razredov za celotno aplikacijo, vključno s knjižnicami tretjih oseb.
 
-- znebite se vseh `require`
-- naložijo se samo potrebni skripti
-- ne zahteva strogih konvencij za poimenovanje imenikov ali datotek
+- Odpravite vse izjave `require`
+- Nalagali se bodo samo potrebni skripti
+- Ne zahteva strogih poimenovalnih konvencij za imenike ali datoteke
+- Izjemno hitro
+- Ni ročnih posodobitev predpomnilnika, vse poteka samodejno
+- Zrela, stabilna in široko uporabljena knjižnica
 
 </div>
 
-Zato lahko pozabimo na tiste znamenite bloke kode:
+Tako lahko pozabimo na te znane bloke kode:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Namestitev .[#toc-installation]
 -------------------------------
 
-Prenesite in namestite paket s [programom Composer |best-practices:composer]:
+RobotLoader lahko prenesete kot [eno samostojno datoteko `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], ki jo s pomočjo `require` vključite v svojo skripto, in takoj uživate v udobnem samodejnem nalaganju za celotno aplikacijo.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Če gradite aplikacijo z uporabo programa [Composer |best-practices:composer], ga lahko namestite prek:
 
 ```shell
 composer require nette/robot-loader
@@ -34,37 +46,37 @@ composer require nette/robot-loader
 Uporaba .[#toc-usage]
 ---------------------
 
-Podobno kot robot Google preiskuje in indeksira spletna mesta, [RobotLoader |api:Nette\Loaders\RobotLoader] preiskuje vse skripte PHP in beleži, katere razrede in vmesnike je našel v njih. Ti zapisi se nato shranijo v predpomnilnik in uporabijo pri vseh naslednjih zahtevah. Določiti morate le, katere imenike indeksirati in kam shraniti predpomnilnik:
+Podobno kot robot Google preiskuje in indeksira spletne strani, [RobotLoader |api:Nette\Loaders\RobotLoader] pregleda vse skripte PHP in zapiše, katere razrede, vmesnike, lastnosti in enume je našel. Rezultate nato shrani v predpomnilnik za uporabo pri naslednjih zahtevah. Določiti morate le, katere imenike naj pregleda in kje naj shrani predpomnilnik:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// imeniki, ki jih bo indeksiral RobotLoader (vključno s podimeniki).
+// imeniki za indeksiranje RobotLoaderja (vključno s podimeniki)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// uporabite imenik 'temp' za predpomnilnik
+// Nastavitev predpomnjenja na imenik 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Zaženite RobotLoader
+$loader->register(); // Aktivirajte RobotLoader
 ```
 
-In to je vse. Od zdaj naprej vam ni treba več uporabljati `require`. Super, kajne?
+In to je to, od te točke naprej nam ni treba več uporabljati `require`. Odlično!
 
-Ko RobotLoader med indeksiranjem naleti na podvojeno ime razreda, vrže izjemo in vas o tem obvesti. RobotLoader tudi samodejno posodobi predpomnilnik, kadar mora naložiti razred, ki ga ne pozna. Priporočamo, da to onemogočite v produkcijskih strežnikih, glejte poglavje [Predpomnilnik |#Caching].
+Če RobotLoader med indeksiranjem naleti na podvojeno ime razreda, bo vrgel izjemo in vas o tem obvestil. RobotLoader tudi samodejno posodobi predpomnilnik, kadar mora naložiti neznan razred. Priporočamo, da to izklopite na produkcijskih strežnikih, glejte [Predpomnilnik |#Caching].
 
-Če želite, da RobotLoader preskoči nekatere imenike, uporabite `$loader->excludeDirectory('temp')` (lahko ga pokličete večkrat ali posredujete več imenikov).
+Če želite, da RobotLoader preskoči določene imenike, uporabite `$loader->excludeDirectory('temp')` (lahko ga pokličete večkrat ali posredujete več imenikov).
 
-Privzeto RobotLoader poroča o napakah v datotekah PHP tako, da vrže izjemo `ParseError`. To lahko onemogočite prek `$loader->reportParseErrors(false)`.
+Privzeto RobotLoader poroča o napakah v datotekah PHP tako, da vrže izjemo `ParseError`. To lahko odpravite z uporabo `$loader->reportParseErrors(false)`.
 
 
-Nette aplikacija .[#toc-nette-application]
-------------------------------------------
+Neto aplikacija .[#toc-nette-application]
+-----------------------------------------
 
-Znotraj aplikacije Nette, kjer se `$configurator` uporablja v `Bootstrap.php`, lahko RobotLoader nastavite na ta način:
+Znotraj aplikacije Nette Application, kjer se `$configurator` uporablja v `Bootstrap.php`, lahko RobotLoader nastavite na ta način:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -73,27 +85,29 @@ $configurator->createRobotLoader()
 ```
 
 
-PHP Files Analyzer .[#toc-php-files-analyzer]
----------------------------------------------
+Analizator datotek PHP .[#toc-php-files-analyzer]
+-------------------------------------------------
 
-RobotLoader lahko uporabite tudi za iskanje razredov, vmesnikov in lastnosti v datotekah PHP, ne da bi uporabili funkcijo samodejnega nalaganja:
+RobotLoader lahko uporabite tudi za iskanje razredov, vmesnikov, lastnosti in enumov v datotekah PHP, ne da bi uporabili funkcijo samodejnega nalaganja:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Pregledovanje imenikov za razrede / vmesnike / lastnosti
+// Pregleduje imenike za razrede/interfaces/traits/enums
 $loader->rebuild();
 
 // Vrne polje parov razred => ime datoteke
 $res = $loader->getIndexedClasses();
 ```
 
-Tudi pri takšni uporabi lahko uporabite predpomnilnik. Zaradi tega se nespremenjene datoteke pri ponovnem iskanju ne bodo večkrat analizirale:
+Tudi pri takšni uporabi lahko uporabite predpomnjenje. To zagotavlja, da se nespremenjene datoteke ne bodo ponovno iskale:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Nastavite predpomnjenje v imenik 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
 // Pregleduje imenike z uporabo predpomnilnika
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Predpomnilnik .[#toc-caching]
 -----------------------------
 
-RobotLoader je zelo hiter, ker pametno uporablja predpomnilnik.
+RobotLoader je zelo hiter, ker pametno uporablja predpomnjenje.
 
-Pri razvijanju z njim praktično ne veste, da deluje v ozadju. Sprotno posodablja predpomnilnik, saj ve, da se razredi in datoteke lahko ustvarjajo, brišejo, preimenujejo itd. In ne pregleduje nespremenjenih datotek večkrat.
+Med razvojem skoraj ne opazite, da teče v ozadju. Svoj predpomnilnik nenehno posodablja, saj upošteva, da se razredi in datoteke lahko ustvarjajo, brišejo, preimenujejo itd. Nespremenjenih datotek ne pregleduje ponovno.
 
-Pri uporabi v produkcijskem strežniku pa priporočamo, da posodobitev predpomnilnika onemogočite z uporabo spletne strani `$loader->setAutoRefresh(false)` (to se samodejno izvede v aplikaciji Nette), saj se datoteke ne spreminjajo. Hkrati je treba **izbrisati predpomnilnik** ob prenosu nove različice na gostovanje.
+V produkcijskem strežniku pa priporočamo, da posodobitve predpomnilnika izklopite z uporabo spletne strani `$loader->setAutoRefresh(false)` (v aplikaciji Nette se to zgodi samodejno), saj se datoteke ne spreminjajo. Hkrati je treba **izbrisati predpomnilnik** ob prenosu nove različice na gostovanje.
 
-Seveda lahko začetno pregledovanje datotek, ko predpomnilnik še ne obstaja, pri večjih aplikacijah traja nekaj sekund. RobotLoader ima vgrajeno preprečevanje "stampeda predpomnilnika":https://en.wikipedia.org/wiki/Cache_stampede.
-To je situacija, ko produkcijski strežnik prejme veliko število hkratnih zahtevkov in ker predpomnilnik RobotLoader še ne obstaja, bi vsi začeli skenirati datoteke. To poveča porabo procesorja in datotečnega sistema.
-Na srečo RobotLoader deluje tako, da pri več hkratnih zahtevah le prva nit indeksira datoteke, ustvari predpomnilnik, druge počakajo in nato uporabijo predpomnilnik.
+Začetno pregledovanje datotek, ko predpomnilnik še ne obstaja, lahko pri večjih aplikacijah seveda traja nekaj časa. RobotLoader ima vgrajeno preprečevanje "stampeda predpomnilnika":https://en.wikipedia.org/wiki/Cache_stampede.
+To je situacija, ko bi veliko število hkratnih zahtevkov v produkcijskem strežniku sprožilo RobotLoader, in ker predpomnilnik še ne obstaja, bi vsi začeli pregledovati datoteke, kar bi preobremenilo strežnik.
+Na srečo RobotLoader deluje tako, da samo prva nit indeksira datoteke in ustvari predpomnilnik, ostale pa počakajo in nato uporabijo predpomnilnik.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Danes se lahko program Composer uporablja za [samodejno polnjenje v |best-practices:composer#autoloading] skladu s PSR-4. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, tj. `App\Router\RouterFactory` se nahaja v datoteki `/path/to/App/Router/RouterFactory.php`.
+Danes lahko [za samodejno nalaganje uporabljate program Composer |best-practices:composer#autoloading] in hkrati upoštevate PSR-4. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, npr. `App\Core\RouterFactory` bo v datoteki `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader ni vezan na nobeno fiksno strukturo, zato je uporaben v primerih, ko vam ne ustreza, da je struktura imenikov zasnovana kot imenski prostori v PHP, ali ko razvijate aplikacijo, ki v preteklosti ni uporabljala takih konvencij. Oba nalagalnika je mogoče uporabljati tudi skupaj.
+RobotLoader ni vezan na nobeno fiksno strukturo, zato je uporaben v primerih, ko ne želite, da bi bila struktura imenikov zasnovana povsem enako kot imenski prostori PHP, ali pri razvoju aplikacije, ki v preteklosti ni uporabljala takšnih konvencij. Oba nalagalnika je mogoče uporabljati tudi skupaj.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/tr/@home.texy b/robot-loader/tr/@home.texy
index 67fd5162ed..8088293c9a 100644
--- a/robot-loader/tr/@home.texy
+++ b/robot-loader/tr/@home.texy
@@ -5,26 +5,38 @@ RobotLoader: Sınıf Otomatik Yükleme
 
 RobotLoader, üçüncü taraf kütüphaneleri de dahil olmak üzere tüm uygulamanız için otomatik sınıf yükleme rahatlığı sağlayan bir araçtır.
 
-- hepsinden kurtulun `require`
-- sadece gerekli komut dosyaları yüklenir
-- katı dizin veya dosya adlandırma kuralları gerektirmez
+- Tüm `require` ifadelerini ortadan kaldırın
+- Yalnızca gerekli komut dosyaları yüklenecektir
+- Dizinler veya dosyalar için katı adlandırma kuralları gerektirmez
+- Son derece hızlı
+- Manuel önbellek güncellemesi yok, her şey otomatik olarak çalışıyor
+- Olgun, istikrarlı ve yaygın olarak kullanılan kütüphane
 
 </div>
 
-Bu yüzden o meşhur kod bloklarını unutabiliriz:
+Böylece, bu tanıdık kod bloklarını unutabiliriz:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Kurulum .[#toc-installation]
 ----------------------------
 
-[Composer'ı |best-practices:composer] kullanarak paketi indirin ve yükleyin:
+RobotLoader'ı, komut dosyanıza `require` kullanarak eklediğiniz tek bir [bağımsız dosya `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] olarak indirebilir ve anında tüm uygulama için rahat otomatik yüklemenin keyfini çıkarabilirsiniz.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+ [Composer |best-practices:composer] kullanarak bir uygulama oluşturuyorsanız, bunu şu yolla yükleyebilirsiniz:
 
 ```shell
 composer require nette/robot-loader
@@ -34,37 +46,37 @@ composer require nette/robot-loader
 Kullanım .[#toc-usage]
 ----------------------
 
-Google robotunun web sitelerini taraması ve indekslemesi gibi, [RobotLoader |api:Nette\Loaders\RobotLoader] da tüm PHP betiklerini tarar ve içlerinde hangi sınıfların ve arayüzlerin bulunduğunu kaydeder. Bu kayıtlar daha sonra önbelleğe kaydedilir ve sonraki tüm istekler sırasında kullanılır. Sadece hangi dizinlerin indeksleneceğini ve önbelleğin nereye kaydedileceğini belirtmeniz gerekir:
+Google robotunun web sayfalarını tarayıp indekslemesine benzer şekilde, [RobotLoader |api:Nette\Loaders\RobotLoader] tüm PHP betiklerini gözden geçirir ve hangi sınıfları, arayüzleri, özellikleri ve enumları bulduğunu not eder. Daha sonra sonuçları sonraki isteklerde kullanmak üzere önbellekte saklar. Sadece hangi dizinlerden geçmesi gerektiğini ve önbelleğin nerede saklanacağını belirtmeniz gerekir:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// RobotLoader tarafından indekslenecek dizinler (alt dizinler dahil)
+// RobotLoader'ın dizine ekleyeceği dizinler (alt dizinler dahil)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// önbellek için 'temp' dizinini kullan
+// Önbelleğe almayı 'temp' dizinine ayarlayın
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // RobotLoader'ı çalıştır
+$loader->register(); // RobotLoader'ı Etkinleştir
 ```
 
-Ve hepsi bu kadar. Şu andan itibaren `require` adresini kullanmanıza gerek yok. Harika, değil mi?
+İşte bu kadar, bu noktadan sonra `require` adresini kullanmamıza gerek yok. Harika!
 
-RobotLoader, indeksleme sırasında yinelenen sınıf adıyla karşılaştığında, bir istisna atar ve sizi bu konuda bilgilendirir. RobotLoader ayrıca bilmediği bir sınıfı yüklemek zorunda kaldığında önbelleği otomatik olarak günceller. Üretim sunucularında bunu [devre |#Caching] dışı bırakmanızı öneririz, bkz.
+RobotLoader, indeksleme sırasında yinelenen bir sınıf adıyla karşılaşırsa, bir istisna atacak ve sizi bilgilendirecektir. RobotLoader ayrıca bilinmeyen bir sınıfı yüklemesi gerektiğinde önbelleği otomatik olarak günceller. Üretim sunucularında bunu [kapatmanızı |#Caching] öneririz, bkz.
 
-RobotLoader'ın bazı dizinleri atlamasını istiyorsanız, `$loader->excludeDirectory('temp')` adresini kullanın (birden çok kez çağrılabilir veya birden çok dizin geçebilirsiniz).
+RobotLoader'ın belirli dizinleri atlamasını istiyorsanız, `$loader->excludeDirectory('temp')` adresini kullanın (birden çok kez çağrılabilir veya birden çok dizin geçebilir).
 
-Varsayılan olarak, RobotLoader PHP dosyalarındaki hataları `ParseError` istisnası atarak bildirir. `$loader->reportParseErrors(false)` üzerinden devre dışı bırakılabilir.
+Varsayılan olarak, RobotLoader PHP dosyalarındaki hataları bir `ParseError` istisnası atarak bildirir. Bu, `$loader->reportParseErrors(false)` kullanılarak bastırılabilir.
 
 
 Nette Uygulama .[#toc-nette-application]
 ----------------------------------------
 
-Nette uygulaması içinde, `$configurator` adresinin kullanıldığı `Bootstrap.php` adresinde RobotLoader'ı bu şekilde kurabilirsiniz:
+ `$configurator` adresinin `Bootstrap.php` adresinde kullanıldığı Nette Uygulaması içinde RobotLoader'ı bu şekilde kurabilirsiniz:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -76,27 +88,29 @@ $configurator->createRobotLoader()
 PHP Dosya Çözümleyicisi .[#toc-php-files-analyzer]
 --------------------------------------------------
 
-RobotLoader, otomatik yükleme özelliğini kullanmadan ** PHP dosyalarındaki sınıfları, arayüzleri ve özellikleri bulmak için de kullanılabilir:
+RobotLoader, otomatik yükleme işlevini kullanmadan ** PHP dosyalarındaki sınıfları, arayüzleri, özellikleri ve enumları bulmak için de kullanılabilir:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Sınıflar / arayüzler / özellikler için dizinleri tarar
+// Sınıflar/arayüzler/özellikler/enumlar için dizinleri tarar
 $loader->rebuild();
 
 // Sınıf => dosya adı çiftlerinden oluşan bir dizi döndürür
 $res = $loader->getIndexedClasses();
 ```
 
-Böyle bir kullanımda bile önbelleği kullanabilirsiniz. Sonuç olarak, değiştirilmemiş dosyalar yeniden taranırken tekrar tekrar analiz edilmeyecektir:
+Böyle bir kullanımda bile önbelleğe alma özelliğinden yararlanabilirsiniz. Bu, değişmeyen dosyaların yeniden taranmamasını sağlar:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Önbelleğe almayı 'temp' dizinine ayarlayın
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Bir önbellek kullanarak dizinleri tarar
+// Önbellek kullanarak dizinleri tarar
 $loader->refresh();
 
 // Sınıf => dosya adı çiftlerinden oluşan bir dizi döndürür
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Önbellekleme .[#toc-caching]
 ----------------------------
 
-RobotLoader çok hızlıdır çünkü önbelleği akıllıca kullanır.
+RobotLoader çok hızlıdır çünkü akıllıca önbellekleme kullanır.
 
-Onunla geliştirme yaparken, arka planda çalıştığına dair neredeyse hiçbir fikriniz olmaz. Sınıfların ve dosyaların oluşturulabileceğini, silinebileceğini, yeniden adlandırılabileceğini vb. bildiği için önbelleği sürekli olarak günceller. Ve değiştirilmemiş dosyaları tekrar tekrar taramaz.
+Geliştirme sırasında, arka planda çalıştığını neredeyse hiç fark etmezsiniz. Sınıfların ve dosyaların oluşturulabileceğini, silinebileceğini, yeniden adlandırılabileceğini vb. göz önünde bulundurarak önbelleğini sürekli olarak günceller. Ve değişmemiş dosyaları yeniden taramaz.
 
-Öte yandan, bir üretim sunucusunda kullanıldığında, dosyalar değişmediği için `$loader->setAutoRefresh(false)` adresini kullanarak önbellek güncellemesini devre dışı bırakmanızı öneririz (bu, Nette Uygulamasında otomatik olarak yapılır). Aynı zamanda, barındırmaya yeni bir sürüm yüklerken **önbelleği temizlemek** gerekir.
+Öte yandan, bir üretim sunucusunda, dosyalar değişmediği için `$loader->setAutoRefresh(false)` adresini kullanarak önbellek güncellemelerini kapatmanızı öneririz (bir Nette Uygulamasında bu otomatik olarak gerçekleşir). Aynı zamanda, barındırmaya yeni bir sürüm yüklerken **önbelleği temizlemek** gerekir.
 
-Elbette, önbellek zaten mevcut olmadığında dosyaların ilk taranması, daha büyük uygulamalar için birkaç saniye sürebilir. RobotLoader, "önbellek izdihamına":https://en.wikipedia.org/wiki/Cache_stampede karşı yerleşik bir önleme sahiptir.
-Bu, üretim sunucusunun çok sayıda eşzamanlı istek aldığı bir durumdur ve RobotLoader'ın önbelleği henüz mevcut olmadığından, hepsi dosyaları taramaya başlayacaktır. Bu da CPU ve dosya sistemi kullanımını artırır.
-Neyse ki, RobotLoader, birden fazla eşzamanlı istek için, yalnızca ilk iş parçacığı dosyaları indeksleyecek, bir önbellek oluşturacak, diğerleri bekleyecek ve ardından önbelleği kullanacak şekilde çalışır.
+Önbellek henüz mevcut olmadığında ilk dosya taraması, daha büyük uygulamalar için doğal olarak biraz zaman alabilir. RobotLoader, "önbellek izdihamına":https://en.wikipedia.org/wiki/Cache_stampede karşı yerleşik bir önleme sahiptir.
+Bu, bir üretim sunucusunda çok sayıda eşzamanlı isteğin RobotLoader'ı tetikleyeceği bir durumdur ve önbellek henüz mevcut olmadığından, hepsi sunucuyu aşırı yükleyecek dosyaları taramaya başlayacaktır.
+Neyse ki, RobotLoader sadece ilk iş parçacığı dosyaları indeksleyecek, önbelleği oluşturacak ve geri kalanı bekleyecek ve sonra önbelleği kullanacak şekilde çalışır.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Günümüzde Composer, PSR-4'e uygun olarak [otomatik yükleme |best-practices:composer#autoloading] için kullanılabilmektedir. Basitçe söylemek gerekirse, isim alanlarının ve sınıf isimlerinin dizin yapısına ve dosya isimlerine karşılık geldiği bir sistemdir, yani `App\Router\RouterFactory` `/path/to/App/Router/RouterFactory.php` dosyasında bulunur.
+Günümüzde, PSR-4'e bağlı kalarak [Composer'ı otomatik yükleme için |best-practices:composer#autoloading] kullanabilirsiniz. Basitçe söylemek gerekirse, ad alanlarının ve sınıf adlarının dizin yapısına ve dosya adlarına karşılık geldiği bir sistemdir, örneğin, `App\Core\RouterFactory` `/path/to/App/Core/RouterFactory.php` dosyasında olacaktır.
 
-RobotLoader herhangi bir sabit yapıya bağlı değildir, bu nedenle PHP'de ad alanları olarak tasarlanmış dizin yapısına sahip olmanın size uygun olmadığı durumlarda veya tarihsel olarak bu tür sözleşmeleri kullanmayan bir uygulama geliştirirken kullanışlıdır. Her iki yükleyiciyi birlikte kullanmak da mümkündür.
+RobotLoader herhangi bir sabit yapıya bağlı değildir, bu nedenle dizin yapısının tam olarak PHP ad alanları gibi tasarlanmasını istemediğiniz durumlarda veya tarihsel olarak bu tür kuralları kullanmayan bir uygulama geliştirirken kullanışlıdır. Her iki yükleyiciyi birlikte kullanmak da mümkündür.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/robot-loader/uk/@home.texy b/robot-loader/uk/@home.texy
index 1e07799bcc..052f874461 100644
--- a/robot-loader/uk/@home.texy
+++ b/robot-loader/uk/@home.texy
@@ -1,30 +1,42 @@
-RobotLoader: Клас автозавантаження
-**********************************
+RobotLoader: Автозавантаження класу
+***********************************
 
 <div class=perex>
 
-RobotLoader - це інструмент, що забезпечує автоматичне завантаження класів для всієї програми, включно з бібліотеками сторонніх розробників.
+RobotLoader - це інструмент, який надає вам зручність автоматичного завантаження класів для всього вашого додатку, включаючи сторонні бібліотеки.
 
-- позбутися всіх `require`
-- завантажуються тільки необхідні скрипти
-- не вимагає суворих угод про іменування каталогів або файлів
+- Усуньте всі оператори `require`
+- Завантажуються лише необхідні скрипти
+- Не вимагає суворого дотримання правил іменування каталогів або файлів
+- Надзвичайно швидкий
+- Ніяких ручних оновлень кешу, все виконується автоматично
+- Зріла, стабільна та широко використовувана бібліотека
 
 </div>
 
-Тож ми можемо забути про ці знамениті блоки коду:
+Таким чином, ми можемо забути про ці звичні блоки коду:
 
 ```php
 require_once 'Utils/Page.php';
 require_once 'Utils/Style.php';
 require_once 'Utils/Paginator.php';
-// ...
+//...
 ```
 
 
 Встановлення .[#toc-installation]
 ---------------------------------
 
-Завантажте та встановіть пакунок за допомогою [Composer|best-practices:composer]:
+Ви можете завантажити RobotLoader як [окремий файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], який ви включаєте за допомогою `require` у ваш скрипт, і миттєво насолоджуватися зручним автозавантаженням для всього додатку.
+
+```php
+require '/path/to/RobotLoader.php';
+
+$loader = new Nette\Loaders\RobotLoader;
+//...
+```
+
+Якщо ви створюєте додаток за допомогою [Composer |best-practices:composer], ви можете встановити його через нього:
 
 ```shell
 composer require nette/robot-loader
@@ -34,37 +46,37 @@ composer require nette/robot-loader
 Використання .[#toc-usage]
 --------------------------
 
-Подібно до того, як робот Google переглядає та індексує сайти, [RobotLoader |api:Nette\Loaders\RobotLoader] переглядає всі PHP-скрипти і записує, які класи та інтерфейси були в них знайдені. Потім ці записи зберігаються в кеші та використовуються під час усіх наступних запитів. Вам просто потрібно вказати, які каталоги індексувати і де зберігати кеш:
+Подібно до того, як робот Google сканує та індексує веб-сторінки, [RobotLoader |api:Nette\Loaders\RobotLoader] переглядає всі PHP-скрипти і записує, які класи, інтерфейси, риси та зчислення він знайшов. Потім він зберігає результати в кеші для використання в наступних запитах. Вам лише потрібно вказати, через які каталоги він повинен пройти і де зберігати кеш:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 
-// каталоги, які індексуватимуться RobotLoader (включно з підкаталогами)
+// Каталоги для індексації RobotLoader (включаючи підкаталоги)
 $loader->addDirectory(__DIR__ . '/app');
 $loader->addDirectory(__DIR__ . '/libs');
 
-// використовувати каталог 'temp' для кешу
+// Встановити кешування для каталогу 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
-$loader->register(); // Запустити RobotLoader
+$loader->register(); // Активувати RobotLoader
 ```
 
-І це все. З цього моменту вам не потрібно використовувати `require`. Чудово, чи не так?
+І все, з цього моменту нам не потрібно використовувати `require`. Чудово!
 
-Коли RobotLoader стикається з дублюванням імені класу під час індексування, він викидає виняток і повідомляє вам про це. RobotLoader також автоматично оновлює кеш, коли йому потрібно завантажити невідомий йому клас. Ми рекомендуємо вимкнути це на виробничих серверах, див. [Кешування |#Кэширование].
+Якщо RobotLoader під час індексації зустріне повторюване ім'я класу, він згенерує виключення і повідомить вас про це. RobotLoader також автоматично оновлює кеш, коли йому потрібно завантажити невідомий клас. Ми рекомендуємо вимкнути цю функцію на виробничих серверах, див. [Кешування |#Caching].
 
-Якщо ви хочете, щоб RobotLoader пропускав деякі каталоги, використовуйте `$loader->excludeDirectory('temp')` (його можна викликати кілька разів або передати кілька каталогів).
+Якщо ви хочете, щоб RobotLoader пропустив певні каталоги, використовуйте `$loader->excludeDirectory('temp')` (можна викликати кілька разів або передати кілька каталогів).
 
-За замовчуванням RobotLoader повідомляє про помилки в PHP-файлах, кидаючи виняток `ParseError`. Його можна відключити за допомогою `$loader->reportParseErrors(false)`.
+За замовчуванням RobotLoader повідомляє про помилки в PHP-файлах, генеруючи виключення `ParseError`. Це можна придушити за допомогою `$loader->reportParseErrors(false)`.
 
 
 Додаток Nette .[#toc-nette-application]
 ---------------------------------------
 
-Усередині програми Nette, де `$configurator` використовується в `Bootstrap.php`, ви можете налаштувати RobotLoader таким чином:
+Усередині Nette Application, де `$configurator` використовується в `Bootstrap.php`, ви можете налаштувати RobotLoader таким чином:
 
 ```php
 $configurator = new Nette\Bootstrap\Configurator;
-// ...
+//...
 $configurator->setTempDirectory(__DIR__ . '/../temp');
 $configurator->createRobotLoader()
 	->addDirectory(__DIR__)
@@ -73,30 +85,32 @@ $configurator->createRobotLoader()
 ```
 
 
-Аналізатор файлів PHP .[#toc-php-files-analyzer]
+Аналізатор PHP файлів .[#toc-php-files-analyzer]
 ------------------------------------------------
 
-RobotLoader також можна використовувати суто для пошуку класів, інтерфейсів і трейтів у PHP-файлах **без** використання функції автозавантаження:
+RobotLoader також можна використовувати суто для пошуку класів, інтерфейсів, трейтів та зчислень у PHP-файлах **без** використання функції автозавантаження:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
 
-// Сканує каталоги на наявність класів / інтерфейсів / трейтів
+// Сканує каталоги на наявність класів/інтерфейсів/ознак/зчислень
 $loader->rebuild();
 
 // Повертає масив пар клас => ім'я файлу
 $res = $loader->getIndexedClasses();
 ```
 
-Навіть при такому використанні ви можете використовувати кеш. У результаті немодифіковані файли не будуть повторно аналізуватися при повторному скануванні:
+Навіть при такому використанні ви можете використовувати кешування. Це гарантує, що незмінні файли не будуть скановані повторно:
 
 ```php
 $loader = new Nette\Loaders\RobotLoader;
 $loader->addDirectory(__DIR__ . '/app');
+
+// Встановити кешування для каталогу 'temp'
 $loader->setTempDirectory(__DIR__ . '/temp');
 
-// Сканування каталогів із використанням кешу
+// Сканує каталоги з використанням кешу
 $loader->refresh();
 
 // Повертає масив пар клас => ім'я файлу
@@ -107,23 +121,23 @@ $res = $loader->getIndexedClasses();
 Кешування .[#toc-caching]
 -------------------------
 
-RobotLoader працює дуже швидко, тому що він розумно використовує кеш.
+RobotLoader працює дуже швидко, тому що він розумно використовує кешування.
 
-Розробляючи з ним, ви майже не помічаєте, що він працює у фоновому режимі. Він постійно оновлює кеш, оскільки знає, що класи та файли можуть бути створені, видалені, перейменовані тощо. І він не сканує повторно немодифіковані файли.
+Під час розробки ви навряд чи помітите, що він працює у фоновому режимі. Він постійно оновлює свій кеш, враховуючи, що класи і файли можуть створюватися, видалятися, перейменовуватися тощо. І він не сканує незмінні файли.
 
-При використанні на робочому сервері, з іншого боку, ми рекомендуємо відключити оновлення кешу за допомогою `$loader->setAutoRefresh(false)` (це робиться автоматично в додатку Nette), оскільки файли не змінюються. Водночас, необхідно **очистити кеш** під час завантаження нової версії на хостинг.
+З іншого боку, на продуктивному сервері ми рекомендуємо вимкнути оновлення кешу за допомогою `$loader->setAutoRefresh(false)` (в Nette Application це відбувається автоматично), оскільки файли не змінюються. У той же час, необхідно **очищати кеш** при завантаженні нової версії на хостинг.
 
-Звичайно, початкове сканування файлів, коли кеш ще не існує, може зайняти кілька секунд для великих додатків. RobotLoader має вбудований захист від "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede.
-Це ситуація, коли виробничий сервер отримує велику кількість одночасних запитів, і оскільки кеш RobotLoader ще не існує, всі вони почнуть сканувати файли. Це збільшує навантаження на процесор і файлову систему.
-На щастя, RobotLoader працює таким чином, що за кількох одночасних запитів тільки перший потік індексує файли, створює кеш, решта чекають, а потім використовують кеш.
+Початкове сканування файлів, коли кеш ще не існує, може зайняти деякий час для великих додатків. RobotLoader має вбудований захист від "переповнення кешу":https://en.wikipedia.org/wiki/Cache_stampede.
+Це ситуація, коли велика кількість одночасних запитів на робочому сервері запускає RobotLoader, і оскільки кеш ще не існує, всі вони починають сканувати файли, що призводить до перевантаження сервера.
+На щастя, RobotLoader працює таким чином, що тільки перший потік індексує файли, створює кеш, а решта чекають і потім використовують кеш.
 
 
 PSR-4 .[#toc-psr-4]
 -------------------
 
-Сьогодні Composer можна використовувати для [автозавантаження |best-practices:composer#Autoloading] відповідно до PSR-4. Простіше кажучи, це система, у якій простори імен та імена класів відповідають структурі каталогів та іменам файлів, тобто `App\Router\RouterFactory` знаходиться у файлі `/path/to/App/Router/RouterFactory.php`.
+Сьогодні ви можете використовувати [Composer для автозавантаження |best-practices:composer#autoloading], дотримуючись PSR-4. Простіше кажучи, це система, де простори імен та імена класів відповідають структурі каталогів та іменам файлів, наприклад, `App\Core\RouterFactory` буде у файлі `/path/to/App/Core/RouterFactory.php`.
 
-RobotLoader не прив'язаний до будь-якої фіксованої структури, тому він корисний у ситуаціях, коли вам не підходить структура каталогів, оформлена у вигляді просторів імен у PHP, або коли ви розробляєте застосунок, у якому історично не використовуються такі угоди. Також можна використовувати обидва завантажувачі разом.
+RobotLoader не прив'язаний до будь-якої фіксованої структури, тому він корисний у ситуаціях, коли ви не хочете, щоб структура каталогів була розроблена точно так само, як простори імен PHP, або коли ви розробляєте програму, яка історично не використовує такі домовленості. Також можна використовувати обидва завантажувачі разом.
 
 
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/bg/@home.texy b/schema/bg/@home.texy
index 76d7bab75d..a86efec30c 100644
--- a/schema/bg/@home.texy
+++ b/schema/bg/@home.texy
@@ -197,7 +197,7 @@ Expect::anyOf(Expect::string('hello'), true, null)->firstIsDefault();
 
 Структурите са обекти с определени ключове. Всяка от тези двойки ключ => стойност се нарича "свойство":
 
-Структурите приемат масиви и обекти и връщат обекти `stdClass` (освен ако не ги промените с `castTo('array')` и т.н.).
+Структурите приемат масиви и обекти и връщат обекти `stdClass`.
 
 По подразбиране всички свойства са незадължителни и имат стойност по подразбиране `null`. Можете да дефинирате задължителни свойства, като използвате `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // ОК, връща {'optional' => null, 'nullable' => null}
 ```
 
+Масивът от всички свойства на структурата се връща от метода `getShape()`.
+
 По подразбиране във входните данни не може да има допълнителни елементи:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ОШИБКА
 ```
 
+Можете да създадете нова структура, като я извлечете от друга с помощта на `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Масив .[#toc-array]
+-------------------
+
+Масив с дефинирани ключове. Прилагат се същите правила като за [структурите |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Можете да дефинирате и индексиран масив, известен като кортеж:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Остарели елементи .[#toc-ustarevsie-elementy]
 ---------------------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Неуспешно изпълнение на командата "Дори елементи в масив" за елемент с масив от стойности.
 ```
 
-Този метод може да бъде извикан многократно за добавяне на нови твърдения.
+Методът може да бъде извикан многократно, за да се добавят множество ограничения. Той може да се смесва с извикванията на `transform()` и `castTo()`.
 
 
-Съпоставяне с обекти: from() .[#toc-sopostavlenie-s-ob-ektami-from]
--------------------------------------------------------------------
+Трансформация: transform() .[#toc-transformation-transform]
+-----------------------------------------------------------
 
-От класа може да се генерира структурна схема. Пример:
+Успешно валидираните данни могат да бъдат модифицирани с помощта на потребителска функция:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Методът може да бъде извикан многократно, за да се добавят множество трансформации. Той може да се смесва с извиквания на `assert()` и `castTo()`. Операциите ще бъдат изпълнени в реда, в който са декларирани:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Ако използвате PHP 7.4 или по-нова версия, можете да използвате вградените типове:
+Методът `transform()` може едновременно да трансформира и валидира стойността. Това често е по-просто и по-малко излишно от верижното използване на `transform()` и `assert()`. За тази цел функцията получава обект [Context |api:Nette\Schema\Context] с метод `addError()`, който може да се използва за добавяне на информация за проблеми с валидирането:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Поддържат се и анонимни класове:
+
+Заличаване: castTo() .[#toc-casting-castto]
+-------------------------------------------
+
+Успешно валидираните данни могат да бъдат хвърлени:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Тъй като информацията от дефиницията на класа може да не е достатъчна, можете да добавите потребителска схема за елементите с втори параметър:
+В допълнение към нативните PHP типове можете да използвате и класове. Той разграничава дали става въпрос за обикновен клас без конструктор или за клас с конструктор. Ако класът няма конструктор, се създава негова инстанция и всички елементи на структурата се записват в свойствата му:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Заличаване: castTo() .[#toc-privedenie-castto]
-----------------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Успешно тестваните данни могат да бъдат изхвърлени:
+Ако класът има конструктор, елементите на структурата се предават като именувани параметри на конструктора:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-В допълнение към собствените типове на PHP можете също така да се обръщате към класове:
+Casting в комбинация със скаларен параметър създава обект и предава стойността като единствен параметър на конструктора:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, возвращает ['a', 'b', 'c']
 ```
 
+
+Съпоставяне с обекти: from() .[#toc-mapping-to-objects-from]
+------------------------------------------------------------
+
+Можете да генерирате структурна схема от класа. Пример:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Поддържат се и анонимни класове:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Тъй като информацията, получена от дефиницията на класа, може да не е достатъчна, можете да добавите потребителска схема за елементите с втория параметър:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/cs/@home.texy b/schema/cs/@home.texy
index 4d40dc3cdf..5adb759b64 100644
--- a/schema/cs/@home.texy
+++ b/schema/cs/@home.texy
@@ -197,7 +197,7 @@ Struktury
 
 Struktury jsou objekty s definovanými klíči. Každá z dvojic klíč => hodnota je označována jako „vlastnost“:
 
-Struktury přijímají pole a objekty a vrací objekty `stdClass` (pokud to nezměníte pomocí `castTo('array')` apod).
+Struktury přijímají pole a objekty a vrací objekty `stdClass`.
 
 Ve výchozím nastavení jsou všechny vlastnosti volitelné a mají výchozí hodnotu `null`. Povinné vlastnosti můžete definovat pomocí `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, vrací {'optional' => null, 'nullable' => null}
 ```
 
+Pole všech vlastností struktury vrací metoda `getShape()`.
+
 Ve výchozím nastavení nemohou být ve vstupních datech žádné položky navíc:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // CHYBA
 ```
 
+Novou strukturu můžete vytvořit odvozením od jiné pomocí `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Pole .{data-version:1.3.2}
+--------------------------
+
+Pole s definovanými klíči. Platí pro něj vše co [struktury|#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // výchozí hodnota je null
+]);
+```
+
+Lze definovat také indexované pole, známé jako tuple:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Zastaralé vlastnosti
 --------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Failed assertion "Even items in array" for item with value array.
 ```
 
-Metodu lze volat opakovaně a tak přidat více omezení.
+Metodu lze volat opakovaně a tak přidat více omezení. Lze ji prokládat s voláním `transform()` a `castTo()`.
 
 
-Mapování na objekty: from()
----------------------------
+Transformace: transform() .{data-version:1.2.5}
+-----------------------------------------------
 
-Schéma struktury si můžeme nechat vygenerovat ze třídy. Příklad:
+Úspěšně zvalidovaná data lze upravovat pomocí vlastní funkce:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// převod na velká písmena:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'franta',
-];
+Metodu lze volat opakovaně a tak přidat více transformací. Lze ji prokládat s voláním `assert()` a `castTo()`. Operace se provedou v pořadí, v jakém jsou deklarovány:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'franta', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // převod na velká písmena
 ```
 
-Pokud používáte PHP 7.4 nebo vyšší, můžete využít nativních typů:
+Metoda `transform()` může současně transformovat i validovat hodnotu. To je často jednodušší a méně duplicitní než řetězení `transform()` a `assert()`. K tomuto účelu funkce obdrží objekt [Context |api:Nette\Schema\Context] s metodou `addError()`, kterou lze použít k přidání informací o problémech s validací:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Podporovány jsou i anonymní třídy:
+
+Přetypování: castTo()
+---------------------
+
+Úspěšně zvalidovaná data lze přetypovat:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Protože informace získané z definice třídy nemusí být dostačující, můžete druhým parametrem doplnit prvkům vlastní schéma:
+Kromě nativních PHP typů lze přetypovávat i na třídy. Přitom se rozlišuje, zda jde o jednoduchou třídu bez kontruktoru, nebo třídu s konstruktorem. Pokud třída nemá konstruktor, vytvoří se její instance a všechny prvky struktury se zapíší do properties:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Přetypování: castTo()
----------------------
+// vytvoří '$obj = new Info' a zapíše do $obj->processRefund a $obj->refundAmount
+```
 
-Úspěšně zvalidovaná data lze přetypovat:
+Pokud třída konstruktor má, prvky struktury se předají jako pojmenované parametry konstruktoru:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// vytvoří $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Kromě nativních PHP typů lze přetypovávat i na třídy:
+Přetypování v kombinaci se skalárním parametrem vytvoří objekt a hodnotu předá jako jediný parametr konstrukturu:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// vytvoří new DateTime(...)
 ```
 
 
@@ -444,4 +495,47 @@ $normalized = $processor->process($schema, 'a b c');
 ```
 
 
+Mapování na objekty: from()
+---------------------------
+
+Schéma struktury si můžeme nechat vygenerovat ze třídy. Příklad:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'franta',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'franta', 'password' => null, 'admin' => false}
+```
+
+Podporovány jsou i anonymní třídy:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Protože informace získané z definice třídy nemusí být dostačující, můžete druhým parametrem doplnit prvkům vlastní schéma:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/de/@home.texy b/schema/de/@home.texy
index 615b2a8c1b..19bc03279b 100644
--- a/schema/de/@home.texy
+++ b/schema/de/@home.texy
@@ -197,7 +197,7 @@ Strukturen .[#toc-structures]
 
 Strukturen sind Objekte mit definierten Schlüsseln. Jedes dieser Schlüssel => Wert-Paare wird als "Eigenschaft" bezeichnet:
 
-Strukturen akzeptieren Arrays und Objekte und geben Objekte zurück `stdClass` (es sei denn, Sie ändern dies mit `castTo('array')`, etc.).
+Strukturen akzeptieren Arrays und Objekte und geben Objekte zurück `stdClass`.
 
 Standardmäßig sind alle Eigenschaften optional und haben einen Standardwert von `null`. Obligatorische Eigenschaften können Sie mit `required()` definieren:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, liefert {'optional' => null, 'nullable' => null}
 ```
 
+Das Array mit allen Struktureigenschaften wird von der Methode `getShape()` zurückgegeben.
+
 Standardmäßig können keine zusätzlichen Elemente in den Eingabedaten enthalten sein:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+Sie können eine neue Struktur erstellen, indem Sie mit `extend()` von einer anderen ableiten:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Array .[#toc-array]
+-------------------
+
+Ein Array mit definierten Schlüsseln. Es gelten die gleichen Regeln wie für [Strukturen |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Sie können auch ein indiziertes Array, ein sogenanntes Tupel, definieren:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Verwerfungen .[#toc-deprecations]
 ---------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Fehlgeschlagene Assertion "Gerade Elemente in Array" für Element mit Wert array.
 ```
 
-Die Methode kann wiederholt aufgerufen werden, um weitere Behauptungen hinzuzufügen.
+Die Methode kann wiederholt aufgerufen werden, um mehrere Beschränkungen hinzuzufügen. Sie kann mit Aufrufen von `transform()` und `castTo()` vermischt werden.
 
 
-Zuordnung zu Objekten: from() .[#toc-mapping-to-objects-from]
--------------------------------------------------------------
+Umwandlung: transform() .[#toc-transformation-transform]
+--------------------------------------------------------
 
-Sie können aus der Klasse ein Strukturschema erzeugen. Beispiel:
+Erfolgreich überprüfte Daten können mit einer benutzerdefinierten Funktion geändert werden:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Die Methode kann wiederholt aufgerufen werden, um mehrere Transformationen hinzuzufügen. Sie kann mit Aufrufen von `assert()` und `castTo()` vermischt werden. Die Operationen werden in der Reihenfolge ausgeführt, in der sie deklariert sind:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Wenn Sie PHP 7.4 oder höher verwenden, können Sie native Typen verwenden:
+Die Methode `transform()` kann den Wert gleichzeitig transformieren und validieren. Dies ist oft einfacher und weniger redundant als die Verkettung von `transform()` und `assert()`. Zu diesem Zweck erhält die Funktion ein [Context-Objekt |api:Nette\Schema\Context] mit einer `addError()` -Methode, die dazu verwendet werden kann, Informationen über Validierungsprobleme hinzuzufügen:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Anonyme Klassen werden ebenfalls unterstützt:
+
+Gießen: castTo() .[#toc-casting-castto]
+---------------------------------------
+
+Erfolgreich überprüfte Daten können gecastet werden:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Da die aus der Klassendefinition gewonnenen Informationen möglicherweise nicht ausreichen, können Sie mit dem zweiten Parameter ein benutzerdefiniertes Schema für die Elemente hinzufügen:
+Zusätzlich zu den nativen PHP-Typen können Sie auch auf Klassen casten. Es wird unterschieden, ob es sich um eine einfache Klasse ohne Konstruktor oder um eine Klasse mit Konstruktor handelt. Wenn die Klasse keinen Konstruktor hat, wird eine Instanz der Klasse erstellt und alle Elemente der Struktur werden in ihre Eigenschaften geschrieben:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Erfolgreich überprüfte Daten können gecastet werden:
+Wenn die Klasse einen Konstruktor hat, werden die Elemente der Struktur als benannte Parameter an den Konstruktor übergeben:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Zusätzlich zu den nativen PHP-Typen können Sie auch auf Klassen casten:
+Casting in Verbindung mit einem skalaren Parameter erzeugt ein Objekt und übergibt den Wert als einzigen Parameter an den Konstruktor:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, liefert ['a', 'b', 'c']
 ```
 
+
+Zuordnung zu Objekten: from() .[#toc-mapping-to-objects-from]
+-------------------------------------------------------------
+
+Sie können aus der Klasse ein Strukturschema erzeugen. Beispiel:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Anonyme Klassen werden ebenfalls unterstützt:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Da die aus der Klassendefinition gewonnenen Informationen möglicherweise nicht ausreichen, können Sie mit dem zweiten Parameter ein benutzerdefiniertes Schema für die Elemente hinzufügen:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/el/@home.texy b/schema/el/@home.texy
index 4041fa7bdb..d8e72302de 100644
--- a/schema/el/@home.texy
+++ b/schema/el/@home.texy
@@ -197,7 +197,7 @@ Expect::anyOf(Expect::string('hello'), true, null)->firstIsDefault();
 
 Οι δομές είναι αντικείμενα με καθορισμένα κλειδιά. Κάθε ένα από αυτά τα ζεύγη κλειδί => τιμή αναφέρεται ως "ιδιότητα":
 
-Οι δομές δέχονται πίνακες και αντικείμενα και επιστρέφουν αντικείμενα `stdClass` (εκτός αν το αλλάξετε με το `castTo('array')`, κ.λπ.).
+Οι δομές δέχονται πίνακες και αντικείμενα και επιστρέφουν αντικείμενα `stdClass`.
 
 Από προεπιλογή, όλες οι ιδιότητες είναι προαιρετικές και έχουν προεπιλεγμένη τιμή `null`. Μπορείτε να ορίσετε υποχρεωτικές ιδιότητες χρησιμοποιώντας το `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, επιστρέφει {'optional' => null, 'nullable' => null}
 ```
 
+Ο πίνακας όλων των ιδιοτήτων της δομής επιστρέφεται από τη μέθοδο `getShape()`.
+
 Από προεπιλογή, δεν μπορούν να υπάρχουν επιπλέον στοιχεία στα δεδομένα εισόδου:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ΣΦΑΛΜΑ
 ```
 
+Μπορείτε να δημιουργήσετε μια νέα δομή παράγοντας από μια άλλη χρησιμοποιώντας το `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Συστοιχία .[#toc-array]
+-----------------------
+
+Ένας πίνακας με καθορισμένα κλειδιά. Ισχύουν οι ίδιοι κανόνες όπως και για [τις δομές |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Μπορείτε επίσης να ορίσετε έναν δεικτοδοτούμενο πίνακα, γνωστό ως πλειάδα:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Αποσβέσεις .[#toc-deprecations]
 -------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Αποτυχημένος ισχυρισμός "Even items in array" για στοιχείο με τιμή array.
 ```
 
-Η μέθοδος μπορεί να κληθεί επανειλημμένα για να προσθέσετε περισσότερους ισχυρισμούς.
+Η μέθοδος μπορεί να κληθεί επανειλημμένα για την προσθήκη πολλαπλών περιορισμών. Μπορεί να αναμειχθεί με κλήσεις στις `transform()` και `castTo()`.
 
 
-Αντιστοίχιση σε αντικείμενα: from() .[#toc-mapping-to-objects-from]
--------------------------------------------------------------------
+Μετασχηματισμός: transform() .[#toc-transformation-transform]
+-------------------------------------------------------------
 
-Μπορείτε να δημιουργήσετε σχήμα δομής από την κλάση. Παράδειγμα:
+Τα επιτυχώς επικυρωμένα δεδομένα μπορούν να τροποποιηθούν χρησιμοποιώντας μια προσαρμοσμένη συνάρτηση:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Η μέθοδος μπορεί να κληθεί επανειλημμένα για την προσθήκη πολλαπλών μετασχηματισμών. Μπορεί να αναμειχθεί με κλήσεις στις `assert()` και `castTo()`. Οι λειτουργίες θα εκτελούνται με τη σειρά με την οποία δηλώνονται:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Εάν χρησιμοποιείτε PHP 7.4 ή νεότερη έκδοση, μπορείτε να χρησιμοποιήσετε εγγενείς τύπους:
+Η μέθοδος `transform()` μπορεί να μετασχηματίσει και να επικυρώσει την τιμή ταυτόχρονα. Αυτό είναι συχνά απλούστερο και λιγότερο περιττό από την αλυσιδωτή εκτέλεση των `transform()` και `assert()`. Για το σκοπό αυτό, η συνάρτηση λαμβάνει ένα αντικείμενο [Context |api:Nette\Schema\Context] με μια μέθοδο `addError()`, η οποία μπορεί να χρησιμοποιηθεί για την προσθήκη πληροφοριών σχετικά με τα θέματα επικύρωσης:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Υποστηρίζονται επίσης ανώνυμες κλάσεις:
+
+Casting: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Τα επιτυχώς επικυρωμένα δεδομένα μπορούν να μεταφερθούν:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Μπορείτε να προσθέσετε ένα προσαρμοσμένο σχήμα για τα στοιχεία με τη δεύτερη παράμετρο:
+Εκτός από τους εγγενείς τύπους της PHP, μπορείτε επίσης να κάνετε cast σε κλάσεις. Διακρίνεται αν πρόκειται για μια απλή κλάση χωρίς κατασκευαστή ή για μια κλάση με κατασκευαστή. Αν η κλάση δεν έχει κατασκευαστή, δημιουργείται μια παρουσία της και όλα τα στοιχεία της δομής γράφονται στις ιδιότητές της:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Τα επιτυχώς επικυρωμένα δεδομένα μπορούν να μεταφερθούν:
+Εάν η κλάση διαθέτει κατασκευαστή, τα στοιχεία της δομής μεταβιβάζονται ως ονομαστικές παράμετροι στον κατασκευαστή:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Εκτός από τους εγγενείς τύπους της PHP, μπορείτε επίσης να κάνετε cast σε κλάσεις:
+Η χύτευση σε συνδυασμό με μια κλιμακωτή παράμετρο δημιουργεί ένα αντικείμενο και μεταβιβάζει την τιμή ως μοναδική παράμετρο στον κατασκευαστή:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, επιστρέφει ['a', 'b', 'c']
 ```
 
+
+Αντιστοίχιση σε αντικείμενα: from() .[#toc-mapping-to-objects-from]
+-------------------------------------------------------------------
+
+Μπορείτε να δημιουργήσετε σχήμα δομής από την κλάση. Παράδειγμα:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Υποστηρίζονται επίσης ανώνυμες κλάσεις:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Μπορείτε να προσθέσετε ένα προσαρμοσμένο σχήμα για τα στοιχεία με τη δεύτερη παράμετρο:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/en/@home.texy b/schema/en/@home.texy
index 2d1eb11cb2..5a47157acd 100644
--- a/schema/en/@home.texy
+++ b/schema/en/@home.texy
@@ -197,7 +197,7 @@ Structures
 
 Structures are objects with defined keys. Each of these key => value pairs is referred to as a "property":
 
-Structures accept arrays and objects and return objects `stdClass` (unless you change it with `castTo('array')`, etc.).
+Structures accept arrays and objects and return objects `stdClass`.
 
 By default, all properties are optional and have a default value of `null`. You can define mandatory properties using `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, returns {'optional' => null, 'nullable' => null}
 ```
 
+The array of all structure properties is returned by the `getShape()` method.
+
 By default, there can be no extra items in the input data:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+You can create a new structure by deriving from another using `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Array .{data-version:1.3.2}
+---------------------------
+
+An array with defined keys. The same rules apply as for [structures|#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+You can also define an indexed array, known as a tuple:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Deprecations
 ------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Failed assertion "Even items in array" for item with value array.
 ```
 
-The method can be called repeatedly to add more assertions.
+The method can be called repeatedly to add multiple constraints. It can be intermixed with calls to `transform()` and `castTo()`.
 
 
-Mapping to Objects: from()
---------------------------
+Transformation: transform() .{data-version:1.2.5}
+-------------------------------------------------
 
-You can generate structure schema from the class. Example:
+Successfully validated data can be modified using a custom function:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+The method can be called repeatedly to add multiple transformations. It can be intermixed with calls to `assert()` and `castTo()`. The operations will be executed in the order in which they are declared:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-If you are using PHP 7.4 or higher, you can use native types:
+The `transform()` method can both transform and validate the value simultaneously. This is often simpler and less redundant than chaining `transform()` and `assert()`. For this purpose, the function receives a [Context |api:Nette\Schema\Context] object with an `addError()` method, which can be used to add information about validation issues:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Anonymous classes are also supported:
+
+Casting: castTo()
+-----------------
+
+Successfully validated data can be cast:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Because the information obtained from the class definition may not be sufficient, you can add a custom schema for the elements with the second parameter:
+In addition to native PHP types, you can also cast to classes. It distinguishes whether it is a simple class without a constructor or a class with a constructor. If the class has no constructor, an instance of it is created and all elements of the structure are written to its properties:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo()
------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Successfully validated data can be cast:
+If the class has a constructor, the elements of the structure are passed as named parameters to the constructor:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-In addition to native PHP types, you can also cast to classes:
+Casting combined with a scalar parameter creates an object and passes the value as the sole parameter to the constructor:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, returns ['a', 'b', 'c']
 ```
 
+
+Mapping to Objects: from()
+--------------------------
+
+You can generate structure schema from the class. Example:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Anonymous classes are also supported:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Because the information obtained from the class definition may not be sufficient, you can add a custom schema for the elements with the second parameter:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/es/@home.texy b/schema/es/@home.texy
index b74af864a3..4334202fcc 100644
--- a/schema/es/@home.texy
+++ b/schema/es/@home.texy
@@ -197,7 +197,7 @@ Estructuras .[#toc-structures]
 
 Las estructuras son objetos con claves definidas. Cada uno de estos pares clave => valor se denomina "propiedad":
 
-Las estructuras aceptan arrays y objetos y devuelven objetos `stdClass` (a menos que lo cambies con `castTo('array')`, etc.).
+Las estructuras aceptan matrices y objetos y devuelven objetos `stdClass`.
 
 Por defecto, todas las propiedades son opcionales y tienen un valor por defecto de `null`. Puede definir propiedades obligatorias utilizando `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, devuelve {'optional' => null, 'nullable' => null}
 ```
 
+El array de todas las propiedades de la estructura es devuelto por el método `getShape()`.
+
 Por defecto, no puede haber elementos adicionales en los datos de entrada:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+Puede crear una nueva estructura derivando de otra mediante `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Matriz .[#toc-array]
+--------------------
+
+Un array con claves definidas. Se aplican las mismas reglas que para [las estructuras |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+También puedes definir una matriz indexada, conocida como tupla:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Depreciaciones .[#toc-deprecations]
 -----------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Fallo en la aserción "Even items in array" para el elemento con valor array.
 ```
 
-El método puede ser llamado repetidamente para añadir más aserciones.
+El método puede llamarse repetidamente para añadir múltiples restricciones. Puede entremezclarse con llamadas a `transform()` y `castTo()`.
 
 
-Asignación a objetos: from() .[#toc-mapping-to-objects-from]
+Transformación: transform() .[#toc-transformation-transform]
 ------------------------------------------------------------
 
-Se puede generar esquema de estructura a partir de la clase. Ejemplo:
+Los datos validados correctamente pueden modificarse mediante una función personalizada:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+El método puede llamarse repetidamente para añadir múltiples transformaciones. Puede entremezclarse con llamadas a `assert()` y `castTo()`. Las operaciones se ejecutarán en el orden en que se declaren:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Si está usando PHP 7.4 o superior, puede usar tipos nativos:
+El método `transform()` puede transformar y validar el valor simultáneamente. Esto suele ser más sencillo y menos redundante que encadenar `transform()` y `assert()`. Para ello, la función recibe un objeto [Context |api:Nette\Schema\Context] con un método `addError()`, que puede utilizarse para añadir información sobre problemas de validación:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Las clases anónimas también están soportadas:
+
+Casting: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Los datos validados correctamente pueden ser emitidos:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Dado que la información obtenida de la definición de la clase puede no ser suficiente, puede añadir un esquema personalizado para los elementos con el segundo parámetro:
+Además de los tipos nativos de PHP, también se puede hacer cast a clases. Distingue si se trata de una clase simple sin constructor o de una clase con constructor. Si la clase no tiene constructor, se crea una instancia de la misma y todos los elementos de la estructura se escriben en sus propiedades:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Los datos validados correctamente pueden ser emitidos:
+Si la clase tiene un constructor, los elementos de la estructura se pasan como parámetros con nombre al constructor:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Además de los tipos nativos de PHP, también se pueden convertir a clases:
+El moldeado combinado con un parámetro escalar crea un objeto y pasa el valor como único parámetro al constructor:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, devuelve ['a', 'b', 'c']
 ```
 
+
+Asignación a objetos: from() .[#toc-mapping-to-objects-from]
+------------------------------------------------------------
+
+Se puede generar esquema de estructura a partir de la clase. Ejemplo:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+También se admiten clases anónimas:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Dado que la información obtenida de la definición de la clase puede no ser suficiente, puede añadir un esquema personalizado para los elementos con el segundo parámetro:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/fr/@home.texy b/schema/fr/@home.texy
index 06c25f68ef..0019032c5e 100644
--- a/schema/fr/@home.texy
+++ b/schema/fr/@home.texy
@@ -197,7 +197,7 @@ Structures .[#toc-structures]
 
 Les structures sont des objets avec des clés définies. Chacune de ces paires clé => valeur est appelée "propriété" :
 
-Les structures acceptent des tableaux et des objets et renvoient des objets `stdClass` (sauf si vous le changez avec `castTo('array')`, etc.).
+Les structures acceptent des tableaux et des objets et renvoient des objets `stdClass`.
 
 Par défaut, toutes les propriétés sont facultatives et ont une valeur par défaut de `null`. Vous pouvez définir des propriétés obligatoires en utilisant `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, retourne {'optional' => null, 'nullable' => null}.
 ```
 
+Le tableau de toutes les propriétés de la structure est renvoyé par la méthode `getShape()`.
+
 Par défaut, il ne peut y avoir aucun élément supplémentaire dans les données d'entrée :
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERREUR
 ```
 
+Vous pouvez créer une nouvelle structure en dérivant d'une autre à l'aide de `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Tableau .[#toc-array]
+---------------------
+
+Un tableau dont les clés sont définies. Les mêmes règles que pour les [structures |#structure] s'appliquent.
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Vous pouvez également définir un tableau indexé, appelé tuple :
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Dépréciations .[#toc-deprecations]
 ----------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Failed assertion "Even items in array" for item with value array.
 ```
 
-La méthode peut être appelée à plusieurs reprises pour ajouter d'autres assertions.
+La méthode peut être appelée plusieurs fois pour ajouter plusieurs contraintes. Elle peut être combinée avec les appels à `transform()` et `castTo()`.
 
 
-Mappage vers les objets : from() .[#toc-mapping-to-objects-from]
-----------------------------------------------------------------
+Transformation : transform() .[#toc-transformation-transform]
+-------------------------------------------------------------
 
-Vous pouvez générer un schéma de structure à partir de la classe. Exemple :
+Les données validées avec succès peuvent être modifiées à l'aide d'une fonction personnalisée :
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+La méthode peut être appelée à plusieurs reprises pour ajouter des transformations multiples. Elle peut être combinée avec des appels à `assert()` et `castTo()`. Les opérations seront exécutées dans l'ordre dans lequel elles sont déclarées :
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Si vous utilisez PHP 7.4 ou plus, vous pouvez utiliser les types natifs :
+La méthode `transform()` peut transformer et valider la valeur simultanément. C'est souvent plus simple et moins redondant que d'enchaîner `transform()` et `assert()`. À cette fin, la fonction reçoit un objet [Contexte |api:Nette\Schema\Context] avec une méthode `addError()`, qui peut être utilisée pour ajouter des informations sur les problèmes de validation :
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Les classes anonymes sont également supportées :
+
+Casting : castTo() .[#toc-casting-castto]
+-----------------------------------------
+
+Les données validées avec succès peuvent être coulées :
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Comme les informations obtenues à partir de la définition de la classe peuvent ne pas être suffisantes, vous pouvez ajouter un schéma personnalisé pour les éléments avec le deuxième paramètre :
+En plus des types natifs de PHP, vous pouvez également utiliser des classes. Cela permet de distinguer s'il s'agit d'une classe simple sans constructeur ou d'une classe avec constructeur. Si la classe n'a pas de constructeur, une instance est créée et tous les éléments de la structure sont inscrits dans ses propriétés :
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting : castTo() .[#toc-casting-castto]
------------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Les données validées avec succès peuvent être coulées :
+Si la classe a un constructeur, les éléments de la structure sont transmis au constructeur en tant que paramètres nommés :
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-En plus des types natifs de PHP, vous pouvez également effectuer des castings vers des classes :
+La fonte combinée à un paramètre scalaire crée un objet et transmet la valeur comme seul paramètre au constructeur :
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, renvoie ['a', 'b', 'c']
 ```
 
+
+Mapping to Objects : from() .[#toc-mapping-to-objects-from]
+-----------------------------------------------------------
+
+Vous pouvez générer un schéma de structure à partir de la classe. Exemple :
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Les classes anonymes sont également prises en charge :
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Comme les informations obtenues à partir de la définition de la classe peuvent ne pas être suffisantes, vous pouvez ajouter un schéma personnalisé pour les éléments à l'aide du deuxième paramètre :
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/hu/@home.texy b/schema/hu/@home.texy
index bccac8b89b..1c9423063c 100644
--- a/schema/hu/@home.texy
+++ b/schema/hu/@home.texy
@@ -197,7 +197,7 @@ Struktúrák .[#toc-structures]
 
 A struktúrák meghatározott kulcsokkal rendelkező objektumok. A kulcs => érték párok mindegyikét "tulajdonságnak" nevezzük:
 
-A struktúrák tömböket és objektumokat fogadnak el, és objektumokat adnak vissza `stdClass` (hacsak nem változtatjuk meg a `castTo('array')`, stb. segítségével).
+A struktúrák tömböket és objektumokat fogadnak, és objektumokat adnak vissza `stdClass`.
 
 Alapértelmezés szerint minden tulajdonság opcionális, és alapértelmezett értéke `null`. Kötelező tulajdonságokat a `required()` segítségével lehet definiálni:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, visszatér {'optional' => null, 'nullable' => null}
 ```
 
+A `getShape()` módszer a struktúra összes tulajdonságát tartalmazó tömböt adja vissza.
+
 Alapértelmezés szerint a bemeneti adatokban nem lehetnek extra elemek:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // HIBA
 ```
 
+Új struktúrát hozhat létre egy másik struktúrából származtatva a `extend()` segítségével:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Array .[#toc-array]
+-------------------
+
+Meghatározott kulcsokkal rendelkező tömb. Ugyanazok a szabályok vonatkoznak rá, mint a [struktúrákra |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Definiálhatunk indexelt tömböt is, amelyet tuple-nek nevezünk:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Deprecations .[#toc-deprecations]
 ---------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Sikertelen "Páros elemek a tömbben" állítás a tömb értékű elemre.
 ```
 
-A metódus ismételten meghívható további állítások hozzáadásához.
+A módszer többször is meghívható, hogy több korlátozást adjon hozzá. A `transform()` és a `castTo()` hívásokkal keverhető.
 
 
-Objektumokra való leképezés: from() .[#toc-mapping-to-objects-from]
--------------------------------------------------------------------
+Transzformáció: transform() .[#toc-transformation-transform]
+------------------------------------------------------------
 
-Az osztályból struktúra sémát generálhatunk. Példa:
+A sikeresen érvényesített adatok egy egyéni függvény segítségével módosíthatók:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+A módszer ismételten meghívható több átalakítás hozzáadásához. Ez keverhető a `assert()` és a `castTo()` hívásaival. A műveletek a deklaráció sorrendjében kerülnek végrehajtásra:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Ha a PHP 7.4 vagy magasabb verziószámú PHP-t használ, használhat natív típusokat:
+A `transform()` módszer egyszerre tudja átalakítani és érvényesíteni az értéket. Ez gyakran egyszerűbb és kevésbé redundáns, mint a `transform()` és a `assert()` láncolása. Ehhez a funkció egy [Context |api:Nette\Schema\Context] objektumot kap egy `addError()` metódussal, amely az érvényesítési problémákra vonatkozó információk hozzáadására használható:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-A névtelen osztályok is támogatottak:
+
+Casting: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Sikeresen érvényesített adatok önthetők:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-A második paraméterrel egyéni sémát adhat az elemekhez, mivel az osztálydefinícióból kapott információ nem feltétlenül elegendő:
+A natív PHP-típusok mellett osztályokba is átvihetők. Megkülönbözteti, hogy egyszerű, konstruktor nélküli osztályról vagy konstruktorral rendelkező osztályról van-e szó. Ha az osztálynak nincs konstruktora, akkor létrejön egy példánya, és a struktúra minden elemét kiírja a tulajdonságaiba:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Sikeresen érvényesített adatok önthetők:
+Ha az osztálynak van konstruktora, akkor a struktúra elemeit a konstruktornak nevesített paraméterként adjuk át:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-A natív PHP-típusok mellett osztályokba is átvihetők:
+A skalár paraméterrel kombinált öntött objektum létrehoz egy objektumot, és az értéket adja át egyetlen paraméterként a konstruktornak:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, visszaadja ['a', 'b', 'c']
 ```
 
+
+Objektumokra való leképezés: from() .[#toc-mapping-to-objects-from]
+-------------------------------------------------------------------
+
+Az osztályból struktúra sémát generálhatunk. Példa:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Névtelen osztályok is támogatottak:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+A második paraméterrel egyéni sémát adhat az elemekhez, mivel az osztálydefinícióból kapott információk nem feltétlenül elegendőek:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/it/@home.texy b/schema/it/@home.texy
index 8904af0559..3b1faef1c6 100644
--- a/schema/it/@home.texy
+++ b/schema/it/@home.texy
@@ -197,7 +197,7 @@ Strutture .[#toc-structures]
 
 Le strutture sono oggetti con chiavi definite. Ciascuna di queste coppie chiave => valore viene definita "proprietà":
 
-Le strutture accettano array e oggetti e restituiscono oggetti `stdClass` (a meno che non si cambi con `castTo('array')`, ecc.).
+Le strutture accettano array e oggetti e restituiscono oggetti `stdClass`.
 
 Per impostazione predefinita, tutte le proprietà sono opzionali e hanno un valore predefinito di `null`. È possibile definire proprietà obbligatorie utilizzando `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, restituisce {'optional' => null, 'nullable' => null}
 ```
 
+L'array di tutte le proprietà della struttura viene restituito dal metodo `getShape()`.
+
 Per impostazione predefinita, non ci possono essere elementi extra nei dati di input:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERRORE
 ```
 
+È possibile creare una nuova struttura derivandola da un'altra utilizzando `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Schieramento .[#toc-array]
+--------------------------
+
+Un array con chiavi definite. Si applicano le stesse regole delle [strutture |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+È anche possibile definire un array indicizzato, noto come tupla:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Deprecazioni .[#toc-deprecations]
 ---------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Asserzione fallita "Elementi pari nell'array" per l'elemento con valore array.
 ```
 
-Il metodo può essere richiamato più volte per aggiungere altre asserzioni.
+Il metodo può essere richiamato più volte per aggiungere più vincoli. Può essere mescolato con le chiamate a `transform()` e `castTo()`.
 
 
-Mappatura a oggetti: from() .[#toc-mapping-to-objects-from]
------------------------------------------------------------
+Trasformazione: transform() .[#toc-transformation-transform]
+------------------------------------------------------------
 
-È possibile generare uno schema di struttura dalla classe. Esempio:
+I dati convalidati con successo possono essere modificati utilizzando una funzione personalizzata:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Il metodo può essere richiamato ripetutamente per aggiungere più trasformazioni. Può essere mescolato con le chiamate a `assert()` e `castTo()`. Le operazioni saranno eseguite nell'ordine in cui sono state dichiarate:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Se si utilizza PHP 7.4 o superiore, si possono usare i tipi nativi:
+Il metodo `transform()` può trasformare e convalidare il valore contemporaneamente. Spesso è più semplice e meno ridondante che concatenare `transform()` e `assert()`. A questo scopo, la funzione riceve un oggetto [Context |api:Nette\Schema\Context] con un metodo `addError()`, che può essere usato per aggiungere informazioni sui problemi di validazione:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Sono supportate anche le classi anonime:
+
+Casting: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+I dati convalidati con successo possono essere lanciati:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Poiché le informazioni ottenute dalla definizione della classe potrebbero non essere sufficienti, è possibile aggiungere uno schema personalizzato per gli elementi con il secondo parametro:
+Oltre ai tipi nativi di PHP, è possibile eseguire il cast su classi. Si distingue se si tratta di una classe semplice senza costruttore o di una classe con costruttore. Se la classe non ha un costruttore, ne viene creata un'istanza e tutti gli elementi della struttura vengono scritti nelle sue proprietà:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-I dati convalidati con successo possono essere lanciati:
+Se la classe ha un costruttore, gli elementi della struttura vengono passati come parametri al costruttore:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Oltre ai tipi nativi di PHP, è possibile eseguire il cast su classi:
+Il casting combinato con un parametro scalare crea un oggetto e passa il valore come unico parametro al costruttore:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, restituisce ['a', 'b', 'c']
 ```
 
+
+Mappatura a oggetti: from() .[#toc-mapping-to-objects-from]
+-----------------------------------------------------------
+
+È possibile generare uno schema di struttura dalla classe. Esempio:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Sono supportate anche le classi anonime:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Poiché le informazioni ottenute dalla definizione della classe potrebbero non essere sufficienti, è possibile aggiungere uno schema personalizzato per gli elementi con il secondo parametro:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/ja/@home.texy b/schema/ja/@home.texy
index 76554d052d..fba7d1b25e 100644
--- a/schema/ja/@home.texy
+++ b/schema/ja/@home.texy
@@ -197,7 +197,7 @@ Expect::anyOf(Expect::string('hello'), true, null)->firstIsDefault();
 
 構造体は、定義されたキーを持つオブジェクトである。このキー => 値のペアをそれぞれ「プロパティ」と呼びます。
 
-構造体は配列やオブジェクトを受け入れ、オブジェクトを返す`stdClass` (`castTo('array')`, などで変更しない限り)。
+構造体は配列やオブジェクトを受け入れ、オブジェクトを返す`stdClass` 。
 
 デフォルトでは、すべてのプロパティはオプションであり、デフォルト値は`null` です。必須プロパティは`required()` を使って定義できます。
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, returns {'optional' => null, 'nullable' => null}
 ```
 
+すべての構造体プロパティの配列は、`getShape()` メソッドによって返される。
+
 デフォルトでは、入力データに余分な項目は存在できない。
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+`extend()` を使って別の構造から派生させることで、新しい構造を作成できます:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+配列.[#toc-array]
+---------------
+
+定義されたキーを持つ配列。[構造 |#structure]体と同じルールが適用されます。
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+タプルと呼ばれるインデックス付き配列を定義することもできます:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 非推奨事項 .[#toc-deprecations]
 --------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Failed assertion "Even items in array" for item with value array.
 ```
 
-このメソッドは、繰り返しコールしてアサーションを追加することができます。
+このメソッドは、複数の制約を追加するために繰り返し呼び出すことができる。これは、`transform()` と`castTo()` の呼び出しと混在させることができます。
 
 
-オブジェクトへのマッピング: from() .[#toc-mapping-to-objects-from]
------------------------------------------------------
+変換: transform() .[#toc-transformation-transform]
+------------------------------------------------
 
-クラスから構造体スキーマを生成することができます。例
+バリデーションに成功したデータは、カスタム関数を使用して変更することができます:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+このメソッドを繰り返し呼び出すことで、複数の変換を加えることができる。このメソッドは、`assert()` や`castTo()` の呼び出しと混在させることができる。操作は宣言された順番に実行される:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-PHP 7.4 以降を使用している場合は、ネイティブタイプを使用することができます。
+`transform()` メソッドは、値の変換と検証を同時に行うことができる。これは、`transform()` と`assert()` を連鎖させるよりも単純で冗長性が少ないことが多い。この目的のために、この関数は`addError()` メソッドを持つ[Context |api:Nette\Schema\Context]オブジェクトを受け取ります:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-匿名クラスもサポートされています。
+
+キャスト: castTo() .[#toc-casting-castto]
+-------------------------------------
+
+バリデーションに成功したデータをキャストすることができます:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-クラス定義から得られる情報だけでは十分でない場合があるため、2番目のパラメータで要素にカスタムスキーマを追加することができます。
+PHP ネイティブの型に加えて、クラスへのキャストも可能です。これは、コンストラクタのない単純なクラスなのかコンストラクタのあるクラスなのかを区別します。コンストラクタのないクラスの場合は、そのインスタンスが作成され、 構造体のすべての要素がそのプロパティに書き込まれます:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-キャスト: castTo() .[#toc-casting-castto]
--------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-バリデーションに成功したデータをキャストすることができます。
+コンストラクタを持つクラスの場合、構造体の要素は名前付きパラメータとしてコンストラクタに渡されます:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-PHP のネイティブな型だけでなく、クラスへのキャストも可能です。
+キャストとスカラー・パラメータを組み合わせると、オブジェクトが生成され、その値が唯一のパラメータとしてコンストラクタに渡されます:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, returns ['a', 'b', 'c']
 ```
 
-{{leftbar: nette:en:@menu-topics}}
+
+オブジェクトへのマッピング: from() .[#toc-mapping-to-objects-from]
+-----------------------------------------------------
+
+クラスから構造スキーマを生成することができます。例
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+匿名クラスもサポートされています:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+クラス定義から得られる情報だけでは十分でない可能性があるため、2番目のパラメータで要素のカスタム・スキーマを追加できます:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
+{{leftbar: nette:@menu-topics}}
diff --git a/schema/pl/@home.texy b/schema/pl/@home.texy
index 4e9930ca5b..28adaf5933 100644
--- a/schema/pl/@home.texy
+++ b/schema/pl/@home.texy
@@ -197,7 +197,7 @@ Struktury .[#toc-structures]
 
 Struktury to obiekty o zdefiniowanych kluczach. Każda z par klucz => wartość jest określana jako "właściwość":
 
-Struktury przyjmują tablice i obiekty i zwracają `stdClass` obiekty (chyba że zmienisz to za pomocą `castTo('array')` itp.).
+Struktury akceptują tablice i obiekty oraz zwracają obiekty `stdClass`.
 
 Domyślnie wszystkie właściwości są opcjonalne i domyślnie ustawione na `null`. Możesz zdefiniować właściwości obowiązkowe używając `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, vrací {'optional' => null, 'nullable' => null}
 ```
 
+Tablica wszystkich właściwości struktury jest zwracana przez metodę `getShape()`.
+
 Domyślnie w danych wejściowych nie może być żadnych dodatkowych elementów:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // CHYBA
 ```
 
+Nową strukturę można utworzyć poprzez wyprowadzenie jej z innej za pomocą `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Tablica .[#toc-array]
+---------------------
+
+Tablica ze zdefiniowanymi kluczami. Obowiązują te same zasady, co w przypadku [struktur |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Można również zdefiniować tablicę indeksowaną, znaną jako krotka:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Właściwości przestarzałe .[#toc-deprecations]
 ---------------------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Failed assertion "Even items in array" for item with value array.
 ```
 
-Metoda ta może być wywoływana wielokrotnie, aby dodać więcej ograniczeń.
+Metoda ta może być wywoływana wielokrotnie w celu dodania wielu ograniczeń. Można ją łączyć z wywołaniami `transform()` i `castTo()`.
 
 
-Mapowanie na obiekty: from() .[#toc-mapping-to-objects-from]
-------------------------------------------------------------
+Transformacja: transform() .[#toc-transformation-transform]
+-----------------------------------------------------------
 
-Możemy mieć schemat struktury wygenerowany z klasy. Przykład:
+Pomyślnie zweryfikowane dane można modyfikować za pomocą funkcji niestandardowej:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'franta',
-];
+Metoda ta może być wywoływana wielokrotnie w celu dodania wielu przekształceń. Można ją mieszać z wywołaniami `assert()` i `castTo()`. Operacje będą wykonywane w kolejności, w jakiej zostały zadeklarowane:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'franta', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Jeśli używasz PHP 7.4 lub nowszego, możesz użyć typów natywnych:
+Metoda `transform()` może jednocześnie przekształcać i weryfikować wartość. Jest to często prostsze i mniej zbędne niż łączenie metod `transform()` i `assert()`. W tym celu funkcja otrzymuje obiekt [Context |api:Nette\Schema\Context] z metodą `addError()`, która może być użyta do dodania informacji o kwestiach walidacji:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Obsługiwane są również klasy anonimowe:
+
+Casting: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Pomyślnie zweryfikowane dane mogą być rzutowane:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Ponieważ informacje uzyskane z definicji klasy mogą nie być wystarczające, możesz użyć drugiego parametru, aby dodać własny schemat do elementów:
+Oprócz natywnych typów PHP, można również rzutować na klasy. Rozróżnia to, czy jest to prosta klasa bez konstruktora, czy klasa z konstruktorem. Jeśli klasa nie ma konstruktora, tworzona jest jej instancja, a wszystkie elementy struktury są zapisywane w jej właściwościach:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Override: castTo() .[#toc-casting-castto]
------------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Pomyślnie zwalidowane dane mogą zostać poddane repatriacji:
+Jeśli klasa ma konstruktor, elementy struktury są przekazywane jako nazwane parametry do konstruktora:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Oprócz natywnych typów PHP, może być również przepisany na klasy:
+Rzutowanie w połączeniu z parametrem skalarnym tworzy obiekt i przekazuje wartość jako jedyny parametr do konstruktora:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -444,4 +495,47 @@ $normalized = $processor->process($schema, 'a b c');
 ```
 
 
+Mapowanie do obiektów: from() .[#toc-mapping-to-objects-from]
+-------------------------------------------------------------
+
+Można wygenerować schemat struktury z klasy. Przykład:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Obsługiwane są również klasy anonimowe:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Ponieważ informacje uzyskane z definicji klasy mogą nie być wystarczające, można dodać niestandardowy schemat dla elementów za pomocą drugiego parametru:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
+{{leftbar: nette:@menu-topics}}
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/pt/@home.texy b/schema/pt/@home.texy
index 0184591815..71c816a2bb 100644
--- a/schema/pt/@home.texy
+++ b/schema/pt/@home.texy
@@ -197,7 +197,7 @@ Estruturas .[#toc-structures]
 
 As estruturas são objetos com chaves definidas. Cada uma destas chaves => pares de valores é chamada de "propriedade":
 
-As estruturas aceitam matrizes e objetos e retornam objetos `stdClass` (a menos que você altere com `castTo('array')`, etc.).
+As estruturas aceitam matrizes e objetos e retornam objetos `stdClass`.
 
 Por padrão, todas as propriedades são opcionais e têm um valor padrão de `null`. Você pode definir propriedades obrigatórias usando `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, retorna {'opcional' => nulo, 'anulável' => nulo}
 ```
 
+A matriz de todas as propriedades da estrutura é retornada pelo método `getShape()`.
+
 Por padrão, não pode haver itens extras nos dados de entrada:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+Você pode criar uma nova estrutura derivando de outra usando `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Matriz .[#toc-array]
+--------------------
+
+Uma matriz com chaves definidas. Aplicam-se as mesmas regras das [estruturas |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Você também pode definir uma matriz indexada, conhecida como tupla:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Depreciações .[#toc-deprecations]
 ---------------------------------
@@ -353,83 +393,94 @@ $processor->process($schema, ['a', 'b', 'c']);
 // afirmação falhada "Itens pares na matriz" para item com matriz de valores.
 ```
 
-O método pode ser chamado repetidamente para acrescentar mais afirmações.
+O método pode ser chamado repetidamente para adicionar várias restrições. Ele pode ser misturado com chamadas para `transform()` e `castTo()`.
 
 
-Mapeamento para Objetos: de() .[#toc-mapping-to-objects-from]
--------------------------------------------------------------
+Transformação: transform() .[#toc-transformation-transform]
+-----------------------------------------------------------
 
-Você pode gerar um esquema de estrutura a partir da classe. Exemplo:
+Os dados validados com sucesso podem ser modificados usando uma função personalizada:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$schema = Expect::from(new Config);
+O método pode ser chamado repetidamente para adicionar várias transformações. Ele pode ser misturado com chamadas para `assert()` e `castTo()`. As operações serão executadas na ordem em que forem declaradas:
 
-$data = [
-	'name' => 'jeff',
-];
-
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Se você estiver usando PHP 7.4 ou superior, você pode usar tipos nativos:
+O método `transform()` pode transformar e validar o valor simultaneamente. Isso geralmente é mais simples e menos redundante do que encadear `transform()` e `assert()`. Para esse fim, a função recebe um objeto [Context |api:Nette\Schema\Context] com um método `addError()`, que pode ser usado para adicionar informações sobre problemas de validação:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Aulas anônimas também são suportadas:
+
+Transmissão: castTo() .[#toc-casting-castto]
+--------------------------------------------
+
+Os dados validados com sucesso podem ser convertidos:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Como as informações obtidas da definição de classe podem não ser suficientes, pode-se adicionar um esquema personalizado para os elementos com o segundo parâmetro:
+Além dos tipos nativos do PHP, você também pode converter para classes. Ele distingue se é uma classe simples sem um construtor ou uma classe com um construtor. Se a classe não tiver um construtor, será criada uma instância dela e todos os elementos da estrutura serão gravados em suas propriedades:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Fundição: castTo() .[#toc-casting-castto]
------------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Os dados validados com sucesso podem ser lançados:
+Se a classe tiver um construtor, os elementos da estrutura serão passados como parâmetros nomeados para o construtor:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Além dos tipos de PHP nativos, você também pode participar de aulas:
+A conversão combinada com um parâmetro escalar cria um objeto e passa o valor como o único parâmetro para o construtor:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
-Normalização: antes() .[#toc-normalization-before]
---------------------------------------------------
+Normalização: before() .[#toc-normalization-before]
+---------------------------------------------------
 
 Antes da validação propriamente dita, os dados podem ser normalizados usando o método `before()`. Como exemplo, vamos ter um elemento que deve ser um conjunto de cordas (por exemplo `['a', 'b', 'c']`), mas recebe entrada sob a forma de um cordel `a b c`:
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, retorna ['a', 'b', 'c']
 ```
 
+
+Mapeamento para objetos: from() .[#toc-mapping-to-objects-from]
+---------------------------------------------------------------
+
+Você pode gerar um esquema de estrutura a partir da classe. Exemplo:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Também há suporte para classes anônimas:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Como as informações obtidas da definição da classe podem não ser suficientes, você pode adicionar um esquema personalizado para os elementos com o segundo parâmetro:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/ro/@home.texy b/schema/ro/@home.texy
index 8c257c1e51..2e0b9582ad 100644
--- a/schema/ro/@home.texy
+++ b/schema/ro/@home.texy
@@ -197,7 +197,7 @@ Structuri .[#toc-structures]
 
 Structurile sunt obiecte cu chei definite. Fiecare dintre aceste perechi cheie => valoare este denumită "proprietate":
 
-Structurile acceptă matrici și obiecte și returnează obiecte `stdClass` (dacă nu se modifică cu `castTo('array')`, etc.).
+Structurile acceptă matrici și obiecte și returnează obiecte `stdClass`.
 
 În mod implicit, toate proprietățile sunt opționale și au o valoare implicită de `null`. Puteți defini proprietățile obligatorii utilizând `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, returnează {'optional' => null, 'nullable' => null}
 ```
 
+Matricea tuturor proprietăților structurii este returnată de metoda `getShape()`.
+
 În mod implicit, nu pot exista elemente suplimentare în datele de intrare:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+Puteți crea o structură nouă derivând din alta folosind `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Array .[#toc-array]
+-------------------
+
+Un array cu chei definite. Se aplică aceleași reguli ca pentru [structuri |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+De asemenea, puteți defini un array indexat, cunoscut sub numele de tuple:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Deprecieri .[#toc-deprecations]
 -------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // A eșuat aserțiunea "Even items in array" pentru elementul cu valoarea array.
 ```
 
-Metoda poate fi apelată în mod repetat pentru a adăuga mai multe afirmații.
+Metoda poate fi apelată în mod repetat pentru a adăuga mai multe constrângeri. Ea poate fi amestecată cu apelurile la `transform()` și `castTo()`.
 
 
-Maparea în obiecte: from() .[#toc-mapping-to-objects-from]
+Transformare: transform() .[#toc-transformation-transform]
 ----------------------------------------------------------
 
-Puteți genera o schemă de structură din clasă. Exemplu:
+Datele validate cu succes pot fi modificate cu ajutorul unei funcții personalizate:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Metoda poate fi apelată în mod repetat pentru a adăuga mai multe transformări. Ea poate fi amestecată cu apeluri la `assert()` și `castTo()`. Operațiile vor fi executate în ordinea în care sunt declarate:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Dacă utilizați PHP 7.4 sau o versiune mai recentă, puteți utiliza tipuri native:
+Metoda `transform()` poate transforma și valida valoarea simultan. Acest lucru este adesea mai simplu și mai puțin redundant decât înlănțuirea `transform()` și `assert()`. În acest scop, funcția primește un obiect [Context |api:Nette\Schema\Context] cu o metodă `addError()`, care poate fi utilizată pentru a adăuga informații despre problemele de validare:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Clasele anonime sunt, de asemenea, acceptate:
+
+Casting: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Datele validate cu succes pot fi turnate:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Deoarece este posibil ca informațiile obținute din definiția clasei să nu fie suficiente, puteți adăuga o schemă personalizată pentru elemente cu ajutorul celui de-al doilea parametru:
+În plus față de tipurile native PHP, puteți, de asemenea, să faceți cast la clase. Se distinge dacă este vorba de o clasă simplă fără constructor sau de o clasă cu constructor. În cazul în care clasa nu are constructor, se creează o instanță a acesteia și toate elementele structurii sunt scrise în proprietățile sale:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Casting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Datele validate cu succes pot fi turnate:
+În cazul în care clasa are un constructor, elementele structurii sunt transmise constructorului ca parametri numiți:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-În plus față de tipurile native PHP, puteți, de asemenea, să faceți cast la clase:
+Castingul combinat cu un parametru scalar creează un obiect și transmite valoarea acestuia ca unic parametru către constructor:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, returnează ['a', 'b', 'c']
 ```
 
+
+Maparea în obiecte: from() .[#toc-mapping-to-objects-from]
+----------------------------------------------------------
+
+Puteți genera o schemă de structură din clasă. Exemplu:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Sunt acceptate și clasele anonime:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Deoarece este posibil ca informațiile obținute din definiția clasei să nu fie suficiente, puteți adăuga o schemă personalizată pentru elemente cu ajutorul celui de-al doilea parametru:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/ru/@home.texy b/schema/ru/@home.texy
index a0c7ce1de8..7f87c34c55 100644
--- a/schema/ru/@home.texy
+++ b/schema/ru/@home.texy
@@ -197,7 +197,7 @@ Expect::anyOf(Expect::string('hello'), true, null)->firstIsDefault();
 
 Структуры — это объекты с определенными ключами. Каждая из этих пар ключ => значение называется "свойством":
 
-Структуры принимают массивы и объекты и возвращают объекты `stdClass` (если вы не измените его с помощью `castTo('array')` и т. д.).
+Структуры принимают массивы и объекты и возвращают объекты `stdClass`.
 
 По умолчанию все свойства являются необязательными и имеют значение по умолчанию `null`. Вы можете определить обязательные свойства, используя `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, возвращает {'optional' => null, 'nullable' => null}
 ```
 
+Массив всех свойств структуры возвращается методом `getShape()`.
+
 По умолчанию, во входных данных не может быть лишних элементов:
 
 ```php
@@ -263,9 +265,47 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ОШИБКА
 ```
 
+Вы можете создать новую структуру, производя ее от другой с помощью `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Массив .[#toc-array]
+--------------------
+
+Массив с определенными ключами. Применяются те же правила, что и для [структур |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Вы также можете определить индексированный массив, известный как кортеж:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
-Устаревшие элементы .{data-version:1.1}
----------------------------------------
+Устаревшие элементы
+-------------------
 
 Вы можете объявить свойство устаревшим, используя метод `deprecated([string $message])`. Уведомления об устаревании возвращаются с помощью `$processor->getWarnings()`:
 
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Неудачное утверждение "Четные элементы в массиве" для элемента с массивом значений.
 ```
 
-Этот метод можно вызывать многократно для добавления новых утверждений.
+Этот метод можно вызывать многократно для добавления нескольких ограничений. Его можно смешивать с вызовами `transform()` и `castTo()`.
 
 
-Сопоставление с объектами: from()
----------------------------------
+Трансформация: transform() .[#toc-transformation-transform]
+-----------------------------------------------------------
 
-Из класса можно сгенерировать схему структуры. Пример:
+Успешно подтвержденные данные могут быть изменены с помощью пользовательской функции:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Этот метод можно вызывать многократно для добавления нескольких преобразований. Он может перемежаться с вызовами `assert()` и `castTo()`. Операции будут выполняться в том порядке, в котором они объявлены:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Если вы используете PHP 7.4 или выше, вы можете использовать встроенные типы:
+Метод `transform()` может одновременно преобразовывать и проверять значение. Это часто проще и менее избыточно, чем выстраивание цепочек `transform()` и `assert()`. Для этого функция получает объект [Context |api:Nette\Schema\Context] с методом `addError()`, который может быть использован для добавления информации о проблемах валидации:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Поддерживаются также анонимные классы:
+
+Кастинг: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Успешно проверенные данные могут быть приведены:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Поскольку информации, полученной из определения класса, может быть недостаточно, вы можете добавить пользовательскую схему для элементов с помощью второго параметра:
+Помимо собственных типов PHP, можно также приводить данные к классам. При этом различается, является ли это простой класс без конструктора или класс с конструктором. Если класс не имеет конструктора, то создается его экземпляр и в его свойства записываются все элементы структуры:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Приведение: castTo()
---------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Успешно проверенные данные могут быть отброшены:
+Если класс имеет конструктор, то элементы структуры передаются конструктору в качестве именованных параметров:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-В дополнение к собственным типам PHP, вы также можете приводить к классам:
+Кастинг в сочетании со скалярным параметром создает объект и передает его значение в качестве единственного параметра конструктору:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, возвращает ['a', 'b', 'c']
 ```
 
+
+Отображение на объекты: from() .[#toc-mapping-to-objects-from]
+--------------------------------------------------------------
+
+Из класса можно сгенерировать структурную схему. Пример:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Поддерживаются также анонимные классы:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Поскольку информации, полученной из определения класса, может быть недостаточно, можно добавить пользовательскую схему для элементов с помощью второго параметра:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/sl/@home.texy b/schema/sl/@home.texy
index 9af7ea6247..0c432ad504 100644
--- a/schema/sl/@home.texy
+++ b/schema/sl/@home.texy
@@ -197,7 +197,7 @@ Strukture .[#toc-structures]
 
 Strukture so predmeti z določenimi ključi. Vsak od teh parov ključ => vrednost se imenuje "lastnost":
 
-Strukture sprejemajo polja in predmete ter vračajo predmete `stdClass` (razen če jih spremenite s `castTo('array')`, itd.).
+Strukture sprejemajo polja in predmete ter vračajo predmete `stdClass`.
 
 Privzeto so vse lastnosti neobvezne in imajo privzeto vrednost `null`. Obvezne lastnosti lahko določite z uporabo `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // V redu, vrne {'optional' => null, 'nullable' => null}
 ```
 
+Metoda `getShape()` vrne polje vseh lastnosti strukture.
+
 Privzeto je, da v vhodnih podatkih ne sme biti nobenih dodatnih elementov:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // V REDU
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+Novo strukturo lahko ustvarite tako, da jo izpeljete iz druge strukture z uporabo `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Polje .[#toc-array]
+-------------------
+
+Polje z določenimi ključi. Veljajo enaka pravila kot za [strukture |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Opredelite lahko tudi indeksirano polje, znano kot tuple:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Deprecations .[#toc-deprecations]
 ---------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Neuspešna trditev "Even items in array" za element z vrednostjo array.
 ```
 
-Metodo lahko večkrat pokličete, če želite dodati več trditev.
+Metodo lahko večkrat pokličete, če želite dodati več omejitev. Lahko se meša s klici na `transform()` in `castTo()`.
 
 
-Prikazovanje v predmete: from() .[#toc-mapping-to-objects-from]
----------------------------------------------------------------
+Transformacija: transform() .[#toc-transformation-transform]
+------------------------------------------------------------
 
-Iz razreda lahko ustvarite strukturno shemo. Primer:
+Uspešno potrjene podatke lahko spremenite s funkcijo po meri:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Metodo je mogoče poklicati večkrat, da se doda več preoblikovanj. Lahko se meša s klici na `assert()` in `castTo()`. Operacije se izvedejo v vrstnem redu, v katerem so deklarirane:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Če uporabljate PHP 7.4 ali novejši, lahko uporabite nativne tipe:
+Metoda `transform()` lahko hkrati preoblikuje in potrdi vrednost. To je pogosto preprostejše in manj odvečno kot veriženje metod `transform()` in `assert()`. V ta namen funkcija prejme objekt [Context |api:Nette\Schema\Context] z metodo `addError()`, ki jo lahko uporabimo za dodajanje informacij o težavah pri potrjevanju:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Podprti so tudi anonimni razredi:
+
+Oddajanje: castTo() .[#toc-casting-castto]
+------------------------------------------
+
+Uspešno potrjene podatke je mogoče oddati:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Ker informacije, pridobljene iz definicije razreda, morda ne zadostujejo, lahko z drugim parametrom dodate shemo po meri za elemente:
+Poleg izvornih tipov PHP lahko podatke prelijete tudi v razrede. Razlikuje, ali gre za preprost razred brez konstruktorja ali razred s konstruktorjem. Če razred nima konstruktorja, se ustvari njegov primerek, vsi elementi strukture pa se zapišejo v njegove lastnosti:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Kasting: castTo() .[#toc-casting-castto]
-----------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Uspešno potrjene podatke je mogoče oddati:
+Če ima razred konstruktor, se elementi strukture konstruktorju posredujejo kot poimenovani parametri:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Poleg nativnih tipov PHP lahko podatke prelijete tudi v razrede:
+Casting v kombinaciji s skalarnim parametrom ustvari objekt in konstruktorju posreduje vrednost kot edini parameter:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // V redu, vrne ['a', 'b', 'c']
 ```
 
+
+preslikava v predmete: from() .[#toc-mapping-to-objects-from]
+-------------------------------------------------------------
+
+Iz razreda lahko ustvarite strukturno shemo. Primer:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Podprti so tudi anonimni razredi:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Ker informacije, pridobljene iz definicije razreda, morda ne zadostujejo, lahko z drugim parametrom dodate shemo po meri za elemente:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/tr/@home.texy b/schema/tr/@home.texy
index 738448d658..47ba016283 100644
--- a/schema/tr/@home.texy
+++ b/schema/tr/@home.texy
@@ -197,7 +197,7 @@ Yapılar .[#toc-structures]
 
 Yapılar, tanımlanmış anahtarları olan nesnelerdir. Bu anahtar => değer çiftlerinin her biri "özellik" olarak adlandırılır:
 
-Yapılar dizileri ve nesneleri kabul eder ve `stdClass` nesnelerini döndürür ( `castTo('array')`, vb. ile değiştirmediğiniz sürece).
+Yapılar dizileri ve nesneleri kabul eder ve nesneleri döndürür `stdClass`.
 
 Varsayılan olarak, tüm özellikler isteğe bağlıdır ve varsayılan değerleri `null` şeklindedir. `required()` adresini kullanarak zorunlu özellikleri tanımlayabilirsiniz:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // Tamam, {'optional' => null, 'nullable' => null} döndürür
 ```
 
+Tüm yapı özelliklerinin dizisi `getShape()` yöntemi tarafından döndürülür.
+
 Varsayılan olarak, giriş verilerinde fazladan öğe bulunamaz:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // Tamam
 $processor->process($schema, ['additional' => true]); // ERROR
 ```
 
+`extend()` adresini kullanarak başka bir yapıdan türeterek yeni bir yapı oluşturabilirsiniz:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Dizi .[#toc-array]
+------------------
+
+Tanımlanmış anahtarları olan bir dizi. [Yapılar |#structure] için geçerli olan kuralların aynısı geçerlidir.
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Ayrıca tuple olarak bilinen indeksli bir dizi de tanımlayabilirsiniz:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Kullanımdan kaldırmalar .[#toc-deprecations]
 --------------------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // array değerine sahip öğe için "Even items in array" iddiası başarısız oldu.
 ```
 
-Yöntem, daha fazla onay eklemek için tekrar tekrar çağrılabilir.
+Yöntem, birden fazla kısıtlama eklemek için tekrar tekrar çağrılabilir. `transform()` ve `castTo()` çağrıları ile karıştırılabilir.
 
 
-Nesnelere Eşleme: from() .[#toc-mapping-to-objects-from]
---------------------------------------------------------
+Dönüşüm: transform() .[#toc-transformation-transform]
+-----------------------------------------------------
 
-Sınıftan yapı şeması oluşturabilirsiniz. Örnek:
+Başarıyla doğrulanan veriler özel bir işlev kullanılarak değiştirilebilir:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Yöntem, birden fazla dönüşüm eklemek için tekrar tekrar çağrılabilir. `assert()` ve `castTo()` çağrıları ile karıştırılabilir. İşlemler bildirildikleri sırayla yürütülecektir:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-PHP 7.4 veya daha üstünü kullanıyorsanız, yerel türleri kullanabilirsiniz:
+ `transform()` yöntemi değeri aynı anda hem dönüştürebilir hem de doğrulayabilir. Bu genellikle `transform()` ve `assert()` zincirlemesinden daha basit ve daha az gereksizdir. Bu amaçla, fonksiyon, doğrulama sorunları hakkında bilgi eklemek için kullanılabilecek bir `addError()` yöntemine sahip bir [Context |api:Nette\Schema\Context] nesnesi alır:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Anonim sınıflar da desteklenmektedir:
+
+Döküm: castTo() .[#toc-casting-castto]
+--------------------------------------
+
+Başarıyla doğrulanan veriler dökülebilir:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Sınıf tanımından elde edilen bilgiler yeterli olmayabileceğinden, ikinci parametre ile elemanlar için özel bir şema ekleyebilirsiniz:
+Yerel PHP türlerine ek olarak, sınıflara da döküm yapabilirsiniz. Yapıcısı olmayan basit bir sınıf mı yoksa yapıcısı olan bir sınıf mı olduğu ayırt edilir. Sınıfın kurucusu yoksa, bir örneği oluşturulur ve yapının tüm elemanları özelliklerine yazılır:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Döküm: castTo() .[#toc-casting-castto]
---------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Başarıyla doğrulanan veriler dökülebilir:
+Sınıfın bir yapıcısı varsa, yapının elemanları yapıcıya adlandırılmış parametreler olarak geçirilir:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-Yerel PHP türlerine ek olarak, sınıflara da döküm yapabilirsiniz:
+Bir skaler parametre ile birlikte döküm bir nesne oluşturur ve değeri yapıcıya tek parametre olarak geçirir:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // Tamam, ['a', 'b', 'c'] döndürür
 ```
 
+
+Nesnelere Eşleme: from() .[#toc-mapping-to-objects-from]
+--------------------------------------------------------
+
+Sınıftan yapı şeması oluşturabilirsiniz. Örnek:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Anonim sınıflar da desteklenmektedir:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Sınıf tanımından elde edilen bilgiler yeterli olmayabileceğinden, ikinci parametre ile elemanlar için özel bir şema ekleyebilirsiniz:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/schema/uk/@home.texy b/schema/uk/@home.texy
index 38bcea526e..fa6b9d5b4c 100644
--- a/schema/uk/@home.texy
+++ b/schema/uk/@home.texy
@@ -197,7 +197,7 @@ Expect::anyOf(Expect::string('hello'), true, null)->firstIsDefault();
 
 Структури - це об'єкти з певними ключами. Кожна з цих пар ключ => значення називається "властивістю":
 
-Структури приймають масиви та об'єкти і повертають об'єкти `stdClass` (якщо ви не зміните його за допомогою `castTo('array')` тощо).
+Структури приймають масиви та об'єкти і повертають об'єкти `stdClass`.
 
 За замовчуванням усі властивості є необов'язковими і мають значення за замовчуванням `null`. Ви можете визначити обов'язкові властивості, використовуючи `required()`:
 
@@ -241,6 +241,8 @@ $processor->process($schema, ['nullable' => null]);
 // OK, повертає {'optional' => null, 'nullable' => null}
 ```
 
+Масив усіх властивостей структури повертається методом `getShape()`.
+
 За замовчуванням, у вхідних даних не може бути зайвих елементів:
 
 ```php
@@ -263,6 +265,44 @@ $processor->process($schema, ['additional' => 1]); // OK
 $processor->process($schema, ['additional' => true]); // ПОМИЛКА
 ```
 
+Ви можете створити нову структуру, виводячи її з іншої за допомогою `extend()`:
+
+```php
+$dog = Expect::structure([
+	'name' => Expect::string(),
+	'age' => Expect::int(),
+]);
+
+$dogWithBreed = $dog->extend([
+	'breed' => Expect::string(),
+]);
+```
+
+
+Масив .[#toc-array]
+-------------------
+
+Масив з визначеними ключами. Застосовуються ті ж правила, що і для [структур |#structure].
+
+```php
+$schema = Expect::array([
+	'required' => Expect::string()->required(),
+	'optional' => Expect::string(), // default value is null
+]);
+```
+
+Ви також можете визначити індексований масив, відомий як кортеж:
+
+```php
+$schema = Expect::array([
+	Expect::int(),
+	Expect::string(),
+	Expect::bool(),
+]);
+
+$processor->process($schema, [1, 'hello', true]); // OK
+```
+
 
 Застарілі елементи .[#toc-ustarevsie-elementy]
 ----------------------------------------------
@@ -353,78 +393,89 @@ $processor->process($schema, ['a', 'b', 'c']);
 // Невдале твердження "Парні елементи в масиві" для елемента з масивом значень.
 ```
 
-Цей метод можна викликати багаторазово для додавання нових тверджень.
+Метод можна викликати багаторазово, щоб додати кілька обмежень. Його можна змішувати з викликами `transform()` та `castTo()`.
 
 
-Зіставлення з об'єктами: from() .[#toc-sopostavlenie-s-ob-ektami-from]
-----------------------------------------------------------------------
+Перетворення: transform() .[#toc-transformation-transform]
+----------------------------------------------------------
 
-З класу можна згенерувати схему структури. Приклад:
+Успішно перевірені дані можна змінити за допомогою спеціальної функції:
 
 ```php
-class Config
-{
-	public string $name;
-	public string|null $password;
-	public bool $admin = false;
-}
-
-$schema = Expect::from(new Config);
+// conversion to uppercase:
+Expect::string()->transform(fn(string $s) => strtoupper($s));
+```
 
-$data = [
-	'name' => 'jeff',
-];
+Метод можна викликати багаторазово, щоб додати кілька перетворень. Його можна змішувати з викликами `assert()` та `castTo()`. Операції будуть виконані в тому порядку, в якому вони були оголошені:
 
-$normalized = $processor->process($schema, $data);
-// $normalized instanceof Config
-// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```php
+Expect::type('string|int')
+	->castTo('string')
+	->assert('ctype_lower', 'All characters must be lowercased')
+	->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
 ```
 
-Якщо ви використовуєте PHP 7.4 або вище, ви можете використовувати вбудовані типи:
+Метод `transform()` може одночасно перетворювати і перевіряти значення. Часто це простіше і менш надлишково, ніж ланцюжок `transform()` і `assert()`. Для цього функція отримує об'єкт [Context |api:Nette\Schema\Context] з методом `addError()`, який можна використовувати для додавання інформації про проблеми з валідацією:
 
 ```php
-class Config
-{
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-}
+Expect::string()
+	->transform(function (string $s, Nette\Schema\Context $context) {
+		if (!ctype_lower($s)) {
+			$context->addError('All characters must be lowercased', 'my.case.error');
+			return null;
+		}
 
-$schema = Expect::from(new Config);
+		return strtoupper($s);
+	});
 ```
 
-Підтримуються також анонімні класи:
+
+Кастинг: castTo() .[#toc-casting-castto]
+----------------------------------------
+
+Успішно перевірені дані можуть бути закинуті:
 
 ```php
-$schema = Expect::from(new class {
-	public string $name;
-	public ?string $password;
-	public bool $admin = false;
-});
+Expect::scalar()->castTo('string');
 ```
 
-Оскільки інформації, отриманої з визначення класу, може бути недостатньо, ви можете додати користувацьку схему для елементів за допомогою другого параметра:
+На додаток до власних типів PHP, ви також можете виконувати приведення до класів. При цьому розрізняється, чи це простий клас без конструктора, чи клас з конструктором. Якщо клас не має конструктора, створюється його екземпляр і всі елементи структури записуються в його властивості:
 
 ```php
-$schema = Expect::from(new Config, [
-	'name' => Expect::string()->pattern('\w:.*'),
-]);
-```
+class Info
+{
+	public bool $processRefund;
+	public int $refundAmount;
+}
 
+Expect::structure([
+	'processRefund' => Expect::bool(),
+	'refundAmount' => Expect::int(),
+])->castTo(Info::class);
 
-Приведення: castTo() .[#toc-privedenie-castto]
-----------------------------------------------
+// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount
+```
 
-Успішно перевірені дані можуть бути відкинуті:
+Якщо клас має конструктор, то елементи структури передаються як іменовані параметри до конструктора:
 
 ```php
-Expect::scalar()->castTo('string');
+class Info
+{
+	public function __construct(
+		public bool $processRefund,
+		public int $refundAmount,
+	) {
+	}
+}
+
+// creates $obj = new Info(processRefund: ..., refundAmount: ...)
 ```
 
-На додаток до власних типів PHP, ви також можете приводити до класів:
+Приведення у поєднанні зі скалярним параметром створює об'єкт і передає значення як єдиний параметр до конструктора:
 
 ```php
-Expect::scalar()->castTo('AddressEntity');
+Expect::string()->castTo(DateTime::class);
+// creates new DateTime(...)
 ```
 
 
@@ -443,4 +494,47 @@ $normalized = $processor->process($schema, 'a b c');
 // OK, повертає ['a', 'b', 'c']
 ```
 
+
+Відображення на об'єкти: from() .[#toc-mapping-to-objects-from]
+---------------------------------------------------------------
+
+Ви можете згенерувати схему структури з класу. Приклад:
+
+```php
+class Config
+{
+	public string $name;
+	public string|null $password;
+	public bool $admin = false;
+}
+
+$schema = Expect::from(new Config);
+
+$data = [
+	'name' => 'jeff',
+];
+
+$normalized = $processor->process($schema, $data);
+// $normalized instanceof Config
+// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false}
+```
+
+Також підтримуються анонімні класи:
+
+```php
+$schema = Expect::from(new class {
+	public string $name;
+	public ?string $password;
+	public bool $admin = false;
+});
+```
+
+Оскільки інформації, отриманої з визначення класу, може бути недостатньо, ви можете додати власну схему для елементів за допомогою другого параметра:
+
+```php
+$schema = Expect::from(new Config, [
+	'name' => Expect::string()->pattern('\w:.*'),
+]);
+```
+
 {{leftbar: nette:@menu-topics}}
diff --git a/tester/bg/assertions.texy b/tester/bg/assertions.texy
index c4171e0e92..419e093c88 100644
--- a/tester/bg/assertions.texy
+++ b/tester/bg/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` трябва да бъде същото като `$actual`. Това е същото като оператора на PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Противоположен на `Assert::same()`, така че е същият като оператора на PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` трябва да бъде същото като `$actual`. За разлика от `Assert::same()`, идентичността на обектите, редът на двойките ключ => стойност в масивите и леко различаващите се десетични числа се игнорират, което може да се промени чрез задаване на `$matchIdentity` и `$matchOrder`.
 
 Следните случаи са идентични за `equal()`, но не и за `same()`:
@@ -45,73 +45,73 @@ Assert::equal(
 Можете да използвате и т.нар. [изчакване |#Expectations] в `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Контраст `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Ако `$actual` е низ, той трябва да съдържа подниз от `$needle`. Ако е масив, той трябва да съдържа елемент `$needle` (сравнява се стриктно).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Обратното на `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` трябва да бъде масив и да съдържа ключа `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` трябва да бъде масив и да не съдържа ключа `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` трябва да бъде `true`, така че `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` трябва да е вярно, така че то отговаря на условието `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` трябва да бъде `false`, следователно `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` трябва да е false, така че то отговаря на условието `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` трябва да бъде `null`, така че `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` не следва да бъде `null`, следователно `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` трябва да бъде Не е число. Използвайте `Assert::nan()` само за тестване на NAN. Стойността на NAN е много специфична и изявленията `Assert::same()` или `Assert::equal()` могат да се държат непредсказуемо.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Броят на елементите в `$value` трябва да е равен на `$count`. Това е същото като `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` трябва да е от посочения тип. Като `$type` можем да използваме символа:
 - `array`
 - `list` е масив, индексиран във възходящ цифров ред на ключовете от нула.
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - директно име на клас или обект, тогава трябва да предадете `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 При извикване на `$callable` трябва да се хвърли изключение за `$class`. Ако подадем `$message`, съобщението за изключение трябва да [съвпадне |#Assert-match]. И ако подадем `$code`, кодът на изключението трябва да е същият.
 
 Например този тест не успява, защото съобщението за изключение не съвпада:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Проверява дали извикването на `$callable` генерира очакваните грешки (т.е. предупреждения, известия и т.н.). Като `$type` посочваме една от константите `E_...`, например `E_WARNING`. А ако подадем `$message`, съобщението за грешка също трябва да [съответства на |#Assert-match] шаблона. Например:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Проверява дали `$callable` не изхвърля никакви предупреждения/бележки/грешки или изключения на PHP. Това е полезно за проверка на части от кода, в които няма други оператори.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` трябва да съвпада с `$pattern`. Можем да използваме две опции за шаблони: регулярни изрази или заместващи символи.
 
 Ако подадем регулярен израз като `$pattern`, трябва да използваме `~` or `#`, за да го отделим. Други разделители не се поддържат. Например тест, в който `$var` трябва да съдържа само шестнадесетични цифри:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Изпълнението е идентично с това на [Assert::match() |#Assert-match], но шаблонът е зареден от `$file`. Това е полезно за тестване на много дълги низове. Тестовият файл става четим.
 
 
diff --git a/tester/bg/guide.texy b/tester/bg/guide.texy
index b5a0d2a4d7..009f594bb4 100644
--- a/tester/bg/guide.texy
+++ b/tester/bg/guide.texy
@@ -116,10 +116,10 @@ Nette Tester претърсва посочената директория и в
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Tester може да генерира отчети с обща информац
 
 | PHP съвместима версия
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/bg/helpers.texy b/tester/bg/helpers.texy
index a233013643..2f173d8c93 100644
--- a/tester/bg/helpers.texy
+++ b/tester/bg/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` е клас, разширяващ `SimpleXMLElement` с методи за улесняване на тестването на HTML или XML съдържание.
 
 ```php
-# let's have an HTML document in $html that we load
+# в $html е низ с HTML документа, а в $dom получаваме кореновия елемент
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# или проверете дали елементът отговаря на селектора (от версия 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Създава глобални функции `test()`, `setUp()` и `tearDown()`, на които могат да се разделят тестовете.
+Създава глобални функции `test()`, `testException()`, `setUp()` и `tearDown()`, на които могат да се разделят тестовете.
 
 ```php
 test('test description', function () {
diff --git a/tester/bg/running-tests.texy b/tester/bg/running-tests.texy
index 5fe8d2728f..a45ac599a8 100644
--- a/tester/bg/running-tests.texy
+++ b/tester/bg/running-tests.texy
@@ -23,10 +23,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Использование:
     tester [параметры] [<тестовый файл> | <каталог>]...
@@ -58,16 +58,16 @@ PHP 7.4.8 (cli) | php -n | 8 threads
     -p <путь>                    Укажите интерпретатор PHP для запуска (по умолчанию: php).
     -c <path>                    Искать php.ini файл (или искать в директории) <path>.
     -C                           Использовать общесистемный php.ini.
-    -l | --log <путь>            Запись журнала в файл <путь>.
     -d <ключ=значение>...        Определить INI-запись 'key' со значением 'value'.
     -s                           Показать информацию о пропущенных тестах.
     --stop-on-fail               Остановить выполнение при первом сбое.
     -j <num>                     Выполнять <num> заданий параллельно (по умолчанию: 8).
-    -o <console|tap|junit|none>  Указать формат вывода.
+    -o <console|console-lines|tap|junit|log|none> (напр. -o junit:output.xml)
+                                 Посочете един или повече изходни формати с незадължително име на файл.
     -w | --watch <путь>          Каталог просмотра.
     -i | --info                  Показать информацию об окружении тестов и выйти.
     --setup <путь>               Сценарий для настройки бегущей строки.
-    --temp <путь>                Путь к временному каталогу. По умолчанию: sys_get_temp_dir().
+    --temp <path>                Път до временна директория. По подразбиране от sys_get_temp_dir().
     --colors [1|0]               Включить или отключить цвета.
     --coverage <путь>            Генерировать отчет о покрытии кода в файл.
     --coverage-src <путь>        Путь к исходному коду.
@@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests
 Използва се общосистемният `php.ini`. Така че на платформата UNIX се използват и всички файлове `/etc/php/{sapi}/conf.d/*.ini`. Вижте раздела [Собствен php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Напредъкът на тестването се записва във файл. Всички неуспешни, пропуснати, а също и успешни тестове:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Задава стойността на конфигурационната директива на PHP за тестове. Параметърът може да се използва многократно.
@@ -127,13 +118,15 @@ tester -d max_execution_time=20
 Тестовете се изпълняват в `<num>` паралелни прецеси. Стойността по подразбиране е 8. Ако искаме да изпълняваме тестовете последователно, използваме стойност 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Формат на изхода. По подразбиране е конзолният формат.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Изходен формат. По подразбиране е конзолният формат. Можете да посочите името на файла, в който ще бъде записан изходният файл (напр. `-o junit:output.xml`). Опцията `-o` може да се повтори многократно, за да се генерират няколко формата наведнъж.
 
 - `console`: същият като по подразбиране, но в този случай не се отпечатва ASCII логото
+- `console-lines`: подобно на конзолата, но резултатът от всеки тест се изписва на отделен ред с повече информация
 - `tap`: [TAP формат, |https://en.wikipedia.org/wiki/Test_Anything_Protocol] подходящ за машинна обработка
 - `junit`: JUnit XML формат, подходящ и за машинна обработка
+- `log`: Извежда информация за хода на тестването. Всички неуспешни, пропуснати, а също и успешни тестове
 - `none`: не се отпечатва нищо
 
 
diff --git a/tester/cs/assertions.texy b/tester/cs/assertions.texy
index b574efdac7..b1d3bc635e 100644
--- a/tester/cs/assertions.texy
+++ b/tester/cs/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` musí být totožný s `$actual`. To samé jako PHP operátor `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Opak `Assert::same()`, tedy to samé jako PHP operátor `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` musí být stejný s `$actual`. Na rozdíl od `Assert::same()` se ignoruje identita objektů, pořadí dvojic klíčů => hodnota v polích a marginálně odlišná desetinná čísla, což lze změnit nastavením `$matchIdentity` a `$matchOrder`.
 
 Následující případy jsou shodné z pohledu `equal()`, ale nikoliv `same()`:
@@ -45,73 +45,73 @@ Ovšem pozor, pole `[1, 2]` a `[2, 1]` stejné nejsou, protože se liší jen po
 Dále lze v `$expected` použít tzv. [#očekávání].
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Opak `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Pokud je `$actual` řetězec, musí obsahovat podřetězec `$needle`. Pokud je pole, musí obsahovat prvek `$needle` (porovnává se striktně).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Opak `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` musí být pole a musí obsahovat klíč `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` musí být pole a nesmí obsahovat klíč `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` musí být `true`, tedy `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` musí být pravdivý, tedy splní podmínku `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` musí být `false`, tedy `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` musí být nepravdivý, tedy splní podmínku `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` musí být `null`, tedy `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` nesmí být `null`, tedy `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` musí být Not a Number. Pro testování NAN hodnoty používejte vyhradně `Assert::nan()`. Hodnota NAN je velmi specifická a aserce `Assert::same()` nebo `Assert::equal()` mohou fungovat neočekávaně.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Počet prvků ve `$value` musí být `$count`. Tedy to samé jako `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` musí být daného typu. Jako `$type` můžeme použít řetězec:
 - `array`
 - `list` - pole indexované podle vzestupné řady numerických klíčů od nuly
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - název třídy nebo přímo objekt, potom musí být `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Při zavolání `$callable` musí být vyhozena výjimka třídy `$class`. Pokud uvedeme `$message`, musí [odpovídat vzoru|#assert-match] i zpráva výjimky a pokud uvedeme `$code`, musí se striktně shodovat i kódy.
 
 Následující test selže, protože neodpovídá zpráva výjimky:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Kontroluje, že funkce `$callable` vygenerovala očekávané chyby (tj. varování, notices atd). Jako `$type` uvedeme jednu z konstant `E_...`, tedy například `E_WARNING`. A pokud uvedeme `$message`, musí [odpovídat vzoru|#assert-match] i chybová zpráva. Například:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Kontroluje, že funkce `$callable` nevygenerovala žádné varování, chybu nebo výjimku. Hodí se pro testování kousků kódu, kde není žádná další aserce.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` musí vyhovět vzoru `$pattern`. Můžeme použít dvě varianty vzorů: regulární výrazy nebo zástupné znaky.
 
 Pokud jako `$pattern` předáme regulární výraz, k jeho ohraničení musíme použít `~` nebo `#`, jiné oddělovače nejsou podporovány. Například test, kdy `$var` musí obsahovat pouze hexadecimální číslice:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Aserce je totožná s [Assert::match() |#assert-match], ale vzor se načítá ze souboru `$file`. To je užitečné pro testování velmi dlouhých řetězců. Soubor s testem zůstane přehledný.
 
 
diff --git a/tester/cs/guide.texy b/tester/cs/guide.texy
index 4b7e290a36..d4781909c8 100644
--- a/tester/cs/guide.texy
+++ b/tester/cs/guide.texy
@@ -116,10 +116,10 @@ Výstup může vypadat takto:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Podporované verze PHP
 
 | verze            | kompatibilní s PHP
 |------------------|-------------------
-| Tester 2.5       | PHP 8.0 – 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4       | PHP 7.2 – 8.2
 | Tester 2.3       | PHP 7.1 – 8.0
 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3
diff --git a/tester/cs/helpers.texy b/tester/cs/helpers.texy
index 2677074240..4027ad0888 100644
--- a/tester/cs/helpers.texy
+++ b/tester/cs/helpers.texy
@@ -7,7 +7,7 @@ DomQuery
 `Tester\DomQuery` je třída rozšiřující `SimpleXMLElement` o metody usnadňující testování obsahu HTML nebo XML.
 
 ```php
-# mějme v $html HTML dokument, který načteme
+# v $html je řetězec s HTML dokumentem, v $dom získáme kořenový element
 $dom = Tester\DomQuery::fromHtml($html);
 
 # můžeme testovat přítomnost elementů podle CSS selektorů
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # nebo vybrat elementy jako pole DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# nebo ověřovat, zda element vyhovuje selektoru (od verze 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Vytvoří globální funkce `test()`, `setUp()` a `tearDown()`, do kterých můžete členit testy.
+Vytvoří globální funkce `test()`, `testException()`, `setUp()` a `tearDown()`, do kterých můžete členit testy.
 
 ```php
 test('popis testu', function () {
diff --git a/tester/cs/running-tests.texy b/tester/cs/running-tests.texy
index ee894e59c7..c5b13ad249 100644
--- a/tester/cs/running-tests.texy
+++ b/tester/cs/running-tests.texy
@@ -23,10 +23,10 @@ Výstup může vypadat třeba takto:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Přehled všech voleb příkazové řádky získáme spuštěním Testeru bez pa
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none>  (e.g. -o junit:output.xml)
+                                 Specify one or more output formats with optional file name.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Path to temporary directory. Default by sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Určuje, který `php.ini` se bude používat při spouštění testů. Ve výcho
 Použije se systémové `php.ini`. Na UNIXu také všechny příslušné INI soubory `/etc/php/{sapi}/conf.d/*.ini`. Více v části [#Vlastní php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Do uvedeného souboru bude zapsán průběh testování. Všechny selhané, přeskočené, ale i úspěšné testy:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Nastavuje hodnotu PHP konfigurační direktivy pro testy. Parametr může být použit vícekrát.
@@ -127,13 +118,15 @@ Tester zastaví testování u prvního selhávajícího testu.
 Určuje, kolik paralelních procesů s testy se spustí. Výchozí hodnota je 8. Chceme-li, aby všechny testy proběhly v sérii, použijeme hodnotu 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Nastaví formát výstupu. Výchozí je formát pro konzoli.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Nastaví formát výstupu. Výchozí je formát pro konzoli. Můžete uvést jméno souboru, do kterého se výstup zapíše (např `-o junit:output.xml`). Volbu `-o` lze zopakovat vícekrát a vygenerovat tak více formátů najednou.
 
 - `console`: shodné s výchozím formátem, ale v tomto případě se nezobrazí ASCII logo
+- `console-lines`: podobné jako console, ale výsledek každého testu je uveden na samostatném řádku s dalšími informacemi
 - `tap`: [TAP formát |https://en.wikipedia.org/wiki/Test_Anything_Protocol] vhodný pro strojové zpracování
 - `junit`: XML formát JUnit, taktéž vhodný pro strojové zpracování
+- `log`: Výstupy průběhu testování. Všechny neúspěšné, přeskočené a také úspěšné testy
 - `none`: nic se nevypisuje
 
 
diff --git a/tester/de/assertions.texy b/tester/de/assertions.texy
index 18e2daa58c..be512a570a 100644
--- a/tester/de/assertions.texy
+++ b/tester/de/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` muss mit `$actual` identisch sein. Er ist identisch mit dem PHP-Operator `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Das Gegenteil von `Assert::same()`, also dasselbe wie der PHP-Operator `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` muss mit `$actual` identisch sein. Im Gegensatz zu `Assert::same()` werden Objektidentität, Reihenfolge von Schlüsselpaaren => Wert in Arrays und geringfügig unterschiedliche Dezimalzahlen ignoriert, was durch Setzen von `$matchIdentity` und `$matchOrder` geändert werden kann.
 
 Die folgenden Fälle sind aus der Sicht von `equal()` identisch, aber nicht für `same()`:
@@ -45,73 +45,73 @@ Beachten Sie jedoch, dass das Array `[1, 2]` und `[2, 1]` sind nicht gleich, da
 Sie können auch die sogenannten [Erwartungen |#expectations] in `$expected` verwenden.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Im Gegensatz zu `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Wenn `$actual` eine Zeichenkette ist, muss sie die Teilzeichenkette `$needle` enthalten. Wenn es sich um ein Array handelt, muss es das Element `$needle` enthalten (es wird streng verglichen).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Im Gegensatz zu `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` muss ein Array sein und den Schlüssel `$needle` enthalten.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` muss ein Array sein und darf den Schlüssel `$needle` nicht enthalten.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` muss `true` sein, also `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` muss wahrheitsgemäß sein, also erfüllt es die Bedingung `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` muss `false` sein, also `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` muss falsch sein, also erfüllt es die Bedingung `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` muss `null` sein, also `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` darf nicht `null` sein, also `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` muss Not a Number sein. Verwenden Sie für NAN-Tests nur die `Assert::nan()`. Der NAN-Wert ist sehr spezifisch und die Assertions `Assert::same()` oder `Assert::equal()` können sich unvorhersehbar verhalten.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Die Anzahl der Elemente in `$value` muss `$count` sein. Also dasselbe wie `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` muss von einem bestimmten Typ sein. Als `$type` können wir String verwenden:
 - `array`
 - `list` - Array, das in aufsteigender Reihenfolge der numerischen Schlüssel von Null an indiziert ist
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - Klassenname oder Objekt direkt, dann müssen `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Beim Aufruf von `$callable` muss eine Ausnahme der Instanz `$class` ausgelöst werden. Wenn wir `$message` übergeben, muss die Nachricht der Ausnahme [übereinstimmen |#assert-match]. Und wenn wir `$code` übergeben, muss der Code der Ausnahme derselbe sein.
 
 Dieser Test schlägt zum Beispiel fehl, weil die Meldung der Ausnahme nicht übereinstimmt:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Überprüft, ob der `$callable` -Aufruf die erwarteten Fehler erzeugt (d.h. Warnungen, Hinweise usw.). Als `$type` geben wir eine der Konstanten `E_...` an, zum Beispiel `E_WARNING`. Und wenn wir `$message` übergeben, muss die Fehlermeldung auch [dem |#assert-match] Muster [entsprechen |#assert-match]. Zum Beispiel:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Überprüft, dass die Funktion `$callable` keine PHP-Warnung/Hinweis/Fehler oder Ausnahme auslöst. Sie ist nützlich, um ein Stück Code zu testen, für das es keine andere Assertion gibt.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` muss mit `$pattern` übereinstimmen. Wir können zwei Varianten von Mustern verwenden: reguläre Ausdrücke oder Wildcards.
 
 Wenn wir einen regulären Ausdruck als `$pattern` übergeben, müssen wir `~` or `#` verwenden, um ihn abzugrenzen. Andere Begrenzungszeichen werden nicht unterstützt. Zum Beispiel test, bei dem `$var` nur hexadezimale Ziffern enthalten darf:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Die Assertion ist identisch mit [Assert::match() |#assert-match], aber das Muster wird von `$file` geladen. Sie ist nützlich für das Testen sehr langer Strings. Die Testdatei ist lesbar.
 
 
diff --git a/tester/de/guide.texy b/tester/de/guide.texy
index 31b57967bc..647786a7f4 100644
--- a/tester/de/guide.texy
+++ b/tester/de/guide.texy
@@ -116,10 +116,10 @@ Die Ausgabe kann wie folgt aussehen:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Unterstützte PHP-Versionen .[#toc-supported-php-versions]
 
 | Version | kompatibel mit PHP
 |------------------|-------------------
-| Tester 2.4 | PHP 7.2 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
 | Tester 2.0 | PHP 5.6 - 7.3
diff --git a/tester/de/helpers.texy b/tester/de/helpers.texy
index 5bacb62f16..0451557d1a 100644
--- a/tester/de/helpers.texy
+++ b/tester/de/helpers.texy
@@ -7,7 +7,7 @@ DomQuery
 `Tester\DomQuery` ist eine Klasse, die `SimpleXMLElement` mit Methoden erweitert, die das Testen von HTML- oder XML-Inhalten erleichtern.
 
 ```php
-# let's have an HTML document in $html that we load
+# $html ist ein String mit dem HTML-Dokument, $dom ist das Root-Element.
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# oder überprüfen, ob das Element mit dem Selektor übereinstimmt (ab Version 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Erzeugt die globalen Funktionen `test()`, `setUp()` und `tearDown()`, in die Sie Tests aufteilen können.
+Erzeugt die globalen Funktionen `test()`, `testException()`, `setUp()` und `tearDown()`, in die Sie Tests aufteilen können.
 
 ```php
 test('Testbeschreibung', function () {
diff --git a/tester/de/running-tests.texy b/tester/de/running-tests.texy
index 1e5cd5098a..67eb490415 100644
--- a/tester/de/running-tests.texy
+++ b/tester/de/running-tests.texy
@@ -23,10 +23,10 @@ Die Ausgabe kann wie folgt aussehen:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Einen Überblick über die Kommandozeilenoptionen erhalten wir, indem wir den Te
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (z. B. -o junit:output.xml)
+                                 Geben Sie ein oder mehrere Ausgabeformate mit optionalem Dateinamen an.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Pfad zum temporären Verzeichnis. Vorgabe durch sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Gibt an, welche `php.ini` bei der Ausführung von Tests verwendet wird. Standard
 Es wird eine systemweite `php.ini` verwendet. Auf der UNIX-Plattform also auch alle `/etc/php/{sapi}/conf.d/*.ini` -Dateien. Siehe Abschnitt [Eigene php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Der Testfortschritt wird in eine Datei geschrieben. Alle fehlgeschlagenen, übersprungenen und auch erfolgreichen Tests:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Legt den Wert der PHP-Konfigurationsrichtlinie für Tests fest. Der Parameter kann mehrfach verwendet werden.
@@ -127,13 +118,15 @@ Der Tester bricht den Test ab, sobald der erste Test fehlschlägt.
 Tests laufen in einem `<num>` parallel abläuft. Der Standardwert ist 8. Wenn wir die Tests in Serie laufen lassen wollen, verwenden wir den Wert 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Ausgabeformat. Standard ist das Konsolenformat.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Ausgabeformat. Standardmäßig wird das Konsolenformat verwendet. Sie können den Namen der Datei angeben, in die die Ausgabe geschrieben werden soll (z. B. `-o junit:output.xml`). Die Option `-o` kann mehrmals wiederholt werden, um mehrere Formate auf einmal zu erzeugen.
 
 - `console`: wie Standard, aber das ASCII-Logo wird in diesem Fall nicht gedruckt
+- `console-lines`: ähnlich wie die Konsole, aber das Ergebnis jedes Tests wird in einer separaten Zeile mit weiteren Informationen angezeigt
 - `tap`: [TAP-Format |https://en.wikipedia.org/wiki/Test_Anything_Protocol], geeignet für die maschinelle Verarbeitung
 - `junit`: JUnit XML-Format, auch für die maschinelle Verarbeitung geeignet
+- `log`: Gibt den Testfortschritt aus. Alle fehlgeschlagenen, übersprungenen und auch erfolgreichen Tests
 - `none`: es wird nichts gedruckt
 
 
diff --git a/tester/el/assertions.texy b/tester/el/assertions.texy
index 9bba24f7aa..58739eb2e8 100644
--- a/tester/el/assertions.texy
+++ b/tester/el/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` πρέπει να είναι το ίδιο με το `$actual`. Είναι το ίδιο με τον τελεστή PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Αντίθετος του `Assert::same()`, άρα είναι ίδιος με τον τελεστή PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` πρέπει να είναι το ίδιο με το `$actual`. Σε αντίθεση με το `Assert::same()`, η ταυτότητα αντικειμένων, η σειρά των ζευγών κλειδιών => τιμή σε πίνακες και οι οριακά διαφορετικοί δεκαδικοί αριθμοί αγνοούνται, οι οποίοι μπορούν να αλλάξουν με τη ρύθμιση των `$matchIdentity` και `$matchOrder`.
 
 Οι ακόλουθες περιπτώσεις είναι ταυτόσημες από την άποψη του `equal()`, αλλά όχι για το `same()`:
@@ -45,73 +45,73 @@ Assert::equal(
 Μπορείτε επίσης να χρησιμοποιήσετε τις λεγόμενες [προσδοκίες |#expectations] στο `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Σε αντίθεση με το `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Εάν το `$actual` είναι μια συμβολοσειρά, πρέπει να περιέχει την υποσυμβολοσειρά `$needle`. Εάν είναι πίνακας, πρέπει να περιέχει το στοιχείο `$needle` (συγκρίνεται αυστηρά).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Αντίθετο από το `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` πρέπει να είναι ένας πίνακας και να περιέχει το κλειδί `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` πρέπει να είναι πίνακας και να μην περιέχει το κλειδί `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` πρέπει να είναι `true`, οπότε `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` πρέπει να είναι αληθές, άρα ικανοποιεί τη συνθήκη `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` πρέπει να είναι `false`, άρα `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` πρέπει να είναι ψευδής, άρα ικανοποιεί τη συνθήκη `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` πρέπει να είναι `null`, άρα `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` δεν πρέπει να είναι `null`, οπότε `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` πρέπει να είναι Not a Number. Χρησιμοποιήστε μόνο το `Assert::nan()` για δοκιμές NAN. Η τιμή NAN είναι πολύ συγκεκριμένη και οι ισχυρισμοί `Assert::same()` ή `Assert::equal()` μπορεί να συμπεριφέρονται απρόβλεπτα.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Ο αριθμός των στοιχείων στο `$value` πρέπει να είναι `$count`. Άρα το ίδιο με το `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` πρέπει να είναι συγκεκριμένου τύπου. Ως `$type` μπορούμε να χρησιμοποιήσουμε το string:
 - `array`
 - `list` - πίνακας με ευρετήριο σε αύξουσα σειρά αριθμητικών κλειδιών από το μηδέν
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - το όνομα της κλάσης ή του αντικειμένου απευθείας, τότε πρέπει να περάσει `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Κατά την κλήση του `$callable` πρέπει να εκπέμπεται μια εξαίρεση της περίπτωσης `$class`. Αν περάσουμε το `$message`, το μήνυμα της εξαίρεσης πρέπει να [ταιριάζει |#assert-match]. Και αν περάσουμε το `$code`, ο κωδικός της εξαίρεσης πρέπει να είναι ο ίδιος.
 
 Για παράδειγμα, αυτή η δοκιμή αποτυγχάνει επειδή το μήνυμα της εξαίρεσης δεν ταιριάζει:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Ελέγχει ότι η κλήση του `$callable` παράγει τα αναμενόμενα σφάλματα (δηλαδή προειδοποιήσεις, ειδοποιήσεις κ.λπ.). Ως `$type` καθορίζουμε μία από τις σταθερές `E_...`, για παράδειγμα `E_WARNING`. Και αν περάσει το `$message`, το μήνυμα σφάλματος πρέπει επίσης να [ταιριάζει με |#assert-match] το πρότυπο. Για παράδειγμα:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Ελέγχει ότι η συνάρτηση `$callable` δεν πετάει καμία προειδοποίηση/ειδοποίηση/σφάλμα ή εξαίρεση της PHP. Είναι χρήσιμη για τον έλεγχο ενός κομματιού κώδικα όπου δεν υπάρχει άλλος ισχυρισμός.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` πρέπει να ταιριάζει με το `$pattern`. Μπορούμε να χρησιμοποιήσουμε δύο παραλλαγές προτύπων: κανονικές εκφράσεις ή μπαλαντέρ.
 
 Εάν περάσουμε μια κανονική έκφραση ως `$pattern`, πρέπει να χρησιμοποιήσουμε το `~` or `#` για να την οριοθετήσουμε. Άλλα διαχωριστικά δεν υποστηρίζονται. Για παράδειγμα, το test όπου το `$var` πρέπει να περιέχει μόνο δεκαεξαδικά ψηφία:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Ο ισχυρισμός είναι πανομοιότυπος με την [Assert::match() |#assert-match] αλλά το μοτίβο φορτώνεται από το `$file`. Είναι χρήσιμος για τον έλεγχο πολύ μεγάλων συμβολοσειρών. Το αρχείο δοκιμής είναι αναγνώσιμο.
 
 
diff --git a/tester/el/guide.texy b/tester/el/guide.texy
index 24bfd0da62..184880141a 100644
--- a/tester/el/guide.texy
+++ b/tester/el/guide.texy
@@ -116,10 +116,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads
 
 | έκδοση | συμβατή με PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/el/helpers.texy b/tester/el/helpers.texy
index 98e9a306d1..9063fd3527 100644
--- a/tester/el/helpers.texy
+++ b/tester/el/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` είναι μια κλάση που επεκτείνει το `SimpleXMLElement` με μεθόδους που διευκολύνουν τον έλεγχο περιεχομένου HTML ή XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# στο $html είναι μια συμβολοσειρά με το έγγραφο HTML, στο $dom παίρνουμε το στοιχείο ρίζα
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# ή να επαληθεύσει ότι το στοιχείο ταιριάζει με τον επιλογέα (από την έκδοση 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Δημιουργεί τις παγκόσμιες συναρτήσεις `test()`, `setUp()` και `tearDown()` στις οποίες μπορείτε να χωρίσετε τις δοκιμές.
+Δημιουργεί τις παγκόσμιες συναρτήσεις `test()`, `testException()`, `setUp()` και `tearDown()` στις οποίες μπορείτε να χωρίσετε τις δοκιμές.
 
 ```php
 test('test description', function () {
diff --git a/tester/el/running-tests.texy b/tester/el/running-tests.texy
index 7584b9b4c7..ae822f4283 100644
--- a/tester/el/running-tests.texy
+++ b/tester/el/running-tests.texy
@@ -23,10 +23,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (π.χ. -o junit:output.xml)
+                                 Καθορίστε μία ή περισσότερες μορφές εξόδου με προαιρετικό όνομα αρχείου.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Διαδρομή προς τον προσωρινό κατάλογο. Προεπιλογή από την sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests
 Χρησιμοποιείται ένα `php.ini` σε όλο το σύστημα. Έτσι, στην πλατφόρμα UNIX, όλα τα αρχεία `/etc/php/{sapi}/conf.d/*.ini` επίσης. Δείτε την ενότητα [Own php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Η πρόοδος των δοκιμών γράφεται σε αρχείο. Όλες οι αποτυχημένες, παραλειφθείσες και επιτυχημένες δοκιμές:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Ορίζει την τιμή της οδηγίας διαμόρφωσης PHP για δοκιμές. Η παράμετρος μπορεί να χρησιμοποιηθεί πολλές φορές.
@@ -127,13 +118,15 @@ tester -d max_execution_time=20
 Οι δοκιμές εκτελούνται σε ένα `<num>` παράλληλες διεργασίες. Η προεπιλεγμένη τιμή είναι 8. Αν θέλουμε να εκτελούμε δοκιμές σε σειρά, χρησιμοποιούμε την τιμή 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Μορφή εξόδου. Η προεπιλογή είναι η μορφή κονσόλας.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Μορφή εξόδου. Η προεπιλογή είναι η μορφή κονσόλας. Μπορείτε να καθορίσετε το όνομα του αρχείου στο οποίο θα γραφτεί η έξοδος (π.χ. `-o junit:output.xml`). Η επιλογή `-o` μπορεί να επαναληφθεί πολλές φορές για την ταυτόχρονη παραγωγή πολλαπλών μορφών.
 
 - `console`: η ίδια με την προεπιλογή, αλλά το λογότυπο ASCII δεν εκτυπώνεται σε αυτή την περίπτωση.
+- `console-lines`: παρόμοια με την κονσόλα, αλλά το αποτέλεσμα κάθε δοκιμής παρατίθεται σε ξεχωριστή γραμμή με περισσότερες πληροφορίες
 - `tap`: [Μορφή TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] κατάλληλη για μηχανική επεξεργασία.
 - `junit`: Μορφή JUnit XML, κατάλληλη και για μηχανική επεξεργασία.
+- `log`: Εξάγει την πρόοδο των δοκιμών. Όλες οι αποτυχημένες, παραλειφθείσες και επιτυχημένες δοκιμές
 - `none`: δεν εκτυπώνεται τίποτα
 
 
diff --git a/tester/en/assertions.texy b/tester/en/assertions.texy
index 6a6b61f1f3..7b702da041 100644
--- a/tester/en/assertions.texy
+++ b/tester/en/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` must be the same as `$actual`. It is the same as PHP operator `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Opposite to `Assert::same()`, so it is the same as PHP operator `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` must be the same as `$actual`. Unlike `Assert::same()`, object identity, order of key pairs => value in arrays, and marginally different decimal numbers are ignored, which can be changed by setting `$matchIdentity` and `$matchOrder`.
 
 The following cases are identical from the point of view of `equal()`, but not for `same()`:
@@ -45,73 +45,73 @@ However, beware, the array `[1, 2]` and `[2, 1]` are not equal, because only the
 You can also use the so-called [#expectations] in `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Opposite to `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 If `$actual` is a string, it must contain the substring `$needle`. If it is an array, it must contain the element `$needle` (it is compared strictly).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Opposite to `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` must be an array and must contain the key `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` must be an array and must not contain the key `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` must be `true`, so `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` must be truthy, so it satisfies the condition `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` must be `false`, so `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` must be falsey, so it satisfies the condition `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` must be `null`, so `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` must not be `null`, so `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` must be Not a Number. Use only the `Assert::nan()` for NAN testing. NAN value is very specific and assertions `Assert::same()` or `Assert::equal()` can behave unpredictably.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Number of elements in `$value` must be `$count`. So the same as `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` must be of a given type. As `$type` we can use string:
 - `array`
 - `list` - array indexed in ascending order of numeric keys from zero
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - class name or object directly then must pass `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 On `$callable` invocation an exception of `$class` instance must be thrown. If we pass `$message`, the message of the exception must [match|#assert-match]. And if we pass `$code`, code of the exception must be the same.
 
 For example, this test fails because message of the exception does not match:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Checks that the `$callable` invocation generates the expected errors (ie warnings, notices, etc.). As `$type` we specify one of the constants `E_...`, for example `E_WARNING`. And if pass `$message`, the error message must also [match|#assert-match] pattern. For example:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Checks that the function `$callable` does not throw any PHP warning/notice/error or exception. It is useful for testing a piece of code where is no other assertion.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` must match to `$pattern`. We can use two variants of patterns: regular expressions or wildcards.
 
 If we pass a regular expression as `$pattern`, we must use `~` or `#` to delimit it. Other delimiters are not supported. For example test where `$var` must contain only hexadecimal digits:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 The assertion is identical to [Assert::match() |#assert-match] but the pattern is loaded from `$file`. It is useful for very long strings testing. Test file stands readable.
 
 
diff --git a/tester/en/guide.texy b/tester/en/guide.texy
index 6795bc07b4..91fde34846 100644
--- a/tester/en/guide.texy
+++ b/tester/en/guide.texy
@@ -116,10 +116,10 @@ The output can look like this:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Supported PHP versions
 
 | version          | compatible with PHP
 |------------------|-------------------
-| Tester 2.5       | PHP 8.0 – 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4       | PHP 7.2 – 8.2
 | Tester 2.3       | PHP 7.1 – 8.0
 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3
diff --git a/tester/en/helpers.texy b/tester/en/helpers.texy
index d6107abf65..937d3c6527 100644
--- a/tester/en/helpers.texy
+++ b/tester/en/helpers.texy
@@ -7,7 +7,7 @@ DomQuery
 `Tester\DomQuery` is a class that extends `SimpleXMLElement` with methods that make it easier to test HTML or XML content.
 
 ```php
-# let's have an HTML document in $html that we load
+# in $html is a string with the HTML document, in $dom we get the root element
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# or verify that the element matches the selector (from version 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Creates the global functions `test()`, `setUp()` and `tearDown()` into which you can split tests.
+Creates the global functions `test()`, `testException()`, `setUp()` and `tearDown()` into which you can split tests.
 
 ```php
 test('test description', function () {
diff --git a/tester/en/running-tests.texy b/tester/en/running-tests.texy
index 201f33718f..a49726b70d 100644
--- a/tester/en/running-tests.texy
+++ b/tester/en/running-tests.texy
@@ -23,10 +23,10 @@ The output may look like:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ We obtain command-line options overview by running the Tester without parameters
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none>  (e.g. -o junit:output.xml)
+                                 Specify one or more output formats with optional file name.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Path to temporary directory. Default by sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Specifies which `php.ini` will be used when running tests. By default, no php.in
 A system-wide `php.ini` is used. So on UNIX platform, all the `/etc/php/{sapi}/conf.d/*.ini` files too. See [#Own php.ini] section.
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Testing progress is written into file. All failed, skipped and also successful tests:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Sets the value of the PHP configuration directive for tests. The parameter can be used multiple times.
@@ -127,13 +118,15 @@ Tester stops testing upon the first failing test.
 Tests run in a `<num>` parallel precesses. Default value is 8. If we wish to run tests in series, we use value 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Output format. Default is the console format.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Output format. Default is the console format. You can specify the name of the file into which the output will be written (e.g., `-o junit:output.xml`). The `-o` option can be repeated multiple times to generate multiple formats at once.
 
 - `console`: the same as default, but the ASCII logo is not printed in this case
+- `console-lines`: similar to the console, but the result of each test is listed on a separate line with more information
 - `tap`: [TAP format |https://en.wikipedia.org/wiki/Test_Anything_Protocol] appropriate for machine processing
 - `junit`: JUnit XML format, appropriate for machine processing too
+- `log`: Outputs testing progress. All failed, skipped and also successful tests
 - `none`: nothing is printed
 
 
diff --git a/tester/es/assertions.texy b/tester/es/assertions.texy
index 5774fdb256..abf62f2e1b 100644
--- a/tester/es/assertions.texy
+++ b/tester/es/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` debe ser el mismo que `$actual`. Es el mismo que el operador PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Opuesto a `Assert::same()`, por lo que es el mismo que el operador PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` debe ser igual a `$actual`. A diferencia de `Assert::same()`, se ignoran la identidad del objeto, el orden de los pares clave => valor en matrices, y los números decimales marginalmente diferentes, que pueden cambiarse configurando `$matchIdentity` y `$matchOrder`.
 
 Los siguientes casos son idénticos desde el punto de vista de `equal()`, pero no para `same()`:
@@ -45,73 +45,73 @@ Sin embargo, cuidado, la matriz `[1, 2]` y `[2, 1]` no son iguales, porque sólo
 También puede utilizar las llamadas [expectativas |#expectations] en `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Opuesto a `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Si `$actual` es una cadena, debe contener la subcadena `$needle`. Si es una matriz, debe contener el elemento `$needle` (se compara estrictamente).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Opuesto a `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` debe ser un array y debe contener la clave `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` debe ser una matriz y no debe contener la clave `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` debe ser `true`, por lo que `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` debe ser verdadero, por lo que satisface la condición `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` debe ser `false`, por lo que `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` debe ser falsa, por lo que satisface la condición `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` debe ser `null`, por lo que `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` no debe ser `null`, entonces `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` debe ser Not a Number. Utilice únicamente `Assert::nan()` para las pruebas NAN. El valor NAN es muy específico y las aserciones `Assert::same()` o `Assert::equal()` pueden comportarse de forma impredecible.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 El número de elementos en `$value` debe ser `$count`. Por tanto, igual que `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` debe ser de un tipo determinado. Como `$type` podemos utilizar string:
 - `array`
 - `list` - array indexado en orden ascendente de claves numéricas desde cero
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - nombre de clase u objeto directamente entonces debe pasar `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Al invocar `$callable` debe lanzarse una excepción de instancia `$class`. Si pasamos `$message`, el mensaje de la excepción debe [coincidir |#assert-match]. Y si pasamos `$code`, código de la excepción debe ser el mismo.
 
 Por ejemplo, esta prueba falla porque el mensaje de la excepción no coincide:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Comprueba que la invocación `$callable` genera los errores esperados (es decir, advertencias, avisos, etc.). Como `$type` especificamos una de las constantes `E_...`, por ejemplo `E_WARNING`. Y si pasamos `$message`, el mensaje de error también debe [coincidir |#assert-match] con el patrón. Por ejemplo
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Comprueba que la función `$callable` no lanza ningún warning/notice/error o excepción de PHP. Es útil para probar un fragmento de código en el que no hay ninguna otra aserción.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` debe coincidir con `$pattern`. Podemos utilizar dos variantes de patrones: expresiones regulares o comodines.
 
 Si pasamos una expresión regular como `$pattern`, debemos utilizar `~` or `#` para delimitarla. No se admiten otros delimitadores. Por ejemplo test donde `$var` debe contener sólo dígitos hexadecimales:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 La aserción es idéntica a [Assert::match() |#assert-match] pero el patrón se carga desde `$file`. Es útil para probar cadenas muy largas. El archivo de prueba es legible.
 
 
diff --git a/tester/es/guide.texy b/tester/es/guide.texy
index 03a800b4df..438b62fb62 100644
--- a/tester/es/guide.texy
+++ b/tester/es/guide.texy
@@ -116,10 +116,10 @@ La salida puede tener este aspecto:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Versiones de PHP soportadas .[#toc-supported-php-versions]
 
 | versión | compatible con PHP
 |------------------|-------------------
-| Tester 2.4       | PHP 7.2 – 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.3       | PHP 7.1 – 8.0
 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3
 | Tester 2.0       | PHP 5.6 – 7.3
diff --git a/tester/es/helpers.texy b/tester/es/helpers.texy
index 158466bf52..20f568e17d 100644
--- a/tester/es/helpers.texy
+++ b/tester/es/helpers.texy
@@ -7,7 +7,7 @@ DomQuery
 `Tester\DomQuery` es una clase que amplía `SimpleXMLElement` con métodos que facilitan la comprobación de contenidos HTML o XML.
 
 ```php
-# tengamos un documento HTML en $html que cargamos
+# en $html es una cadena con el documento HTML, en $dom obtenemos el elemento raíz
 $dom = Tester\DomQuery::fromHtml($html);
 
 # podemos comprobar la presencia de elementos utilizando selectores CSS
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # o seleccionar elementos como array de DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# o verificar que el elemento coincide con el selector (a partir de la versión 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Crea las funciones globales `test()`, `setUp()` y `tearDown()` en las que se pueden dividir las pruebas.
+Crea las funciones globales `test()`, `testException()`, `setUp()` y `tearDown()` en las que se pueden dividir las pruebas.
 
 ```php
 test('descripción de la prueba', function () {
diff --git a/tester/es/running-tests.texy b/tester/es/running-tests.texy
index 571b97135b..e7add92adb 100644
--- a/tester/es/running-tests.texy
+++ b/tester/es/running-tests.texy
@@ -23,10 +23,10 @@ La salida puede tener el siguiente aspecto:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Obtenemos una visión general de las opciones de la línea de comandos ejecutand
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Uso:
     tester [opciones] [<archivo de prueba> | <directorio>]...
@@ -58,16 +58,16 @@ Opciones:
     -p <ruta>                    Especificar intérprete PHP a ejecutar (por defecto: php).
     -c <ruta>                    Buscar el archivo php.ini (o buscar en el directorio) <ruta>.
     -C                           Usar php.ini para todo el sistema.
-    -l | --log <ruta>            Escribe el registro en el archivo <ruta>.
     -d <clave=valor>...          Definir entrada INI <clave> con valor <valor>.
     -s                           Mostrar información sobre las pruebas omitidas.
     --stop-on-fail               Detener la ejecución al primer fallo.
     -j <num>                     Ejecutar <num> trabajos en paralelo (por defecto: 8).
-    -o <console|tap|junit|none>  Especifica el formato de salida.
+    -o <console|console-lines|tap|junit|log|none> (por ejemplo, -o junit:output.xml)
+                                 Especifica uno o más formatos de salida con un nombre de archivo opcional.
     -w | --watch <ruta>          Directorio de vigilancia.
     -i | --info                  Mostrar información del entorno de pruebas y salir.
     --setup <ruta>               Script para la configuración del runner.
-    --temp <ruta>                Ruta al directorio temporal. Por defecto: sys_get_temp_dir().
+    --temp <path>                Ruta al directorio temporal. Por defecto por sys_get_temp_dir().
     --colors [1|0]               Activa o desactiva los colores.
     --coverage <ruta>            Generar informe de cobertura de código a archivo.
     --coverage-src <ruta>        Ruta al código fuente.
@@ -94,15 +94,6 @@ Especifica qué `php.ini` se utilizará al ejecutar las pruebas. Por defecto, no
 Se utiliza `php.ini` para todo el sistema. Así que en la plataforma UNIX, todos los archivos `/etc/php/{sapi}/conf.d/*.ini` también. Véase la sección [php.ini propia |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-El progreso de las pruebas se escribe en el archivo. Todas las pruebas fallidas, omitidas y también las exitosas:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Establece el valor de la directiva de configuración PHP para las pruebas. El parámetro se puede utilizar varias veces.
@@ -127,13 +118,15 @@ El probador detiene la prueba al fallar la primera prueba.
 Las pruebas se ejecutan en `<num>` precesos en paralelo. El valor por defecto es 8. Si deseamos ejecutar las pruebas en serie, utilizaremos el valor 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Formato de salida. Por defecto es el formato de consola.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Formato de salida. Por defecto es el formato de consola. Puede especificar el nombre del archivo en el que se escribirá la salida (por ejemplo, `-o junit:output.xml`). La opción `-o` puede repetirse varias veces para generar varios formatos a la vez.
 
 - `console`: igual que por defecto, pero en este caso no se imprime el logotipo ASCII
+- `console-lines`: similar a la consola, pero el resultado de cada prueba aparece en una línea separada con más información
 - `tap`: formato [TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] apropiado para el procesamiento en máquina
 - `junit`: formato JUnit XML, apropiado también para el procesamiento en máquina
+- `log`: Muestra el progreso de las pruebas. Todas las pruebas fallidas, omitidas y también las exitosas
 - `none`: no se imprime nada
 
 
diff --git a/tester/fr/assertions.texy b/tester/fr/assertions.texy
index 550cec2931..a7bd5afb42 100644
--- a/tester/fr/assertions.texy
+++ b/tester/fr/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` doit être le même que `$actual`. Il est identique à l'opérateur PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Opposé à `Assert::same()`, il est donc identique à l'opérateur PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` doit être le même que `$actual`. Contrairement à `Assert::same()`, l'identité de l'objet, l'ordre des paires de clés => valeur dans les tableaux, et les nombres décimaux légèrement différents sont ignorés, ce qui peut être modifié en paramétrant `$matchIdentity` et `$matchOrder`.
 
 Les cas suivants sont identiques du point de vue de `equal()`, mais pas pour `same()`:
@@ -45,73 +45,73 @@ Cependant, attention, le tableau `[1, 2]` et `[2, 1]` ne sont pas égaux, car se
 Vous pouvez également utiliser ce que l'on appelle les [attentes |#expectations] dans `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 A l'opposé de `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Si `$actual` est une chaîne de caractères, elle doit contenir la sous-chaîne `$needle`. Si c'est un tableau, il doit contenir l'élément `$needle` (il est comparé strictement).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Opposé à `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` doit être un tableau et doit contenir la clé `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` doit être un tableau et ne doit pas contenir la clé `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` doit être `true`, donc `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` doit être véridique, donc il satisfait la condition `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` doit être `false`, donc `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` doit être faux, donc il remplit la condition `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` doit être `null`, donc `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` ne doit pas être `null`, donc `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` doit être Not a Number. Utilisez uniquement le site `Assert::nan()` pour les tests NAN. La valeur NAN est très spécifique et les assertions `Assert::same()` ou `Assert::equal()` peuvent se comporter de manière imprévisible.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Le nombre d'éléments dans `$value` doit être `$count`. Donc identique à `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` doit être d'un type donné. Comme `$type` nous pouvons utiliser une chaîne de caractères :
 - `array`
 - `list` - tableau indexé dans l'ordre croissant des clés numériques à partir de zéro.
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - nom de la classe ou de l'objet directement, alors il faut passer `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Lors de l'invocation de `$callable`, une exception de l'instance `$class` doit être levée. Si nous passons `$message`, le message de l'exception doit [correspondre |#assert-match]. Et si nous passons `$code`, le code de l'exception doit être le même.
 
 Par exemple, ce test échoue car le message de l'exception ne correspond pas :
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Vérifie que l'invocation de `$callable` génère les erreurs attendues (c'est-à-dire les avertissements, les avis, etc.). Comme `$type` nous spécifions une des constantes `E_...`, par exemple `E_WARNING`. Et si on passe `$message`, le message d'erreur doit également [correspondre au |#assert-match] modèle. Par exemple :
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Vérifie que la fonction `$callable` ne lève aucun avertissement/notice/erreur ou exception PHP. Elle est utile pour tester un morceau de code où il n'y a pas d'autre assertion.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` doit correspondre à `$pattern`. Nous pouvons utiliser deux variantes de motifs : les expressions régulières ou les caractères génériques.
 
 Si nous transmettons une expression régulière à `$pattern`, nous devons utiliser `~` or `#` pour la délimiter. Les autres délimiteurs ne sont pas pris en charge. Par exemple, test où `$var` ne doit contenir que des chiffres hexadécimaux :
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 L'assertion est identique à [Assert::match() |#assert-match] mais le motif est chargé depuis `$file`. Elle est utile pour tester des chaînes très longues. Le fichier de test est lisible.
 
 
diff --git a/tester/fr/guide.texy b/tester/fr/guide.texy
index 97457945fa..2be1388e6b 100644
--- a/tester/fr/guide.texy
+++ b/tester/fr/guide.texy
@@ -116,10 +116,10 @@ La sortie peut ressembler à ceci :
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Versions PHP prises en charge .[#toc-supported-php-versions]
 
 | version | compatible avec PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/fr/helpers.texy b/tester/fr/helpers.texy
index 3e0ea8efe8..48ad49c8bf 100644
--- a/tester/fr/helpers.texy
+++ b/tester/fr/helpers.texy
@@ -7,7 +7,7 @@ DomQuery
 `Tester\DomQuery` est une classe qui étend `SimpleXMLElement` avec des méthodes qui facilitent le test du contenu HTML ou XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# dans $html est une chaîne avec le document HTML, dans $dom nous obtenons l'élément racine
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# ou vérifier que l'élément correspond au sélecteur (à partir de la version 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Crée les fonctions globales `test()`, `setUp()` et `tearDown()` dans lesquelles vous pouvez diviser les tests.
+Crée les fonctions globales `test()`, `testException()`, `setUp()` et `tearDown()` dans lesquelles vous pouvez diviser les tests.
 
 ```php
 test('test description', function () {
diff --git a/tester/fr/running-tests.texy b/tester/fr/running-tests.texy
index a7fee934e3..c7cc661445 100644
--- a/tester/fr/running-tests.texy
+++ b/tester/fr/running-tests.texy
@@ -23,10 +23,10 @@ La sortie peut ressembler à ceci :
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Nous obtenons un aperçu des options de la ligne de commande en exécutant le Te
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (par exemple -o junit:output.xml)
+                                 Spécifier un ou plusieurs formats de sortie avec un nom de fichier optionnel.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Chemin d'accès au répertoire temporaire. Par défaut par sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Spécifie quel `php.ini` sera utilisé lors de l'exécution des tests. Par défa
 Un `php.ini` à l'échelle du système est utilisé. Donc, sur une plateforme UNIX, tous les fichiers `/etc/php/{sapi}/conf.d/*.ini` aussi. Voir la section [Own php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-La progression des tests est écrite dans le fichier. Tous les tests échoués, ignorés et aussi les tests réussis :
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Définit la valeur de la directive de configuration PHP pour les tests. Le paramètre peut être utilisé plusieurs fois.
@@ -127,13 +118,15 @@ Le testeur arrête les tests au premier échec.
 Les tests s'exécutent dans un `<num>` parallèles. La valeur par défaut est 8. Si nous souhaitons exécuter les tests en série, nous utilisons la valeur 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Format de sortie. Le format par défaut est celui de la console.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Format de sortie. Le format par défaut est celui de la console. Vous pouvez spécifier le nom du fichier dans lequel la sortie sera écrite (par exemple, `-o junit:output.xml`). L'option `-o` peut être répétée plusieurs fois pour générer plusieurs formats à la fois.
 
 - `console`: identique à celui par défaut, mais le logo ASCII n'est pas imprimé dans ce cas
+- `console-lines`: similaire à la console, mais le résultat de chaque test est listé sur une ligne séparée avec plus d'informations
 - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] approprié au traitement machine
 - `junit`: format XML de JUnit, également approprié au traitement par machine
+- `log`: Affiche l'état d'avancement des tests. Tous les tests échoués, ignorés et réussis
 - `none`: rien n'est imprimé
 
 
diff --git a/tester/hu/assertions.texy b/tester/hu/assertions.texy
index 5ca1ceecb2..a341f51295 100644
--- a/tester/hu/assertions.texy
+++ b/tester/hu/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` azonosnak kell lennie a `$actual` címmel. Ez megegyezik a `===` PHP-operátorral.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Ellentétes a `Assert::same()`-val , tehát megegyezik a `!==` PHP-operátorral.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` ugyanannak kell lennie, mint a `$actual`. A `Assert::same()`-től eltérően az objektum azonosságát, a kulcspárok => érték sorrendjét a tömbökben, valamint a minimálisan eltérő decimális számokat figyelmen kívül hagyja, ami a `$matchIdentity` és a `$matchOrder` beállításával módosítható.
 
 A következő esetek a `equal()` szempontjából azonosak, de a `same()` szempontjából nem:
@@ -45,73 +45,73 @@ Azonban vigyázat, a tömb `[1, 2]` és a `[2, 1]` nem egyenlőek, mert csak az
 Használhatjuk az úgynevezett [elvárásokat |#expectations] is a `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Ellentétben a `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Ha a `$actual` egy karakterlánc, akkor tartalmaznia kell a `$needle` részláncot. Ha tömb, akkor a `$needle` elemet kell tartalmaznia (szigorúan összehasonlításra kerül).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 A `Assert::contains()` ellentéte.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` tömbnek kell lennie, és tartalmaznia kell a `$needle` kulcsot.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` tömbnek kell lennie, és nem tartalmazhatja a `$needle` kulcsot.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` a `true` kell, hogy legyen, tehát `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` igaznak kell lennie, tehát teljesíti a `if ($value) ...` feltételt.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` kell lennie `false`, tehát `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` hamisnak kell lennie, tehát teljesíti a `if (!$value) ...` feltételt.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` a `null` kell, hogy legyen, tehát `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` nem lehet `null`, tehát `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` nem lehet szám. A NAN teszteléshez csak a `Assert::nan()` címet használja. A NAN érték nagyon specifikus, és a `Assert::same()` vagy a `Assert::equal()` állítások kiszámíthatatlanul viselkedhetnek.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 A `$value` elemszámának a `$count` kell lennie. Tehát ugyanaz, mint a `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` adott típusúnak kell lennie. Mint `$type` használhatjuk a stringet:
 - `array`
 - `list` - nullától kezdve a numerikus kulcsok növekvő sorrendjében indexelt tömb.
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - osztály nevét vagy objektumot közvetlenül, akkor át kell adnia `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 A `$callable` meghívásakor egy `$class` példányú kivételt kell dobni. Ha átadjuk a `$message` címet, a kivétel üzenetének [meg |#assert-match] kell [egyeznie |#assert-match]. És ha átadjuk a `$code`, a kivétel kódjának meg kell egyeznie.
 
 Például ez a teszt sikertelen, mert a kivétel üzenete nem egyezik:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Ellenőrzi, hogy a `$callable` meghívása a várt hibákat (azaz figyelmeztetéseket, értesítéseket stb.) generálja. Mint `$type` megadjuk a `E_...`, például a `E_WARNING` konstansok egyikét. És ha átadjuk a `$message`, a hibaüzenetnek is [meg |#assert-match] kell [felelnie |#assert-match] a mintának. Például:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Ellenőrzi, hogy a `$callable` függvény nem dob-e PHP figyelmeztetést/értesítést/hibát vagy kivételt. Hasznos egy olyan kódrészlet teszteléséhez, ahol nincs más állítás.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` kell, hogy egyezzen a `$pattern`. A minták két változatát használhatjuk: a reguláris kifejezéseket vagy a vadkártyákat.
 
 Ha egy reguláris kifejezést adunk át a `$pattern` címen, akkor a `~` or `#` címet kell használnunk az elhatároláshoz. Más elválasztójelek nem támogatottak. Például a teszt, ahol a `$var` csak hexadecimális számjegyeket tartalmazhat:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Az állítás megegyezik az [Assert::match()-vel |#assert-match], de a minta a `$file` oldalról töltődik be. Nagyon hosszú karakterláncok teszteléséhez hasznos. A tesztfájl olvashatóan áll.
 
 
diff --git a/tester/hu/guide.texy b/tester/hu/guide.texy
index d11610bf65..8048d58a88 100644
--- a/tester/hu/guide.texy
+++ b/tester/hu/guide.texy
@@ -116,10 +116,10 @@ A kimenet így nézhet ki:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Támogatott PHP verziók .[#toc-supported-php-versions]
 
 | verzió | kompatibilis a PHP-vel
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/hu/helpers.texy b/tester/hu/helpers.texy
index 13e4a27c04..6312705ce2 100644
--- a/tester/hu/helpers.texy
+++ b/tester/hu/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` egy olyan osztály, amely a `SimpleXMLElement` címet bővíti olyan metódusokkal, amelyek megkönnyítik a HTML- vagy XML-tartalom tesztelését.
 
 ```php
-# let's have an HTML document in $html that we load
+# a $html-ben egy karakterlánc a HTML dokumentummal, a $dom-ban pedig a gyökérelemet kapjuk meg.
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# vagy ellenőrizze, hogy az elem megfelel-e a szelektornak (a 2.5.3. verziótól)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Létrehozza a `test()`, `setUp()` és `tearDown()` globális függvényeket, amelyekre a teszteket feloszthatja.
+Létrehozza a `test()`, `testException()`, `setUp()` és `tearDown()` globális függvényeket, amelyekre a teszteket feloszthatja.
 
 ```php
 test('test description', function () {
diff --git a/tester/hu/running-tests.texy b/tester/hu/running-tests.texy
index a44e03b88a..ee1b5480a0 100644
--- a/tester/hu/running-tests.texy
+++ b/tester/hu/running-tests.texy
@@ -23,10 +23,10 @@ A kimenet így nézhet ki:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ A parancssori opciók áttekintését a Tester paraméterek nélküli vagy a `-h
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (pl. -o junit:output.xml)
+                                 Egy vagy több kimeneti formátum megadása opcionális fájlnévvel.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Az ideiglenes könyvtár elérési útvonala. Alapértelmezett a sys_get_temp_dir() által.
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Megadja, hogy a tesztek futtatásakor melyik `php.ini` oldalt használja a rends
 Egy rendszerszintű `php.ini` kerül felhasználásra. Tehát UNIX platformon az összes `/etc/php/{sapi}/conf.d/*.ini` fájl is. Lásd a [saját php.ini |#Own php.ini] részt.
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-A tesztelés előrehaladása kiíródik a fájlba. Minden sikertelen, kihagyott és sikeres tesztet:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 A tesztek PHP konfigurációs direktíva értékének beállítása. A paraméter többször is használható.
@@ -127,13 +118,15 @@ A tesztelő az első sikertelen tesztnél leállítja a tesztelést.
 A tesztek futtatása egy `<num>` párhuzamos előfeldolgozásban. Az alapértelmezett érték 8. Ha a teszteket sorban szeretnénk futtatni, akkor az 1 értéket használjuk.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Kimeneti formátum. Az alapértelmezett a konzol formátum.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Kimeneti formátum. Az alapértelmezett a konzol formátum. Megadhatja annak a fájlnak a nevét, amelybe a kimenetet írja (pl. `-o junit:output.xml`). A `-o` opciót többször is megismételhetjük, hogy egyszerre több formátumot generáljunk.
 
 - `console`: ugyanaz, mint az alapértelmezett, de az ASCII logó ebben az esetben nem kerül kiírásra.
+- `console-lines`: hasonló a konzolhoz, de az egyes tesztek eredményei külön sorban, több információval szerepelnek
 - `tap`: gépi feldolgozásra alkalmas [TAP formátum |https://en.wikipedia.org/wiki/Test_Anything_Protocol].
 - `junit`: JUnit XML formátum, gépi feldolgozásra is alkalmas.
+- `log`: A tesztelés előrehaladásának kimenete. Minden sikertelen, kihagyott és sikeres tesztet
 - `none`: semmi sem kerül kinyomtatásra
 
 
diff --git a/tester/it/assertions.texy b/tester/it/assertions.texy
index f7b9b7859a..d26882630e 100644
--- a/tester/it/assertions.texy
+++ b/tester/it/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` deve essere uguale a `$actual`. È uguale all'operatore PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Opposto a `Assert::same()`, quindi uguale all'operatore PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` deve essere uguale a `$actual`. A differenza di `Assert::same()`, vengono ignorati l'identità degli oggetti, l'ordine delle coppie chiave => valore negli array e i numeri decimali marginalmente diversi, che possono essere modificati impostando `$matchIdentity` e `$matchOrder`.
 
 I casi seguenti sono identici dal punto di vista di `equal()`, ma non per `same()`:
@@ -45,73 +45,73 @@ Tuttavia, attenzione, l'array `[1, 2]` e `[2, 1]` non sono uguali, perché solo
 È inoltre possibile utilizzare le cosiddette [aspettative |#expectations] in `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Opposto a `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Se `$actual` è una stringa, deve contenere la sottostringa `$needle`. Se è una matrice, deve contenere l'elemento `$needle` (viene confrontato strettamente).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Opposto a `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` deve essere un array e deve contenere la chiave `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` deve essere un array e non deve contenere la chiave `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` deve essere `true`, quindi `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` deve essere vero, quindi soddisfa la condizione `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` deve essere `false`, quindi `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` deve essere falso, quindi soddisfa la condizione `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` deve essere `null`, quindi `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` non deve essere `null`, quindi `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` deve essere Not a Number. Utilizzare solo `Assert::nan()` per i test NAN. Il valore NAN è molto specifico e le asserzioni `Assert::same()` o `Assert::equal()` possono comportarsi in modo imprevedibile.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Il numero di elementi in `$value` deve essere `$count`. Quindi lo stesso di `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` deve essere di un determinato tipo. Come `$type` possiamo usare stringa:
 - `array`
 - `list` - array indicizzato in ordine crescente di chiavi numeriche a partire da zero
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - nome della classe o dell'oggetto direttamente, allora deve passare `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 All'invocazione di `$callable` deve essere lanciata un'eccezione dell'istanza `$class`. Se si passa `$message`, il messaggio dell'eccezione deve [corrispondere |#assert-match]. E se si passa `$code`, il codice dell'eccezione deve essere lo stesso.
 
 Ad esempio, questo test fallisce perché il messaggio dell'eccezione non corrisponde:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Controlla che l'invocazione di `$callable` generi gli errori previsti (cioè avvisi, notifiche, ecc.). Come `$type` si specifica una delle costanti `E_...`, ad esempio `E_WARNING`. E se si supera `$message`, anche il messaggio di errore deve [corrispondere al |#assert-match] modello. Ad esempio:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Controlla che la funzione `$callable` non lanci alcun avviso/nota/errore o eccezione PHP. È utile per testare un pezzo di codice in cui non ci sono altre asserzioni.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` deve corrispondere a `$pattern`. Si possono usare due varianti di pattern: espressioni regolari o caratteri jolly.
 
 Se si passa un'espressione regolare come `$pattern`, si deve usare `~` or `#` per delimitarla. Altri delimitatori non sono supportati. Ad esempio, il test in cui `$var` deve contenere solo cifre esadecimali:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 L'asserzione è identica a [Assert::match() |#assert-match], ma il modello viene caricato da `$file`. È utile per testare stringhe molto lunghe. Il file di test è leggibile.
 
 
diff --git a/tester/it/guide.texy b/tester/it/guide.texy
index 33811b8bfb..c8b830e795 100644
--- a/tester/it/guide.texy
+++ b/tester/it/guide.texy
@@ -116,10 +116,10 @@ L'output può essere simile a questo:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Versioni PHP supportate .[#toc-supported-php-versions]
 
 | Versione compatibile con PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/it/helpers.texy b/tester/it/helpers.texy
index 2f48325d7f..f9674eb746 100644
--- a/tester/it/helpers.texy
+++ b/tester/it/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` è una classe che estende `SimpleXMLElement` con metodi che facilitano il test di contenuti HTML o XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# in $html c'è una stringa con il documento HTML, in $dom c'è l'elemento root
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# o verificare che l'elemento corrisponda al selettore (dalla versione 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Crea le funzioni globali `test()`, `setUp()` e `tearDown()` in cui è possibile suddividere i test.
+Crea le funzioni globali `test()`, `testException()`, `setUp()` e `tearDown()` in cui è possibile suddividere i test.
 
 ```php
 test('test description', function () {
diff --git a/tester/it/running-tests.texy b/tester/it/running-tests.texy
index e3d685a801..8e040201cb 100644
--- a/tester/it/running-tests.texy
+++ b/tester/it/running-tests.texy
@@ -23,10 +23,10 @@ L'output può apparire come:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Otteniamo una panoramica delle opzioni da riga di comando eseguendo il Tester se
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (ad esempio -o junit:output.xml)
+                                 Specifica uno o più formati di output con un nome di file opzionale.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Percorso della directory temporanea. Predefinito da sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Specifica quale `php.ini` sarà usato durante l'esecuzione dei test. Per imposta
 Viene utilizzato un `php.ini` a livello di sistema. Quindi, su piattaforma UNIX, anche tutti i file `/etc/php/{sapi}/conf.d/*.ini`. Vedere la sezione [php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Il progresso dei test viene scritto nel file. Tutti i test falliti, saltati e anche quelli riusciti:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Imposta il valore della direttiva di configurazione PHP per i test. Il parametro può essere usato più volte.
@@ -127,13 +118,15 @@ Il tester interrompe il test al primo fallimento.
 I test vengono eseguiti in un `<num>` in parallelo. Il valore predefinito è 8. Se si desidera eseguire i test in serie, si utilizza il valore 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Formato di output. Il formato predefinito è quello della console.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Formato di uscita. Il formato predefinito è quello della console. È possibile specificare il nome del file in cui verrà scritto l'output (ad esempio, `-o junit:output.xml`). L'opzione `-o` può essere ripetuta più volte per generare più formati contemporaneamente.
 
 - `console`: uguale a quello predefinito, ma in questo caso il logo ASCII non viene stampato
+- `console-lines`: simile alla console, ma il risultato di ogni test è elencato su una riga separata con maggiori informazioni
 - `tap`: [formato TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] adatto all'elaborazione automatica
 - `junit`: formato XML JUnit, appropriato anche per l'elaborazione meccanica
+- `log`: Visualizza l'avanzamento dei test. Tutti i test falliti, saltati e anche quelli riusciti
 - `none`: non viene stampato nulla
 
 
diff --git a/tester/pl/assertions.texy b/tester/pl/assertions.texy
index 04e9b5e33a..b7208cf7ff 100644
--- a/tester/pl/assertions.texy
+++ b/tester/pl/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` musi być identyczny z `$actual`. Identyczny jak operator PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Przeciwieństwo `Assert::same()`, czyli to samo co operator PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` musi być taka sama jak `$actual`. W przeciwieństwie do `Assert::same()`, tożsamość obiektu, kolejność par kluczy => wartości w polach i marginalnie różne liczby dziesiętne są ignorowane, co można zmienić poprzez ustawienie `$matchIdentity` i `$matchOrder`.
 
 Poniższe przypadki są identyczne z perspektywy `equal()`, ale nie `same()`:
@@ -45,73 +45,73 @@ Jednakże, uważaj, pole `[1, 2]` a `[2, 1]` nie są takie same, ponieważ tylko
 Ponadto w `$expected` można wykorzystać tzw. [oczekiwania |#Expectations].
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Przeciwieństwo `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Jeśli `$actual` jest ciągiem, musi zawierać podłańcuch `$needle`. Jeśli jest to tablica, musi zawierać element `$needle` (dopasowany ściśle).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Przeciwieństwo `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` musi być tablicą i musi zawierać klucz `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` musi być tablicą i nie może zawierać klucza `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` musi być `true`, czyli `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` musi być prawdziwa, czyli spełnia warunek `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` musi być `false`, czyli `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` musi być fałszywy, czyli spełnia warunek `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` musi być `null`, czyli `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` nie może być `null`, czyli `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` musi być "Not a Number". Do testowania wartości NAN używaj wyłącznie `Assert::nan()` Wartość NAN jest bardzo specyficzna i asercje `Assert::same()` lub `Assert::equal()` mogą działać nieoczekiwanie.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Liczba elementów w `$value` musi być `$count`. Zatem taka sama jak `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` musi być danego typu. Jako `$type` możemy użyć ciągu znaków:
 - `array`
 - `list` - tablica indeksowana rosnącym szeregiem kluczy numerycznych od zera
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - nazwa klasy lub samego obiektu, to musi być `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Po wywołaniu `$callable` musi zostać rzucony wyjątek klasowy `$class` Jeśli podamy `$message`, komunikat wyjątku musi [pasować do wzorca |#Assert-match], a jeśli podamy `$code`, kody muszą być ściśle [dopasowane |#Assert-match].
 
 Poniższy test kończy się niepowodzeniem, ponieważ komunikat wyjątku nie pasuje:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Sprawdza, czy funkcja `$callable` wygenerowała oczekiwane błędy (tj. Ostrzeżenia, powiadomienia itp.). Jako `$type` podajemy jedną ze stałych `E_...`, czyli np. `E_WARNING`. A jeśli określimy `$message`, to komunikat o błędzie musi [pasować do wzorca |#Assert-match]. Na przykład:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Sprawdza, czy funkcja `$callable` nie wygenerowała żadnych ostrzeżeń, błędów lub wyjątków. Jest to przydatne do testowania fragmentów kodu, w których nie ma innej asercji.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` musi pasować do wzorca `$pattern`. Możemy użyć dwóch wariantów wzorców: wyrażeń regularnych lub symboli wieloznacznych.
 
 Jeśli przekażemy wyrażenie regularne jako `$pattern`, musimy użyć `~` nebo `#` do jego delimitacji, inne delimitery nie są obsługiwane. Na przykład test, w którym `$var` musi zawierać tylko cyfry szesnastkowe:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Asercja jest identyczna jak [Assert::match() |#Assert-match], ale wzór jest odczytywany z `$file`. Jest to przydatne do testowania bardzo długich łańcuchów. Plik testowy pozostaje przezroczysty.
 
 
diff --git a/tester/pl/guide.texy b/tester/pl/guide.texy
index ef741f36ad..4f68adba4b 100644
--- a/tester/pl/guide.texy
+++ b/tester/pl/guide.texy
@@ -116,10 +116,10 @@ Dane wyjściowe mogą wyglądać tak:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Obsługiwane wersje PHP .[#toc-supported-php-versions]
 
 | wersje | kompatybilne z PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/pl/helpers.texy b/tester/pl/helpers.texy
index 72bd8b7b52..87c0d1ab10 100644
--- a/tester/pl/helpers.texy
+++ b/tester/pl/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` jest klasą rozszerzającą `SimpleXMLElement` o metody ułatwiające testowanie zawartości HTML lub XML.
 
 ```php
-# mějme v $html HTML dokument, který načteme
+# w $html jest łańcuch z dokumentem HTML, w $dom otrzymujemy element główny
 $dom = Tester\DomQuery::fromHtml($html);
 
 # můžeme testovat přítomnost elementů podle CSS selektorů
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # nebo vybrat elementy jako pole DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# lub sprawdzić, czy element pasuje do selektora (od wersji 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Tworzy globalne funkcje `test()`, `setUp()`, i `tearDown()`, na które można podzielić swoje testy.
+Tworzy globalne funkcje `test()`, `testException()`, `setUp()`, i `tearDown()`, na które można podzielić swoje testy.
 
 ```php
 test('popis testu', function () {
diff --git a/tester/pl/running-tests.texy b/tester/pl/running-tests.texy
index f4f3a9625e..2fa84feefe 100644
--- a/tester/pl/running-tests.texy
+++ b/tester/pl/running-tests.texy
@@ -23,10 +23,10 @@ Dane wyjściowe mogą wyglądać jak:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Przegląd opcji wiersza poleceń uzyskujemy uruchamiając Tester bez parametrów
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (np. -o junit:output.xml)
+                                 Określa jeden lub więcej formatów wyjściowych z opcjonalną nazwą pliku.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Ścieżka do katalogu tymczasowego. Domyślna przez sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Określa, która strona `php.ini` będzie używana podczas uruchamiania testów.
 Używany jest ogólnosystemowy `php.ini`. Czyli na platformie UNIX wszystkie pliki `/etc/php/{sapi}/conf.d/*.ini` również. Patrz rozdział [Własny php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Postęp testów jest zapisywany do pliku. Wszystkie nieudane, pominięte, a także udane testy:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Ustawia wartość dyrektywy konfiguracyjnej PHP dla testów. Parametr może być użyty wielokrotnie.
@@ -127,13 +118,15 @@ Tester zatrzymuje testowanie po pierwszym nieudanym teście.
 Testy są uruchamiane w `<num>` równoległych procesach. Domyślna wartość to 8. Jeśli chcemy uruchamiać testy szeregowo, używamy wartości 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Format wyjścia. Domyślnie jest to format konsoli.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Format wyjścia. Domyślnie jest to format konsolowy. Można określić nazwę pliku, do którego zostaną zapisane dane wyjściowe (np. `-o junit:output.xml`). Opcja `-o` może być powtarzana wielokrotnie w celu wygenerowania wielu formatów jednocześnie.
 
 - `console`: taki sam jak domyślny, ale w tym przypadku nie jest wypisywane logo ASCII
+- `console-lines`: podobny do konsoli, ale wynik każdego testu jest wyświetlany w osobnym wierszu z większą ilością informacji
 - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] odpowiedni do przetwarzania maszynowego
 - `junit`: format JUnit XML, odpowiedni również do przetwarzania maszynowego
+- `log`: Wyświetla postęp testowania. Wszystkie nieudane, pominięte, a także udane testy
 - `none`: nic nie jest drukowane
 
 
diff --git a/tester/pt/assertions.texy b/tester/pt/assertions.texy
index 8cf920b3b5..013893af06 100644
--- a/tester/pt/assertions.texy
+++ b/tester/pt/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` deve ser o mesmo que `$actual`. É o mesmo que o operador de PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Ao contrário de `Assert::same()`, então é o mesmo que o operador PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` deve ser o mesmo que `$actual`. Ao contrário de `Assert::same()`, a identidade do objeto, a ordem dos pares de chaves => valor em arrays e números decimais marginalmente diferentes são ignorados, o que pode ser alterado através da configuração `$matchIdentity` e `$matchOrder`.
 
 Os seguintes casos são idênticos do ponto de vista de `equal()`, mas não para `same()`:
@@ -45,73 +45,73 @@ Entretanto, tenha cuidado, a matriz `[1, 2]` e `[2, 1]` não são iguais, porque
 Você também pode usar as chamadas [expectativas |#expectations] em `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Oposto a `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Se `$actual` for um fio, ele deve conter o substrato `$needle`. Se for uma matriz, deve conter o elemento `$needle` (é comparado estritamente).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Oposto a `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` deve ser uma matriz e deve conter a chave `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` deve ser uma matriz e não deve conter a chave `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` deve ser `true`, portanto `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` deve ser verdadeira, portanto satisfaz a condição `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` deve ser `false`, portanto `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` deve ser falso, por isso satisfaz a condição `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` deve ser `null`, portanto `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` não deve ser `null`, portanto `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` não deve ser um número. Use apenas o `Assert::nan()` para testes NAN. O valor do NAN é muito específico e as afirmações `Assert::same()` ou `Assert::equal()` podem se comportar de forma imprevisível.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 O número de elementos em `$value` deve ser `$count`. Portanto, o mesmo que `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` deve ser de um determinado tipo. Como `$type`, podemos usar cordel:
 - `array`
 - `list` - matriz indexada em ordem ascendente de chaves numéricas a partir de zero
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - nome da classe ou objeto deve então passar diretamente `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Em `$callable` deve ser lançada uma exceção de instância `$class`. Se passarmos `$message`, a mensagem da exceção deve [coincidir |#assert-match]. E se passarmos `$code`, o código da exceção deve ser o mesmo.
 
 Por exemplo, este teste falha porque a mensagem da exceção não corresponde:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Verifica se a invocação `$callable` gera os erros esperados (ou seja, avisos, avisos, etc.). Como `$type`, especificamos uma das constantes `E_...`, por exemplo `E_WARNING`. E, se passar `$message`, a mensagem de erro também deve [corresponder |#assert-match] ao padrão. Por exemplo:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Verifica se a função `$callable` não lança nenhum aviso/notificação/erro ou exceção em PHP. É útil para testar um pedaço de código onde não há outra asserção.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` Devemos corresponder a `$pattern`. Podemos utilizar duas variantes de padrões: expressões regulares ou wildcards.
 
 Se passarmos uma expressão regular como `$pattern`, devemos usar `~` or `#` para delimitá-la. Outros delimitadores não são suportados. Por exemplo, teste onde `$var` deve conter apenas dígitos hexadecimais:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 A afirmação é idêntica a [Assert::match() |#assert-match] mas o padrão é carregado a partir de `$file`. É útil para testes de cordas muito longas. Os arquivos de teste podem ser lidos.
 
 
diff --git a/tester/pt/guide.texy b/tester/pt/guide.texy
index edbe36e3b3..6f31106fc6 100644
--- a/tester/pt/guide.texy
+++ b/tester/pt/guide.texy
@@ -116,10 +116,10 @@ A saída pode ser assim:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Versões PHP suportadas .[#toc-supported-php-versions]
 
 | versão | compatível com PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/pt/helpers.texy b/tester/pt/helpers.texy
index 4b20d97442..2fdc8a72b0 100644
--- a/tester/pt/helpers.texy
+++ b/tester/pt/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` é uma classe que se estende `SimpleXMLElement` com métodos que facilitam o teste de conteúdo HTML ou XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# em $html é uma string com o documento HTML, em $dom obtemos o elemento raiz
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# ou verificar se o elemento corresponde ao seletor (a partir da versão 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Cria as funções globais `test()`, `setUp()` e `tearDown()`, nas quais é possível dividir os testes.
+Cria as funções globais `test()`, `testException()`, `setUp()` e `tearDown()`, nas quais é possível dividir os testes.
 
 ```php
 test('test description', function () {
diff --git a/tester/pt/running-tests.texy b/tester/pt/running-tests.texy
index 0621d3f451..8d06996771 100644
--- a/tester/pt/running-tests.texy
+++ b/tester/pt/running-tests.texy
@@ -23,10 +23,10 @@ O resultado pode ser parecido:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Obtemos uma visão geral das opções de linha de comando executando o Tester se
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (por exemplo, -o junit:output.xml)
+                                 Especifique um ou mais formatos de saída com um nome de arquivo opcional.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Caminho para o diretório temporário. Padrão por sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Especifica qual `php.ini` será usado ao executar testes. Por padrão, nenhum ph
 É utilizado um sistema de todo o sistema `php.ini`. Assim, na plataforma UNIX, todos os arquivos `/etc/php/{sapi}/conf.d/*.ini` também são utilizados. Veja a seção [php.ini Próprio |#Own php.ini].
 
 
-"'-l | --log <path>"'". .[filter]
----------------------------------
-Os testes de progresso são escritos em arquivo. Todos os testes falharam, saltaram e também foram bem-sucedidos:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Define o valor da diretiva de configuração PHP para testes. O parâmetro pode ser usado várias vezes.
@@ -127,13 +118,15 @@ O testador interrompe os testes após o primeiro teste reprovado.
 Os testes são realizados em um `<num>` precessos paralelos. O valor padrão é 8. Se desejarmos realizar testes em série, usamos o valor 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Formato de saída. O formato padrão é o formato do console.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Formato de saída. O padrão é o formato do console. Você pode especificar o nome do arquivo no qual a saída será gravada (por exemplo, `-o junit:output.xml`). A opção `-o` pode ser repetida várias vezes para gerar vários formatos de uma só vez.
 
 - `console`: o mesmo que o padrão, mas o logotipo ASCII não é impresso neste caso
+- `console-lines`: semelhante ao console, mas o resultado de cada teste é listado em uma linha separada com mais informações
 - `tap`: [Formato TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] apropriado para o processamento de máquinas
 - `junit`: formato JUnit XML, apropriado também para processamento em máquinas
+- `log`: Exibe o progresso do teste. Todos os testes falhos, ignorados e também os bem-sucedidos
 - `none`: nada é impresso
 
 
diff --git a/tester/ro/assertions.texy b/tester/ro/assertions.texy
index ac720308aa..e986b7bfa7 100644
--- a/tester/ro/assertions.texy
+++ b/tester/ro/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` trebuie să fie aceeași cu `$actual`. Este același lucru cu operatorul PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Opusul lui `Assert::same()`, deci este același lucru cu operatorul PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` trebuie să fie același cu `$actual`. Spre deosebire de `Assert::same()`, identitatea obiectului, ordinea perechilor cheie => valoare în array-uri și numerele zecimale marginal diferite sunt ignorate, care pot fi modificate prin setarea `$matchIdentity` și `$matchOrder`.
 
 Următoarele cazuri sunt identice din punctul de vedere al `equal()`, dar nu și pentru `same()`:
@@ -45,73 +45,73 @@ Cu toate acestea, atenție, matricea `[1, 2]` și `[2, 1]` nu sunt egale, deoare
 Puteți utiliza, de asemenea, așa-numitele [așteptări |#expectations] în `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Opusul lui `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Dacă `$actual` este un șir de caractere, acesta trebuie să conțină subșirul `$needle`. Dacă este o matrice, trebuie să conțină elementul `$needle` (acesta este comparat strict).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Opusul lui `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` trebuie să fie o matrice și să conțină cheia `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` trebuie să fie o matrice și să nu conțină cheia `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` trebuie să fie `true`, deci `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` trebuie să fie adevărat, deci satisface condiția `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` trebuie să fie `false`, deci `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` trebuie să fie falsey, deci îndeplinește condiția `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` trebuie să fie `null`, deci `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` nu trebuie să fie `null`, deci `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` trebuie să nu fie un număr. Utilizați numai `Assert::nan()` pentru testarea NAN. Valoarea NAN este foarte specifică, iar afirmațiile `Assert::same()` sau `Assert::equal()` se pot comporta în mod imprevizibil.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Numărul de elemente din `$value` trebuie să fie `$count`. Deci la fel ca `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` trebuie să fie de un anumit tip. La fel ca `$type` putem folosi string:
 - `array`
 - `list` - matrice indexată în ordine crescătoare a cheilor numerice de la zero.
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - numele clasei sau obiectul direct, atunci trebuie să treacă `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 La invocarea `$callable` trebuie să se arunce o excepție de instanță `$class`. Dacă se trece `$message`, mesajul excepției trebuie să [corespundă |#assert-match]. Iar dacă se trece `$code`, codul excepției trebuie să fie același.
 
 De exemplu, acest test eșuează deoarece mesajul excepției nu se potrivește:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Verifică dacă invocarea `$callable` generează erorile așteptate (adică avertismente, notificări etc.). Ca `$type` se specifică una dintre constantele `E_...`, de exemplu `E_WARNING`. Iar dacă se trece `$message`, mesajul de eroare trebuie să [corespundă |#assert-match] și el modelului. De exemplu:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Verifică dacă funcția `$callable` nu aruncă niciun avertisment/notificare/error sau excepție PHP. Este utilă pentru testarea unei bucăți de cod în care nu există nicio altă afirmație.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` trebuie să se potrivească cu `$pattern`. Putem utiliza două variante de tipare: expresii regulate sau caractere sălbatice.
 
 Dacă trecem o expresie regulată ca `$pattern`, trebuie să folosim `~` or `#` pentru a o delimita. Alte delimitatoare nu sunt acceptate. De exemplu, testul în care `$var` trebuie să conțină numai cifre hexazecimale:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Afirmația este identică cu [Assert::match() |#assert-match], dar modelul este încărcat din `$file`. Este utilă pentru testarea șirurilor foarte lungi. Fișierul de test stă în picioare lizibil.
 
 
diff --git a/tester/ro/guide.texy b/tester/ro/guide.texy
index da369c5d74..3078deac72 100644
--- a/tester/ro/guide.texy
+++ b/tester/ro/guide.texy
@@ -116,10 +116,10 @@ Rezultatul poate arăta astfel:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Versiuni PHP acceptate .[#toc-supported-php-versions]
 
 | versiune | compatibil cu PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/ro/helpers.texy b/tester/ro/helpers.texy
index 9a53f54e34..7f93e9a4df 100644
--- a/tester/ro/helpers.texy
+++ b/tester/ro/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` este o clasă care extinde `SimpleXMLElement` cu metode care facilitează testarea conținutului HTML sau XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# în $html este un șir de caractere cu documentul HTML, în $dom obținem elementul rădăcină
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# sau verifică dacă elementul se potrivește cu selectorul (din versiunea 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Creează funcțiile globale `test()`, `setUp()` și `tearDown()` în care puteți împărți testele.
+Creează funcțiile globale `test()`, `testException()`, `setUp()` și `tearDown()` în care puteți împărți testele.
 
 ```php
 test('test description', function () {
diff --git a/tester/ro/running-tests.texy b/tester/ro/running-tests.texy
index 5563f703e0..788d8f03de 100644
--- a/tester/ro/running-tests.texy
+++ b/tester/ro/running-tests.texy
@@ -23,10 +23,10 @@ Rezultatul poate arăta astfel:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Obținem prezentarea generală a opțiunilor din linia de comandă prin rularea
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (de exemplu, -o junit:output.xml)
+                                 Specifică unul sau mai multe formate de ieșire cu nume de fișier opțional.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Calea către directorul temporar. Predefinit de sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Specifică ce `php.ini` va fi utilizat la rularea testelor. În mod implicit, nu
 Se utilizează un sistem la nivel de sistem `php.ini`. Deci, pe platforma UNIX, toate fișierele `/etc/php/{sapi}/conf.d/*.ini`. A se vedea secțiunea [Own php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Progresul testării este scris în fișier. Toate testele eșuate, sărite, dar și cele reușite:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Stabilește valoarea directivei de configurare PHP pentru teste. Parametrul poate fi utilizat de mai multe ori.
@@ -127,13 +118,15 @@ Testerul oprește testarea la primul test eșuat.
 Testele se execută în `<num>` precesiuni paralele. Valoarea implicită este 8. Dacă dorim să rulăm testele în serie, folosim valoarea 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Format de ieșire. Formatul implicit este cel de consolă.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Format de ieșire. Formatul implicit este cel de consolă. Puteți specifica numele fișierului în care va fi scrisă ieșirea (de exemplu, `-o junit:output.xml`). Opțiunea `-o` poate fi repetată de mai multe ori pentru a genera mai multe formate deodată.
 
 - `console`: la fel ca în mod implicit, dar logo-ul ASCII nu este tipărit în acest caz.
+- `console-lines`: similar cu consola, dar rezultatul fiecărui test este listat pe o linie separată cu mai multe informații
 - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] adecvat pentru procesarea pe mașină
 - `junit`: format JUnit XML, adecvat și pentru procesarea pe mașină
+- `log`: Afișează progresul testelor. Toate testele eșuate, sărite și, de asemenea, cele reușite
 - `none`: nu se tipărește nimic
 
 
diff --git a/tester/ru/assertions.texy b/tester/ru/assertions.texy
index 493cb21305..0694bff7c8 100644
--- a/tester/ru/assertions.texy
+++ b/tester/ru/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` должно быть то же самое, что и `$actual`. Это то же самое, что и оператор PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Противоположен оператору `Assert::same()`, поэтому совпадает с оператором PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` должно быть таким же, как `$actual`. В отличие от `Assert::same()`, идентичность объектов, порядок пар ключ => значение в массивах и незначительно отличающиеся десятичные числа игнорируются, что можно изменить, задав `$matchIdentity` и `$matchOrder`.
 
 Следующие случаи идентичны с точки зрения `equal()`, но не для `same()`:
@@ -45,73 +45,73 @@ Assert::equal(
 Вы также можете использовать так называемые [ожидания |#Expectations] в `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Противоположность `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Если `$actual` - строка, то она должна содержать подстроку `$needle`. Если это массив, то он должен содержать элемент `$needle` (он сравнивается строго).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Противоположность `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` должен быть массивом и содержать ключ `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` должен быть массивом и не должен содержать ключ `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` должен быть `true`, поэтому `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` должно быть истинным, поэтому оно удовлетворяет условию `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` должно быть `false`, поэтому `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` должен быть ложным, поэтому он удовлетворяет условию `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` должно быть `null`, поэтому `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` не должно быть `null`, поэтому `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` должен быть Not a Number. Используйте только `Assert::nan()` для тестирования NAN. Значение NAN очень специфично, и утверждения `Assert::same()` или `Assert::equal()` могут повести себя непредсказуемо.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Количество элементов в `$value` должно быть равно `$count`. То есть то же самое, что и `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` должен быть заданного типа. В качестве `$type` мы можем использовать строку:
 - `array`
 - `list` - массив, индексированный в порядке возрастания числовых ключей от нуля.
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - имя класса или объекта напрямую, то необходимо передать `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 При вызове `$callable` должно быть выброшено исключение экземпляра `$class`. Если мы передаем `$message`, то сообщение исключения должно [совпадать |#Assert-match]. А если мы передаем `$code`, то код исключения должен быть таким же.
 
 Например, этот тест не пройден, потому что сообщение исключения не совпадает:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Проверяет, что вызов `$callable` генерирует ожидаемые ошибки (т.е. предупреждения, уведомления и т.д.). В качестве `$type` мы указываем одну из констант `E_...`, например `E_WARNING`. И если передаем `$message`, то сообщение об ошибке также должно [соответствовать |#Assert-match] шаблону. Например:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Проверяет, что функция `$callable` не выбрасывает никаких предупреждений/замечаний/ошибок или исключений PHP. Это полезно для проверки части кода, где нет других утверждений.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` должен соответствовать `$pattern`. Мы можем использовать два варианта шаблонов: регулярные выражения или подстановочные знаки.
 
 Если мы передаем регулярное выражение как `$pattern`, мы должны использовать `~` or `#` для его разделения. Другие разделители не поддерживаются. Например, тест, где `$var` должен содержать только шестнадцатеричные цифры:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Утверждение идентично [Assert::match() |#Assert-match], но шаблон загружается из `$file`. Это полезно для тестирования очень длинных строк. Тестовый файл становится читабельным.
 
 
diff --git a/tester/ru/guide.texy b/tester/ru/guide.texy
index fc73305514..532b61548e 100644
--- a/tester/ru/guide.texy
+++ b/tester/ru/guide.texy
@@ -116,10 +116,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Tester может генерировать отчеты с обзором тог
 
 | Версия | совместимая с PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/ru/helpers.texy b/tester/ru/helpers.texy
index 87d907ec78..ce17cc0fe1 100644
--- a/tester/ru/helpers.texy
+++ b/tester/ru/helpers.texy
@@ -7,7 +7,7 @@ DomQuery
 `Tester\DomQuery` это класс, расширяющий `SimpleXMLElement` с методами, облегчающими тестирование содержимого HTML или XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# в $html - строка с HTML-документом, в $dom - корневой элемент
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# или проверьте, соответствует ли элемент селектору (начиная с версии 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Создает глобальные функции `test()`, `setUp()` и `tearDown()`, на которые можно разбить тесты.
+Создает глобальные функции `test()`, `testException()`, `setUp()` и `tearDown()`, на которые можно разбить тесты.
 
 ```php
 test('описание теста', function () {
diff --git a/tester/ru/running-tests.texy b/tester/ru/running-tests.texy
index 3ab154cdae..5525ed6591 100644
--- a/tester/ru/running-tests.texy
+++ b/tester/ru/running-tests.texy
@@ -23,10 +23,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Использование:
     tester [параметры] [<тестовый файл> | <каталог>]...
@@ -58,16 +58,16 @@ PHP 7.4.8 (cli) | php -n | 8 threads
     -p <путь>                    Укажите интерпретатор PHP для запуска (по умолчанию: php).
     -c <path>                    Искать php.ini файл (или искать в директории) <path>.
     -C                           Использовать общесистемный php.ini.
-    -l | --log <путь>            Запись журнала в файл <путь>.
     -d <ключ=значение>...        Определить INI-запись 'key' со значением 'value'.
     -s                           Показать информацию о пропущенных тестах.
     --stop-on-fail               Остановить выполнение при первом сбое.
     -j <num>                     Выполнять <num> заданий параллельно (по умолчанию: 8).
-    -o <console|tap|junit|none>  Указать формат вывода.
+    -o <console|console-lines|tap|junit|log|none> (например, -o junit:output.xml)
+                                 Укажите один или несколько выходных форматов с необязательным именем файла.
     -w | --watch <путь>          Каталог просмотра.
     -i | --info                  Показать информацию об окружении тестов и выйти.
     --setup <путь>               Сценарий для настройки бегущей строки.
-    --temp <путь>                Путь к временному каталогу. По умолчанию: sys_get_temp_dir().
+    --temp <path>                Путь к временному каталогу. По умолчанию определяется функцией sys_get_temp_dir().
     --colors [1|0]               Включить или отключить цвета.
     --coverage <путь>            Генерировать отчет о покрытии кода в файл.
     --coverage-src <путь>        Путь к исходному коду.
@@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests
 Используется общесистемный `php.ini`. Поэтому на платформе UNIX все файлы `/etc/php/{sapi}/conf.d/*.ini` тоже. См. раздел [Собственный php.ini |#Own php.ini].
 
 
-'' -l | --log <path>'' .[filter]
---------------------------------
-Ход тестирования записывается в файл. Все неудачные, пропущенные, а также успешные тесты:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Устанавливает значение директивы конфигурации PHP для тестов. Параметр может быть использован несколько раз.
@@ -127,13 +118,15 @@ tester -d max_execution_time=20
 Тесты запускаются в `<num>` параллельно. Значение по умолчанию - 8. Если мы хотим запускать тесты последовательно, мы используем значение 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Формат вывода. По умолчанию - консольный формат.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Формат вывода. По умолчанию используется консольный формат. Вы можете указать имя файла, в который будет записан вывод (например, `-o junit:output.xml`). Опцию `-o` можно повторить несколько раз, чтобы сгенерировать несколько форматов одновременно.
 
 - `console`: то же, что и по умолчанию, но ASCII-логотип в этом случае не печатается.
+- `console-lines`: аналогично консоли, но результат каждого теста выводится в отдельной строке с дополнительной информацией
 - `tap`: [формат TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol], подходящий для машинной обработки
 - `junit`: формат JUnit XML, также подходящий для машинной обработки.
+- `log`: Выводит информацию о ходе тестирования. Все неудачные, пропущенные, а также успешные тесты
 - `none`: ничего не печатается
 
 
diff --git a/tester/sl/assertions.texy b/tester/sl/assertions.texy
index 1b1c792bae..a0092de8ce 100644
--- a/tester/sl/assertions.texy
+++ b/tester/sl/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` mora biti enak kot `$actual`. Je enak kot operator PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Nasproten kot `Assert::same()`, zato je enak operatorju PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` mora biti enak kot `$actual`. Za razliko od `Assert::same()` se identiteta predmetov, vrstni red parov ključ => vrednost v poljih in mejno različna decimalna števila ne upoštevajo, kar je mogoče spremeniti z nastavitvijo `$matchIdentity` in `$matchOrder`.
 
 Naslednji primeri so enaki z vidika `equal()`, ne pa tudi za `same()`:
@@ -45,73 +45,73 @@ Vendar pazite, da se polje `[1, 2]` in `[2, 1]` nista enaki, saj se razlikuje le
 Uporabite lahko tudi tako imenovana [pričakovanja |#expectations] v `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Nasprotno od `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Če je `$actual` niz, mora vsebovati podredni niz `$needle`. Če je polje, mora vsebovati element `$needle` (primerja se strogo).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Nasprotje `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` mora biti polje in mora vsebovati ključ `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` mora biti polje in ne sme vsebovati ključa `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` mora biti `true`, torej `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` mora biti resničen, zato izpolnjuje pogoj `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` mora biti `false`, torej `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` mora biti falsey, zato izpolnjuje pogoj `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` mora biti `null`, torej `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` ne sme biti `null`, torej `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` ne sme biti številka. Za testiranje NAN uporabite samo `Assert::nan()`. Vrednost NAN je zelo specifična in trditve `Assert::same()` ali `Assert::equal()` se lahko obnašajo nepredvidljivo.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Število elementov v `$value` mora biti `$count`. Torej enako kot `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` mora biti določene vrste. Kot `$type` lahko uporabimo niz:
 - `array`
 - `list` - polje, indeksirano v naraščajočem vrstnem redu številskih ključev od nič
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - ime razreda ali predmeta neposredno, potem mora posredovati `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 Ob klicu `$callable` je treba zavreči izjemo primera `$class`. Če posredujemo `$message`, [se |#assert-match] mora sporočilo izjeme [ujemati |#assert-match]. In če posredujemo `$code`, mora biti koda izjeme enaka.
 
 Na primer, ta preskus ni uspešen, ker se sporočilo izjeme ne ujema:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Preveri, ali klic `$callable` ustvari pričakovane napake (tj. opozorila, obvestila itd.). Kot `$type` navedemo eno od konstant `E_...`, na primer `E_WARNING`. In če predamo `$message`, mora tudi sporočilo o napaki [ustrezati |#assert-match] vzorcu. For example:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Preveri, ali funkcija `$callable` ne vrže nobenega opozorila/opozorila/pomote ali izjeme PHP. Uporabna je za testiranje dela kode, v katerem ni nobene druge trditve.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` se mora ujemati z `$pattern`. Uporabimo lahko dve različici vzorcev: regularne izraze ali nadomestne znake.
 
 Če posredujemo regularni izraz kot `$pattern`, moramo za njegovo razmejitev uporabiti `~` or `#`. Drugi delilniki niso podprti. Na primer test, pri katerem mora `$var` vsebovati samo šestnajstiške številke:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Trditev je enaka kot [Assert::match( |#assert-match] ), vendar se vzorec naloži iz `$file`. Uporabna je za testiranje zelo dolgih nizov. Testna datoteka stoji berljivo.
 
 
diff --git a/tester/sl/guide.texy b/tester/sl/guide.texy
index a7d4c6ead5..cfd0219356 100644
--- a/tester/sl/guide.texy
+++ b/tester/sl/guide.texy
@@ -116,10 +116,10 @@ Izpis je lahko videti takole:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Podprte različice PHP .[#toc-supported-php-versions]
 
 | različica | združljiva s PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/sl/helpers.texy b/tester/sl/helpers.texy
index 87c3e3ef08..9ca0cf7705 100644
--- a/tester/sl/helpers.texy
+++ b/tester/sl/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` je razred, ki razširja `SimpleXMLElement` z metodami, ki olajšajo testiranje vsebine HTML ali XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# v $html je niz z dokumentom HTML, v $dom dobimo korenski element
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# ali preverite, ali element ustreza izbirniku (od različice 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Ustvari globalne funkcije `test()`, `setUp()` in `tearDown()`, v katere lahko razdelite teste.
+Ustvari globalne funkcije `test()`, `testException()`, `setUp()` in `tearDown()`, v katere lahko razdelite teste.
 
 ```php
 test('test description', function () {
diff --git a/tester/sl/running-tests.texy b/tester/sl/running-tests.texy
index 716d247f7c..61f88fe883 100644
--- a/tester/sl/running-tests.texy
+++ b/tester/sl/running-tests.texy
@@ -23,10 +23,10 @@ Izpis je lahko videti takole:
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Pregled možnosti ukazne vrstice dobimo tako, da zaženemo Tester brez parametro
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (npr. -o junit:output.xml)
+                                 Določite enega ali več izhodnih formatov z neobveznim imenom datoteke.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Pot do začasnega imenika. Privzeto s sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Določa, kateri `php.ini` se bo uporabljal pri izvajanju testov. Privzeto se ne
 Uporabi se sistemski `php.ini`. Tako so na platformi UNIX uporabljene tudi vse datoteke `/etc/php/{sapi}/conf.d/*.ini`. Oglejte si razdelek [Lastni php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Potek testiranja se zapiše v datoteko. Vsi neuspešni, preskočeni in tudi uspešni testi:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Nastavi vrednost konfiguracijske direktive PHP za teste. Parameter lahko uporabite večkrat.
@@ -127,13 +118,15 @@ Tester ustavi testiranje ob prvem neuspešnem testu.
 Testi se izvajajo v `<num>` vzporednih procesih. Privzeta vrednost je 8. Če želimo teste izvajati zaporedno, uporabimo vrednost 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Izhodna oblika. Privzeta je konzolna oblika.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Izhodni format. Privzeta je konzolna oblika. Določite lahko ime datoteke, v katero se bo zapisal izpis (npr. `-o junit:output.xml`). Možnost `-o` lahko večkrat ponovite, da ustvarite več formatov naenkrat.
 
 - `console`: enako kot privzeto, vendar se v tem primeru logotip ASCII ne izpiše.
+- `console-lines`: podobno kot v konzoli, vendar je rezultat vsakega testa naveden v ločeni vrstici z več informacijami
 - `tap`: [format TAP, |https://en.wikipedia.org/wiki/Test_Anything_Protocol] primeren za strojno obdelavo
 - `junit`: format JUnit XML, primeren tudi za strojno obdelavo
+- `log`: Izpis poteka testiranja. Vsi neuspešni, preskočeni in tudi uspešni testi
 - `none`: nič se ne izpiše
 
 
diff --git a/tester/tr/assertions.texy b/tester/tr/assertions.texy
index 41e50c6e0f..aa997c7081 100644
--- a/tester/tr/assertions.texy
+++ b/tester/tr/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` `$actual` ile aynı olmalıdır. PHP operatörü ile aynıdır `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
  `Assert::same()`'un tersidir, bu nedenle PHP operatörü `!==` ile aynıdır.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` `$actual` ile aynı olmalıdır. `Assert::same()` adresinden farklı olarak, nesne kimliği, dizilerdeki anahtar çiftleri => değer sırası ve marjinal olarak farklı ondalık sayılar göz ardı edilir; bunlar `$matchIdentity` ve `$matchOrder` adresleri ayarlanarak değiştirilebilir.
 
 Aşağıdaki durumlar `equal()` açısından aynıdır, ancak `same()` için aynı değildir:
@@ -45,73 +45,73 @@ Ancak, dikkat edin, dizi `[1, 2]` ve `[2, 1]` eşit değildir, çünkü anahtar
 Sözde [beklentileri |#expectations] `$expected` adresinde de kullanabilirsiniz.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Karşısında `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 `$actual` bir dizeyse, `$needle` alt dizesini içermelidir. Bir dizi ise, `$needle` öğesini içermelidir (kesinlikle karşılaştırılır).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Karşısında `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` bir dizi olmalı ve `$needle` anahtarını içermelidir.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` bir dizi olmalı ve `$needle` anahtarını içermemelidir.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` `true` , yani `$value === true` olmalıdır.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` doğru olmalıdır, bu nedenle `if ($value) ...` koşulunu karşılar.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` `false` , yani `$value === false` olmalıdır.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` falsey olmalıdır, bu nedenle `if (!$value) ...` koşulunu karşılar.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` `null` , yani `$value === null` olmalıdır.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` `null` olmamalıdır, bu yüzden `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` Bir Numara Değil olmalıdır. NAN testi için yalnızca `Assert::nan()` adresini kullanın. NAN değeri çok spesifiktir ve `Assert::same()` veya `Assert::equal()` iddiaları tahmin edilemeyecek şekilde davranabilir.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 `$value` adresindeki öğe sayısı `$count` olmalıdır. Yani `count($value) === $count` ile aynı.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` belirli bir tipte olmalıdır. `$type` olarak string kullanabiliriz:
 - `array`
 - `list` - sıfırdan itibaren sayısal anahtarların artan sırasına göre dizinlenmiş dizi
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - sınıf adını veya nesnesini doğrudan geçmelidir. `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 `$callable` çağrıldığında `$class` örneğinin bir istisnası fırlatılmalıdır. Eğer `$message` adresini geçersek, istisnanın mesajı [eşleşmelidir |#assert-match]. Ve eğer `$code` adresini geçersek, istisnanın kodu aynı olmalıdır.
 
 Örneğin, istisnanın mesajı eşleşmediği için bu test başarısız olur:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 `$callable` çağrısının beklenen hataları (yani uyarılar, bildirimler, vb.) oluşturup oluşturmadığını kontrol eder. `$type` olarak `E_...` sabitlerinden birini belirtiriz, örneğin `E_WARNING`. Ve eğer `$message` geçilirse, hata mesajı da kalıpla [eşleşmelidir |#assert-match]. Örneğin:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 `$callable` işlevinin herhangi bir PHP uyarısı/bildirimi/hatası veya istisnası atmadığını kontrol eder. Başka bir iddianın olmadığı bir kod parçasını test etmek için kullanışlıdır.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` `$pattern` ile eşleşmelidir. İki çeşit kalıp kullanabiliriz: düzenli ifadeler veya joker karakterler.
 
 Bir düzenli ifadeyi `$pattern` olarak geçirirsek, sınırlandırmak için `~` or `#` kullanmalıyız. Diğer sınırlayıcılar desteklenmez. Örneğin, `$var` adresinin yalnızca onaltılık basamaklar içermesi gereken test:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 [Assert::match() |#assert-match] ile aynıdır ancak kalıp `$file` adresinden yüklenir. Çok uzun dizeleri test etmek için kullanışlıdır. Test dosyası okunabilir duruyor.
 
 
diff --git a/tester/tr/guide.texy b/tester/tr/guide.texy
index 1dcee56145..402f2f9184 100644
--- a/tester/tr/guide.texy
+++ b/tester/tr/guide.texy
@@ -116,10 +116,10 @@ Tamamlanan her test için, çalıştırıcı ilerlemeyi göstermek için bir kar
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Desteklenen PHP sürümleri .[#toc-supported-php-versions]
 
 | sürüm | PHP ile uyumlu
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/tr/helpers.texy b/tester/tr/helpers.texy
index 7c53678321..dd4834f341 100644
--- a/tester/tr/helpers.texy
+++ b/tester/tr/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` HTML veya XML içeriğini test etmeyi kolaylaştıran yöntemlerle `SimpleXMLElement` adresini genişleten bir sınıftır.
 
 ```php
-# let's have an HTML document in $html that we load
+# in $html HTML belgesini içeren bir dizedir, $dom içinde kök öğeyi alırız
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# veya öğenin seçiciyle eşleştiğini doğrulayın (2.5.3 sürümünden itibaren)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Testleri bölebileceğiniz `test()`, `setUp()` ve `tearDown()` global fonksiyonlarını oluşturur.
+Testleri bölebileceğiniz `test()`, `testException()`, `setUp()` ve `tearDown()` global fonksiyonlarını oluşturur.
 
 ```php
 test('test açıklaması', function () {
diff --git a/tester/tr/running-tests.texy b/tester/tr/running-tests.texy
index 33eb45386c..38b67a826e 100644
--- a/tester/tr/running-tests.texy
+++ b/tester/tr/running-tests.texy
@@ -23,10 +23,10 @@ Daha sonra testleri yürütecektir. Tamamlanan her test için, koşucu ilerlemey
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ Tester'ı parametresiz veya `-h` seçeneği ile çalıştırarak komut satırı
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Usage:
     tester [options] [<test file> | <directory>]...
@@ -58,16 +58,16 @@ Options:
     -p <path>                    Specify PHP interpreter to run (default: php).
     -c <path>                    Look for php.ini file (or look in directory) <path>.
     -C                           Use system-wide php.ini.
-    -l | --log <path>            Write log to file <path>.
     -d <key=value>...            Define INI entry 'key' with value 'value'.
     -s                           Show information about skipped tests.
     --stop-on-fail               Stop execution upon the first failure.
     -j <num>                     Run <num> jobs in parallel (default: 8).
-    -o <console|tap|junit|none>  Specify output format.
+    -o <console|console-lines|tap|junit|log|none> (örneğin -o junit:output.xml)
+                                 İsteğe bağlı dosya adıyla birlikte bir veya daha fazla çıktı biçimi belirtin.
     -w | --watch <path>          Watch directory.
     -i | --info                  Show tests environment info and exit.
     --setup <path>               Script for runner setup.
-    --temp <path>                Path to temporary directory. Default: sys_get_temp_dir().
+    --temp <path>                Geçici dizine giden yol. Varsayılan değer sys_get_temp_dir().
     --colors [1|0]               Enable or disable colors.
     --coverage <path>            Generate code coverage report to file.
     --coverage-src <path>        Path to source code.
@@ -94,15 +94,6 @@ Testleri çalıştırırken hangi `php.ini` adresinin kullanılacağını belirt
 Sistem genelinde bir `php.ini` kullanılır. Yani UNIX platformunda, tüm `/etc/php/{sapi}/conf.d/*.ini` dosyaları da. [Kendi php.ini |#Own php.ini] bölümüne bakın.
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Test ilerlemesi dosyaya yazılır. Tüm başarısız, atlanmış ve ayrıca başarılı testler:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Sınamalar için PHP yapılandırma yönergesinin değerini ayarlar. Değiştirge birden çok kez kullanılabilir.
@@ -127,13 +118,15 @@ Test cihazı ilk başarısız testte testi durdurur.
 Testler bir `<num>` paralel ön işlemler. Varsayılan değer 8'dir. Testleri seri olarak çalıştırmak istiyorsak 1 değerini kullanırız.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Çıktı biçimi. Varsayılan biçim konsol biçimidir.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Çıktı biçimi. Varsayılan biçim konsol biçimidir. Çıktının içine yazılacağı dosyanın adını belirtebilirsiniz (örneğin, `-o junit:output.xml`). Aynı anda birden fazla format oluşturmak için `-o` seçeneği birden fazla kez tekrarlanabilir.
 
 - `console`: varsayılan ile aynı, ancak ASCII logosu bu durumda yazdırılmaz
+- `console-lines`: konsola benzer, ancak her testin sonucu daha fazla bilgi ile ayrı bir satırda listelenir
 - `tap`: Makine işlemesi için uygun [TAP formatı |https://en.wikipedia.org/wiki/Test_Anything_Protocol]
 - `junit`: JUnit XML formatı, makine işlemesi için de uygun
+- `log`: Test ilerlemesini çıktılar. Tüm başarısız, atlanmış ve ayrıca başarılı testler
 - `none`: hiçbir şey yazdırılmaz
 
 
diff --git a/tester/uk/assertions.texy b/tester/uk/assertions.texy
index 8d29bcdd6d..68d8122dba 100644
--- a/tester/uk/assertions.texy
+++ b/tester/uk/assertions.texy
@@ -15,18 +15,18 @@ use Tester\Assert;
 ```
 
 
-Assert::same($expected, $actual, string $description=null) .[method]
---------------------------------------------------------------------
+Assert::same($expected, $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------
 `$expected` має бути те саме, що й `$actual`. Це те саме, що й оператор PHP `===`.
 
 
-Assert::notSame($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
+Assert::notSame($expected, $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------
 Протилежний оператору `Assert::same()`, тому збігається з оператором PHP `!==`.
 
 
-Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
+Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
+-------------------------------------------------------------------------------------------------------------------------
 `$expected` має бути таким самим, як `$actual`. На відміну від `Assert::same()`, ідентичність об'єктів, порядок пар ключ => значення в масивах і незначно відмінні десяткові числа ігноруються, що можна змінити, задавши `$matchIdentity` і `$matchOrder`.
 
 Наступні випадки ідентичні з точки зору `equal()`, але не для `same()`:
@@ -45,73 +45,73 @@ Assert::equal(
 Ви також можете використовувати так звані [очікування |#Expectations] в `$expected`.
 
 
-Assert::notEqual($expected, $actual, string $description=null) .[method]
-------------------------------------------------------------------------
+Assert::notEqual($expected, $actual, ?string $description=null) .[method]
+-------------------------------------------------------------------------
 Протилежність `Assert::equal()`.
 
 
-Assert::contains($needle, string|array $actual, string $description=null) .[method]
------------------------------------------------------------------------------------
+Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
+------------------------------------------------------------------------------------
 Якщо `$actual` - рядок, то він повинен містити підрядок `$needle`. Якщо це масив, то він має містити елемент `$needle` (він порівнюється строго).
 
 
-Assert::notContains($needle, string|array $actual, string $description=null) .[method]
---------------------------------------------------------------------------------------
+Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
+---------------------------------------------------------------------------------------
 Протилежність `Assert::contains()`.
 
 
-Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
+Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+--------------------------------------------------------------------------------------------------------
 `$actual` має бути масивом і містити ключ `$needle`.
 
 
-Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
+Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
+-----------------------------------------------------------------------------------------------------------
 `$actual` має бути масивом і не повинен містити ключ `$needle`.
 
 
-Assert::true($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::true($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` має бути `true`, тому `$value === true`.
 
 
-Assert::truthy($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::truthy($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` має бути істинним, тому воно задовольняє умову `if ($value) ...`.
 
 
-Assert::false($value, string $description=null) .[method]
----------------------------------------------------------
+Assert::false($value, ?string $description=null) .[method]
+----------------------------------------------------------
 `$value` має бути `false`, тому `$value === false`.
 
 
-Assert::falsey($value, string $description=null) .[method]
-----------------------------------------------------------
+Assert::falsey($value, ?string $description=null) .[method]
+-----------------------------------------------------------
 `$value` має бути хибним, тому він задовольняє умову `if (!$value) ...`.
 
 
-Assert::null($value, string $description=null) .[method]
---------------------------------------------------------
+Assert::null($value, ?string $description=null) .[method]
+---------------------------------------------------------
 `$value` має бути `null`, тому `$value === null`.
 
 
-Assert::notNull($value, string $description=null) .[method]
------------------------------------------------------------
+Assert::notNull($value, ?string $description=null) .[method]
+------------------------------------------------------------
 `$value` не повинно бути `null`, тому `$value !== null`.
 
 
-Assert::nan($value, string $description=null) .[method]
--------------------------------------------------------
+Assert::nan($value, ?string $description=null) .[method]
+--------------------------------------------------------
 `$value` має бути Not a Number. Використовуйте тільки `Assert::nan()` для тестування NAN. Значення NAN дуже специфічне, і твердження `Assert::same()` або `Assert::equal()` можуть повести себе непередбачувано.
 
 
-Assert::count($count, Countable|array $value, string $description=null) .[method]
----------------------------------------------------------------------------------
+Assert::count($count, Countable|array $value, ?string $description=null) .[method]
+----------------------------------------------------------------------------------
 Кількість елементів у `$value` має дорівнювати `$count`. Тобто те саме, що й `count($value) === $count`.
 
 
-Assert::type(string|object $type, $value, string $description=null) .[method]
------------------------------------------------------------------------------
+Assert::type(string|object $type, $value, ?string $description=null) .[method]
+------------------------------------------------------------------------------
 `$value` має бути заданого типу. Як `$type` ми можемо використовувати рядок:
 - `array`
 - `list` - масив, індексований у порядку зростання числових ключів від нуля.
@@ -127,8 +127,8 @@ Assert::type(string|object $type, $value, string $description=null) .[method]
 - ім'я класу або об'єкта безпосередньо, то необхідно передати `$value instanceof $type`
 
 
-Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
+Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
+-------------------------------------------------------------------------------------------------
 При виклику `$callable` має бути викинуто виключення екземпляра `$class`. Якщо ми передаємо `$message`, то повідомлення виключення має [збігатися |#Assert-match]. А якщо ми передаємо `$code`, то код виключення має бути таким самим.
 
 Наприклад, цей тест не пройдено, тому що повідомлення виключення не збігається:
@@ -154,8 +154,8 @@ Assert::type(RuntimeException::class, $e->getPrevious());
 ```
 
 
-Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
----------------------------------------------------------------------------------------
+Assert::error(string $callable, int|string|array $type, ?string $message=null) .[method]
+----------------------------------------------------------------------------------------
 Перевіряє, що виклик `$callable` генерує очікувані помилки (тобто попередження, повідомлення тощо). Як `$type` ми вказуємо одну з констант `E_...`, наприклад `E_WARNING`. І якщо передаємо `$message`, то повідомлення про помилку також має [відповідати |#Assert-match] шаблону. Наприклад:
 
 ```php
@@ -187,8 +187,8 @@ Assert::noError(callable $callable) .[method]
 Перевіряє, що функція `$callable` не викидає жодних попереджень/зауважень/помилок або виключень PHP. Це корисно для перевірки частини коду, де немає інших тверджень.
 
 
-Assert::match(string $pattern, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
+Assert::match(string $pattern, $actual, ?string $description=null) .[method]
+----------------------------------------------------------------------------
 `$actual` повинен відповідати `$pattern`. Ми можемо використовувати два варіанти шаблонів: регулярні вирази або знаки підстановки.
 
 Якщо ми передаємо регулярний вираз як `$pattern`, ми повинні використовувати `~` or `#` для його поділу. Інші роздільники не підтримуються. Наприклад, тест, де `$var` повинен містити тільки шістнадцяткові цифри:
@@ -227,8 +227,8 @@ Assert::match('Error in file %a% on line %i%', $errorMessage);
 ```
 
 
-Assert::matchFile(string $file, $actual, string $description=null) .[method]
-----------------------------------------------------------------------------
+Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
+-----------------------------------------------------------------------------
 Твердження ідентичне [Assert::match() |#Assert-match], але шаблон завантажується з `$file`. Це корисно для тестування дуже довгих рядків. Тестовий файл стає читабельним.
 
 
diff --git a/tester/uk/guide.texy b/tester/uk/guide.texy
index ca06db82f4..9b52c9c76f 100644
--- a/tester/uk/guide.texy
+++ b/tester/uk/guide.texy
@@ -116,10 +116,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s................<span style="color: #FFF; background-color: #900">F</span>.........
 
@@ -160,7 +160,7 @@ Tester може генерувати звіти з оглядом того, як
 
 | Версія | сумісна з PHP
 |------------------|-------------------
-| Tester 2.5 | PHP 8.0 - 8.2
+| Tester 2.5       | PHP 8.0 – 8.3
 | Tester 2.4 | PHP 7.2 - 8.2
 | Tester 2.3 | PHP 7.1 - 8.0
 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3
diff --git a/tester/uk/helpers.texy b/tester/uk/helpers.texy
index 397dc430d4..36b74139bb 100644
--- a/tester/uk/helpers.texy
+++ b/tester/uk/helpers.texy
@@ -7,7 +7,7 @@ DomQuery .[#toc-domquery]
 `Tester\DomQuery` це клас, що розширює `SimpleXMLElement` з методами, які полегшують тестування вмісту HTML або XML.
 
 ```php
-# let's have an HTML document in $html that we load
+# в $html знаходиться рядок з HTML-документом, в $dom ми отримуємо кореневий елемент
 $dom = Tester\DomQuery::fromHtml($html);
 
 # we can test the presence of elements using CSS selectors
@@ -17,6 +17,9 @@ Assert::true($dom->has('input[type="submit"]'));
 
 # or select elements as array of DomQuery
 $elems = $dom->find('input[data-autocomplete]');
+
+# або перевірка відповідності елемента селектору (починаючи з версії 2.5.3)
+Assert::true($elems[0]->matches('[type="submit"]'));
 ```
 
 
@@ -119,7 +122,7 @@ Environment::setup() .[filter]
 
 Environment::setupFunctions() .[filter]{data-version:2.5}
 ---------------------------------------------------------
-Створює глобальні функції `test()`, `setUp()` і `tearDown()`, на які можна розбити тести.
+Створює глобальні функції `test()`, `testException()`, `setUp()` і `tearDown()`, на які можна розбити тести.
 
 ```php
 test('опис тесту', function () {
diff --git a/tester/uk/running-tests.texy b/tester/uk/running-tests.texy
index 51c1835d90..a3b07f972d 100644
--- a/tester/uk/running-tests.texy
+++ b/tester/uk/running-tests.texy
@@ -23,10 +23,10 @@ vendor/bin/tester .
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Note: No php.ini is used.
-PHP 7.4.8 (cli) | php -n | 8 threads
+PHP 8.3.2 (cli) | php -n | 8 threads
 
 ........s..........................
 
@@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads
 /--pre .[terminal]
  _____ ___  ___ _____ ___  ___
 |_   _/ __)( __/_   _/ __)| _ )
-  |_| \___ /___) |_| \___ |_|_\  v2.3.3
+  |_| \___ /___) |_| \___ |_|_\  v2.5.2
 
 Использование:
     tester [параметры] [<тестовый файл> | <каталог>]...
@@ -58,16 +58,16 @@ PHP 7.4.8 (cli) | php -n | 8 threads
     -p <путь>                    Укажите интерпретатор PHP для запуска (по умолчанию: php).
     -c <path>                    Искать php.ini файл (или искать в директории) <path>.
     -C                           Использовать общесистемный php.ini.
-    -l | --log <путь>            Запись журнала в файл <путь>.
     -d <ключ=значение>...        Определить INI-запись 'key' со значением 'value'.
     -s                           Показать информацию о пропущенных тестах.
     --stop-on-fail               Остановить выполнение при первом сбое.
     -j <num>                     Выполнять <num> заданий параллельно (по умолчанию: 8).
-    -o <console|tap|junit|none>  Указать формат вывода.
+    -o <console|console-lines|tap|junit|log|none> (наприклад, -o junit:output.xml)
+                                 Вкажіть один або декілька форматів виводу з необов'язковим ім'ям файлу.
     -w | --watch <путь>          Каталог просмотра.
     -i | --info                  Показать информацию об окружении тестов и выйти.
     --setup <путь>               Сценарий для настройки бегущей строки.
-    --temp <путь>                Путь к временному каталогу. По умолчанию: sys_get_temp_dir().
+    --temp <path>                Шлях до тимчасового каталогу. За замовчуванням визначається функцією sys_get_temp_dir().
     --colors [1|0]               Включить или отключить цвета.
     --coverage <путь>            Генерировать отчет о покрытии кода в файл.
     --coverage-src <путь>        Путь к исходному коду.
@@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests
 Використовується загальносистемний `php.ini`. Отже, на платформі UNIX всі файли `/etc/php/{sapi}/conf.d/*.ini` також. Див. розділ [Власний php.ini |#Own php.ini].
 
 
-''-l | --log <path>'' .[filter]
--------------------------------
-Прогрес тестування записується у файл. Всі невдалі, пропущені, а також успішні тести:
-
-/--pre .[terminal]
-tester --log /var/log/tests.log tests
-\--
-
-
 -d <key=value> .[filter]
 ------------------------
 Задає значення директиви конфігурації PHP для тестів. Параметр можна використовувати декілька разів.
@@ -127,13 +118,15 @@ tester -d max_execution_time=20
 Тести виконуються в `<num>` паралельними прецесіями. Значення за замовчуванням 8. Якщо ми хочемо запускати тести послідовно, ми використовуємо значення 1.
 
 
--o <console|tap|junit|none> .[filter]
--------------------------------------
-Формат виводу. За замовчуванням - формат консолі.
+-o <console|console-lines|tap|junit|log|none> .[filter]
+-------------------------------------------------------
+Формат виводу. За замовчуванням використовується формат консолі. Ви можете вказати назву файлу, до якого буде записано вивід (наприклад, `-o junit:output.xml`). Параметр `-o` можна повторити декілька разів, щоб згенерувати одразу декілька форматів.
 
 - `console`: те саме, що і за замовчуванням, але у цьому випадку не виводиться ASCII-логотип
+- `console-lines`: аналогічно консолі, але результат кожного тесту виводиться в окремому рядку з додатковою інформацією
 - `tap`: [формат TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol], придатний для машинної обробки
 - `junit`: формат JUnit XML, також придатний для машинної обробки
+- `log`: Прогрес тестування вихідних даних. Всі невдалі, пропущені та успішні тести
 - `none`: нічого не друкується
 
 
diff --git a/tracy/bg/guide.texy b/tracy/bg/guide.texy
index 4a74e8c5b3..aea8524809 100644
--- a/tracy/bg/guide.texy
+++ b/tracy/bg/guide.texy
@@ -79,9 +79,9 @@ Debugger::$showBar = false;
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com';
 
 | Tracy | съвместим с PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/bg/open-files-in-ide.texy b/tracy/bg/open-files-in-ide.texy
index 2dc107b45e..af0a54662c 100644
--- a/tracy/bg/open-files-in-ide.texy
+++ b/tracy/bg/open-files-in-ide.texy
@@ -41,6 +41,15 @@ var settings = {
 
 Това става, като се стартира скриптът `install.cmd`. ** Трябва да го стартирате като администратор.** Скриптът `open-editor.js` сега ще обслужва протокола `editor://`.
 
+За да отваряте връзки, генерирани на други сървъри, например производствен сървър или Docker, добавете съпоставяне на отдалечен към локален URL адрес към `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/bg/recipes.texy b/tracy/bg/recipes.texy
index 03187fdca1..e8c5959363 100644
--- a/tracy/bg/recipes.texy
+++ b/tracy/bg/recipes.texy
@@ -42,10 +42,35 @@ header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic';");
 ```
 
 
-AJAX и пренасочени заявки .[#toc-ajax-and-redirected-requests]
-==============================================================
+Отстраняване на грешки при заявките AJAX .[#toc-debugging-ajax-requests]
+========================================================================
 
-Трейси може да показва Debug bar и Bluescreens за AJAX заявки и пренасочвания. Tracy създава свои собствени сесии, съхранява данни в свои собствени временни файлове и използва бисквитка `tracy-session`.
+Tracy автоматично улавя заявките AJAX, направени с помощта на jQuery или родния API на `fetch`. Тези заявки се показват като допълнителни редове в лентата Tracy, което позволява лесно и удобно отстраняване на грешки в AJAX.
+
+Ако не искате да улавяте автоматично AJAX заявки, можете да деактивирате тази функция, като зададете JavaScript променливата:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+За ръчно следене на конкретни AJAX заявки добавете HTTP заглавието `X-Tracy-Ajax` със стойността, върната от `Tracy.getAjaxHeader()`. Ето пример за използването му с функцията `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Този подход позволява селективно отстраняване на грешки в AJAX заявките.
+
+
+Съхранение на данни .[#toc-data-storage]
+========================================
+
+Tracy може да показва панели Tracy bar и Bluescreens за AJAX заявки и пренасочвания. Tracy създава свои собствени сесии, съхранява данни в свои собствени временни файлове и използва бисквитка `tracy-session`.
 
 Tracy може също така да бъде конфигуриран да използва собствена PHP сесия, която се стартира преди Tracy да бъде включен:
 
diff --git a/tracy/cs/guide.texy b/tracy/cs/guide.texy
index a64e50a135..46c2df2e18 100644
--- a/tracy/cs/guide.texy
+++ b/tracy/cs/guide.texy
@@ -79,9 +79,9 @@ nebo při nezachycené výjimce:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Podporované verze PHP
 
 | Tracy     | kompatibilní s PHP
 |-----------|-------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 – 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 – 8.2
 | Tracy 2.8 | PHP 7.2 – 8.1
 | Tracy 2.6 – 2.7 | PHP 7.1 – 8.0
diff --git a/tracy/cs/open-files-in-ide.texy b/tracy/cs/open-files-in-ide.texy
index 2483f08ae5..0d7fa6a865 100644
--- a/tracy/cs/open-files-in-ide.texy
+++ b/tracy/cs/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Pozor, ponechávejte dvojitá lomítka v cestách.
 
 To uděláte spuštěním soubor `install.cmd`. **Je potřeba ho spustit jako Správce.** Skript `open-editor.js` bude nyní obsluhovat protokol `editor://`.
 
+Aby bylo možné otevírat odkazy vygenerované na jiných serverech, jako třeba na ostrém serveru nebo v Dockeru, doplňte do `open-editor.js` ještě mapování vzdálené URL na lokální:
+
+```js
+	mappings: {
+		// vzdálená cesta: lokální cesta
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux
 =====
@@ -119,8 +128,8 @@ Vytvoření souboru:
 
 - Ve Firefoxu může být potřeba protokol povolit [nastavením |http://kb.mozillazine.org/Register_protocol#Firefox_3.5_and_above] `network.protocol-handler.expose.editor` na `false` a `network.protocol-handler.expose-all` na `true` v about:config.
 - Pokud vám to hned nepůjde, nepanikařte a zkuste párkrát refreshnout stránku před klikem na onen odkaz. Rozjede se to!
-- Zde je [link|https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/] na opravu případné chyby:
- Input Error: There is no script engine for file extension ".js" Maybe you associated ".js" file to another app, not JScript engine.
+- Zde je [link|https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/]
+ na opravu případné chyby: `Input Error: There is no script engine for file extension ".js"`, `Maybe you associated ".js" file to another app, not JScript engine.` respektive `pro příponu .js není k dispozici žádný skriptovací stroj`.
 
 V Google Chrome od verze 77 již neuvidíte zatržítko „Tento typ odkazů vždy otevírat v přidružené aplikaci“, když je editor spuštěný prostřednictvím odkazu. Řešení pro Windows: vytvořte soubor `fix.reg`:
 
diff --git a/tracy/cs/recipes.texy b/tracy/cs/recipes.texy
index ccbe9f02b5..18b0dc37ec 100644
--- a/tracy/cs/recipes.texy
+++ b/tracy/cs/recipes.texy
@@ -42,10 +42,35 @@ Spuštění je přímočaré, pokud však máte na webové stránce pomalu nač
 ```
 
 
-AJAX a přesměrování
-===================
+Ladění AJAXový požadavků
+========================
 
-Tracy umí zobrazit Debug bar a Bluescreeny pro AJAXové požadavky a přesměrovaní. Tracy si vytváří vlastní session, data uchovává ve vlastních dočasných souborech a používá cookie `tracy-session`.
+Tracy automaticky zachycuje AJAXové požadavky vytvořené pomocí jQuery nebo nativního API `fetch`. Požadavky jsou v liště Tracy zobrazeny jako další řádky, což umožňuje snadné a pohodlné ladění AJAXu.
+
+Pokud nechcete AJAXové požadavky zachycovat automaticky, můžete tuto funkci zakázat nastavením JavaScriptové proměnné:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Pro ruční monitorování specifických AJAX požadavků přidejte HTTP hlavičku `X-Tracy-Ajax` s hodnotou, kterou vrátí `Tracy.getAjaxHeader()`. Zde je příklad použití s funkcí `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Tento přístup umožňuje selektivní ladění AJAX požadavků.
+
+
+Datové úložiště
+===============
+
+Tracy umí zobrazit panely v Tracy baru a Bluescreeny pro AJAXové požadavky a přesměrovaní. Tracy si vytváří vlastní session, data uchovává ve vlastních dočasných souborech a používá cookie `tracy-session`.
 
 Tracy lze nakonfigurovat také tak, aby používala nativní PHP session, kterou nastartujeme ještě před zapnutím Tracy:
 
diff --git a/tracy/de/guide.texy b/tracy/de/guide.texy
index 453e31a580..f163a6e00e 100644
--- a/tracy/de/guide.texy
+++ b/tracy/de/guide.texy
@@ -79,9 +79,9 @@ oder nicht gefangene Ausnahme:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Unterstützte PHP-Versionen .[#toc-supported-php-versions]
 
 | Tracy ist kompatibel mit PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/de/open-files-in-ide.texy b/tracy/de/open-files-in-ide.texy
index cb31a42091..0f30fb6c2d 100644
--- a/tracy/de/open-files-in-ide.texy
+++ b/tracy/de/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Seien Sie vorsichtig und behalten Sie die doppelten Schrägstriche in den Pfaden
 
 Dazu führen Sie `install.cmd` aus. **Sie müssen es als Administrator ausführen**. Das Skript `open-editor.js` bedient nun das Protokoll `editor://`.
 
+Um Links zu öffnen, die auf anderen Servern generiert wurden, z. B. auf einem Produktionsserver oder Docker, fügen Sie eine Remote-zu-Local-URL-Zuordnung zu `open-editor.js` hinzu:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/de/recipes.texy b/tracy/de/recipes.texy
index 497f2e82c6..49d3789728 100644
--- a/tracy/de/recipes.texy
+++ b/tracy/de/recipes.texy
@@ -42,10 +42,35 @@ Die Lösung ist, dass Sie `<?php Tracy\Debugger::renderLoader() ?>` in Ihre Vorl
 ```
 
 
-AJAX und umgeleitete Anfragen .[#toc-ajax-and-redirected-requests]
-==================================================================
+Fehlersuche bei AJAX-Anfragen .[#toc-debugging-ajax-requests]
+=============================================================
+
+Tracy erfasst automatisch AJAX-Anfragen, die mit jQuery oder der systemeigenen API `fetch` gestellt werden. Diese Anfragen werden als zusätzliche Zeilen in der Tracy-Leiste angezeigt, was ein einfaches und bequemes AJAX-Debugging ermöglicht.
+
+Wenn Sie nicht möchten, dass AJAX-Anfragen automatisch erfasst werden, können Sie diese Funktion durch Setzen der JavaScript-Variable deaktivieren:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Für die manuelle Überwachung bestimmter AJAX-Anfragen fügen Sie den HTTP-Header `X-Tracy-Ajax` mit dem von `Tracy.getAjaxHeader()` zurückgegebenen Wert hinzu. Hier ist ein Beispiel für die Verwendung mit der Funktion `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Dieser Ansatz ermöglicht ein selektives Debugging von AJAX-Anfragen.
+
+
+Datenspeicherung .[#toc-data-storage]
+=====================================
 
-Tracy kann Debug-Balken und Bluescreens für AJAX-Anfragen und Redirects anzeigen. Tracy erstellt seine eigenen Sitzungen, speichert Daten in seinen eigenen temporären Dateien und verwendet ein `tracy-session` Cookie.
+Tracy kann Tracy-Leisten und Bluescreens für AJAX-Anfragen und Weiterleitungen anzeigen. Tracy erstellt seine eigenen Sitzungen, speichert Daten in seinen eigenen temporären Dateien und verwendet ein `tracy-session` Cookie.
 
 Tracy kann auch so konfiguriert werden, dass es eine native PHP-Sitzung verwendet, die gestartet wird, bevor Tracy eingeschaltet wird:
 
diff --git a/tracy/el/guide.texy b/tracy/el/guide.texy
index f942fa71e8..62d8d3ed9d 100644
--- a/tracy/el/guide.texy
+++ b/tracy/el/guide.texy
@@ -79,9 +79,9 @@ or uncaught exception:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com';
 
 | Tracy | συμβατή με PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/el/open-files-in-ide.texy b/tracy/el/open-files-in-ide.texy
index 13621cdf1c..e8b94df8e0 100644
--- a/tracy/el/open-files-in-ide.texy
+++ b/tracy/el/open-files-in-ide.texy
@@ -41,6 +41,15 @@ var settings = {
 
 Αυτό γίνεται εκτελώντας το `install.cmd`. **Πρέπει να το εκτελέσετε ως διαχειριστής.** Το σενάριο `open-editor.js` θα εξυπηρετεί τώρα το πρωτόκολλο `editor://`.
 
+Για να ανοίξετε συνδέσμους που δημιουργούνται σε άλλους διακομιστές, όπως ένας διακομιστής παραγωγής ή ο Docker, προσθέστε μια αντιστοίχιση απομακρυσμένης σε τοπική διεύθυνση URL στο `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/el/recipes.texy b/tracy/el/recipes.texy
index d5381ba77d..ba1e2fefe8 100644
--- a/tracy/el/recipes.texy
+++ b/tracy/el/recipes.texy
@@ -42,10 +42,35 @@ header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic';");
 ```
 
 
-AJAX και ανακατευθυνόμενες αιτήσεις .[#toc-ajax-and-redirected-requests]
-========================================================================
+Αποσφαλμάτωση αιτημάτων AJAX .[#toc-debugging-ajax-requests]
+============================================================
 
-Το Tracy μπορεί να εμφανίσει τη γραμμή εντοπισμού σφαλμάτων και τα Bluescreens για αιτήσεις AJAX και ανακατευθύνσεις. Το Tracy δημιουργεί τις δικές του συνεδρίες, αποθηκεύει δεδομένα στα δικά του προσωρινά αρχεία και χρησιμοποιεί ένα cookie `tracy-session`.
+Το Tracy καταγράφει αυτόματα τα αιτήματα AJAX που πραγματοποιούνται με τη χρήση του jQuery ή του εγγενούς API `fetch`. Αυτές οι αιτήσεις εμφανίζονται ως πρόσθετες γραμμές στη γραμμή Tracy, επιτρέποντας την εύκολη και βολική αποσφαλμάτωση AJAX.
+
+Εάν δεν θέλετε να καταγράφετε αυτόματα τις αιτήσεις AJAX, μπορείτε να απενεργοποιήσετε αυτή τη λειτουργία ρυθμίζοντας τη μεταβλητή JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Για χειροκίνητη παρακολούθηση συγκεκριμένων αιτήσεων AJAX, προσθέστε την επικεφαλίδα HTTP `X-Tracy-Ajax` με την τιμή που επιστρέφει η `Tracy.getAjaxHeader()`. Ακολουθεί ένα παράδειγμα χρήσης της με τη συνάρτηση `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Αυτή η προσέγγιση επιτρέπει την επιλεκτική αποσφαλμάτωση των αιτήσεων AJAX.
+
+
+Αποθήκευση δεδομένων .[#toc-data-storage]
+=========================================
+
+Το Tracy μπορεί να εμφανίζει πίνακες Tracy bar και Bluescreens για αιτήματα AJAX και ανακατευθύνσεις. Το Tracy δημιουργεί τις δικές του συνεδρίες, αποθηκεύει δεδομένα στα δικά του προσωρινά αρχεία και χρησιμοποιεί ένα cookie `tracy-session`.
 
 Το Tracy μπορεί επίσης να ρυθμιστεί ώστε να χρησιμοποιεί μια εγγενή συνεδρία PHP, η οποία ξεκινά πριν από την ενεργοποίηση του Tracy:
 
diff --git a/tracy/en/guide.texy b/tracy/en/guide.texy
index 94b755fbcf..e0e09adf6d 100644
--- a/tracy/en/guide.texy
+++ b/tracy/en/guide.texy
@@ -79,9 +79,9 @@ or uncaught exception:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Supported PHP Versions
 
 | Tracy     | compatible with PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 – 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 – 8.2
 | Tracy 2.8 | PHP 7.2 – 8.1
 | Tracy 2.6 – 2.7 | PHP 7.1 – 8.0
diff --git a/tracy/en/open-files-in-ide.texy b/tracy/en/open-files-in-ide.texy
index 0c55974726..6a9d269a10 100644
--- a/tracy/en/open-files-in-ide.texy
+++ b/tracy/en/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Be careful and keep the double slashes in the paths.
 
 This is done by running `install.cmd`. **You need to run it as an Administrator.** The `open-editor.js` script will now serve the `editor://` protocol.
 
+In order to open links generated on other servers, such as a production server or Docker, add a remote to local URL mapping to `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux
 =====
@@ -119,8 +128,8 @@ Troubleshooting
 
 - In Firefox you may need to [allow |http://kb.mozillazine.org/Register_protocol#Firefox_3.5_and_above] custom protocol execution in about:config by setting `network.protocol-handler.expose.editor` to `false` and `network.protocol-handler.expose-all` to `true`. It should be allowed by default, however.
 - If it's not all working immediately, don't panic. Try to refresh the page, restart browser or computer. That should help.
-- See [here|https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/] to fix:
- Input Error: There is no script engine for file extension ".js" Maybe you associated ".js" file to another app, not JScript engine.
+- Here is the [link |https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/]
+ to correct any errors: `Input Error: There is no script engine for file extension ".js"` or `Maybe you associated ".js" file to another app, not JScript engine.`
 
 Starting from Google Chrome version 77 you will no longer see the checkbox “Always open these types of links in the associated app” when editor is opened through a link. Workaround for Windows: create file `fix.reg`:
 
diff --git a/tracy/en/recipes.texy b/tracy/en/recipes.texy
index 158fd0a39b..b293e530a6 100644
--- a/tracy/en/recipes.texy
+++ b/tracy/en/recipes.texy
@@ -42,10 +42,35 @@ The solution is to place `<?php Tracy\Debugger::renderLoader() ?>` into your tem
 ```
 
 
-AJAX and Redirected Requests
-============================
+Debugging AJAX Requests
+=======================
+
+Tracy automatically captures AJAX requests made using jQuery or the native `fetch` API. These requests are displayed as additional rows in the Tracy bar, enabling easy and convenient AJAX debugging.
+
+If you do not want to capture AJAX requests automatically, you can disable this feature by setting the JavaScript variable:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+For manual monitoring of specific AJAX requests, add the HTTP header `X-Tracy-Ajax` with the value returned by `Tracy.getAjaxHeader()`. Here is an example of using it with the `fetch` function:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+This approach allows for selective debugging of AJAX requests.
+
+
+Data Storage
+============
 
-Tracy can display Debug bar and Bluescreens for AJAX requests and redirects. Tracy creates its own sessions, stores data in its own temporary files, and uses a `tracy-session` cookie.
+Tracy can display Tracy bar panels and Bluescreens for AJAX requests and redirects. Tracy creates its own sessions, stores data in its own temporary files, and uses a `tracy-session` cookie.
 
 Tracy can also be configured to use a native PHP session, which is started before Tracy is turned on:
 
diff --git a/tracy/es/guide.texy b/tracy/es/guide.texy
index 3538ea6275..26aec10192 100644
--- a/tracy/es/guide.texy
+++ b/tracy/es/guide.texy
@@ -79,9 +79,9 @@ o excepción no capturada:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Versiones de PHP soportadas .[#toc-supported-php-versions]
 
 | Tracy | compatible con PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 – 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 – 8.2
 | Tracy 2.8 | PHP 7.2 – 8.1
 | Tracy 2.6 – 2.7 | PHP 7.1 – 8.0
diff --git a/tracy/es/open-files-in-ide.texy b/tracy/es/open-files-in-ide.texy
index 787ff8a5db..506ea462d6 100644
--- a/tracy/es/open-files-in-ide.texy
+++ b/tracy/es/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Ten cuidado y mantén las barras dobles en las rutas.
 
 Esto se hace ejecutando `install.cmd`. **Necesitas ejecutarlo como Administrador. El script `open-editor.js` ahora servirá al protocolo `editor://`.
 
+Para abrir enlaces generados en otros servidores, como un servidor de producción o Docker, añada una asignación de URL remota a local a `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/es/recipes.texy b/tracy/es/recipes.texy
index c78bdad3a7..e43feb16aa 100644
--- a/tracy/es/recipes.texy
+++ b/tracy/es/recipes.texy
@@ -42,10 +42,35 @@ La solución es colocar `<?php Tracy\Debugger::renderLoader() ?>` en tu plantill
 ```
 
 
-AJAX y peticiones redirigidas .[#toc-ajax-and-redirected-requests]
-==================================================================
+Depuración de peticiones AJAX .[#toc-debugging-ajax-requests]
+=============================================================
 
-Tracy puede mostrar Debug bar y Bluescreens para peticiones AJAX y redirecciones. Tracy crea sus propias sesiones, almacena datos en sus propios archivos temporales y utiliza una cookie `tracy-session`.
+Tracy captura automáticamente las peticiones AJAX realizadas mediante jQuery o la API nativa `fetch`. Estas peticiones se muestran como filas adicionales en la barra de Tracy, permitiendo una depuración AJAX fácil y cómoda.
+
+Si no desea capturar automáticamente las solicitudes AJAX, puede desactivar esta función configurando la variable JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Para la monitorización manual de peticiones AJAX específicas, añada la cabecera HTTP `X-Tracy-Ajax` con el valor devuelto por `Tracy.getAjaxHeader()`. Aquí tiene un ejemplo de uso con la función `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Este enfoque permite la depuración selectiva de peticiones AJAX.
+
+
+Almacenamiento de datos .[#toc-data-storage]
+============================================
+
+Tracy puede mostrar paneles de barras Tracy y Bluescreens para peticiones AJAX y redirecciones. Tracy crea sus propias sesiones, almacena datos en sus propios archivos temporales y utiliza una cookie `tracy-session`.
 
 Tracy también puede configurarse para usar una sesión nativa PHP, que se inicia antes de que Tracy se active:
 
diff --git a/tracy/fr/guide.texy b/tracy/fr/guide.texy
index de2abc975f..c601e75f62 100644
--- a/tracy/fr/guide.texy
+++ b/tracy/fr/guide.texy
@@ -79,9 +79,9 @@ ou exception non attrapée :
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Versions de PHP prises en charge .[#toc-supported-php-versions]
 
 | Tracy | compatible avec PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/fr/open-files-in-ide.texy b/tracy/fr/open-files-in-ide.texy
index 4adeae2223..e6f5f73384 100644
--- a/tracy/fr/open-files-in-ide.texy
+++ b/tracy/fr/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Faites attention et gardez les doubles slashs dans les chemins.
 
 Ceci est fait en exécutant `install.cmd`. **Vous devez l'exécuter en tant qu'administrateur. Le script `open-editor.js` servira désormais le protocole `editor://`.
 
+Afin d'ouvrir les liens générés sur d'autres serveurs, tels qu'un serveur de production ou Docker, ajoutez un mappage d'URL distant à local à `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/fr/recipes.texy b/tracy/fr/recipes.texy
index 8bef651219..e3eae7ee12 100644
--- a/tracy/fr/recipes.texy
+++ b/tracy/fr/recipes.texy
@@ -42,10 +42,35 @@ La solution consiste à placer `<?php Tracy\Debugger::renderLoader() ?>` dans vo
 ```
 
 
-AJAX et requêtes redirigées .[#toc-ajax-and-redirected-requests]
-================================================================
+Débogage des requêtes AJAX .[#toc-debugging-ajax-requests]
+==========================================================
+
+Tracy capture automatiquement les requêtes AJAX effectuées à l'aide de jQuery ou de l'API native `fetch`. Ces requêtes sont affichées sous forme de lignes supplémentaires dans la barre de Tracy, ce qui permet un débogage AJAX facile et pratique.
+
+Si vous ne souhaitez pas capturer automatiquement les requêtes AJAX, vous pouvez désactiver cette fonctionnalité en définissant la variable JavaScript :
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Pour surveiller manuellement des requêtes AJAX spécifiques, ajoutez l'en-tête HTTP `X-Tracy-Ajax` avec la valeur renvoyée par `Tracy.getAjaxHeader()`. Voici un exemple d'utilisation avec la fonction `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Cette approche permet un débogage sélectif des requêtes AJAX.
+
+
+Stockage des données .[#toc-data-storage]
+=========================================
 
-Tracy peut afficher la barre de débogage et les écrans bleus pour les demandes AJAX et les redirections. Tracy crée ses propres sessions, stocke les données dans ses propres fichiers temporaires et utilise un cookie `tracy-session`.
+Tracy peut afficher des panneaux de barre Tracy et des écrans bleus pour les requêtes AJAX et les redirections. Tracy crée ses propres sessions, stocke les données dans ses propres fichiers temporaires et utilise un cookie `tracy-session`.
 
 Tracy peut également être configuré pour utiliser une session PHP native, qui est lancée avant que Tracy ne soit activé :
 
diff --git a/tracy/hu/guide.texy b/tracy/hu/guide.texy
index 31dec6942e..aed573360f 100644
--- a/tracy/hu/guide.texy
+++ b/tracy/hu/guide.texy
@@ -79,9 +79,9 @@ vagy el nem fogott kivétel:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Támogatott PHP-verziók .[#toc-supported-php-versions]
 
 | Tracy | kompatibilis a PHP-vel
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/hu/open-files-in-ide.texy b/tracy/hu/open-files-in-ide.texy
index 5500772969..551428802a 100644
--- a/tracy/hu/open-files-in-ide.texy
+++ b/tracy/hu/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Legyen óvatos, és tartsa meg a kettős kötőjeleket az elérési utakban.
 
 Ez a `install.cmd` futtatásával történik. **Adminisztrátorként kell futtatnia.** A `open-editor.js` szkript mostantól a `editor://` protokollt fogja kiszolgálni.
 
+Ahhoz, hogy más szervereken, például egy termelési szerveren vagy Dockerben létrehozott hivatkozásokat nyisson meg, adjon hozzá egy távoli helyi URL-t leképezőt a `open-editor.js` címhez:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/hu/recipes.texy b/tracy/hu/recipes.texy
index da394e86cb..36546716f5 100644
--- a/tracy/hu/recipes.texy
+++ b/tracy/hu/recipes.texy
@@ -42,10 +42,35 @@ A megoldás az, hogy a `<?php Tracy\Debugger::renderLoader() ?>` a sablonba a sz
 ```
 
 
-AJAX és átirányított kérések .[#toc-ajax-and-redirected-requests]
-=================================================================
+AJAX-kérelmek hibakeresése .[#toc-debugging-ajax-requests]
+==========================================================
 
-A Tracy megjelenítheti a hibakereső sávot és a Bluescreent az AJAX-kérések és átirányítások esetében. A Tracy saját munkameneteket hoz létre, az adatokat saját ideiglenes fájlokban tárolja, és a `tracy-session` cookie-t használja.
+A Tracy automatikusan rögzíti a jQuery vagy a natív `fetch` API segítségével végrehajtott AJAX-kéréseket. Ezek a kérések további sorokként jelennek meg a Tracy sávban, lehetővé téve az egyszerű és kényelmes AJAX hibakeresést.
+
+Ha nem szeretné automatikusan rögzíteni az AJAX-kéréseket, akkor a JavaScript változó beállításával kikapcsolhatja ezt a funkciót:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+A konkrét AJAX-kérések kézi megfigyeléséhez adja hozzá a `X-Tracy-Ajax` HTTP-fejlécet a `Tracy.getAjaxHeader()` által visszaadott értékkel. Íme egy példa a `fetch` függvénnyel való használatára:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Ez a megközelítés lehetővé teszi az AJAX-kérések szelektív hibakeresését.
+
+
+Adattárolás .[#toc-data-storage]
+================================
+
+A Tracy képes megjeleníteni a Tracy bárpaneleket és a Bluescreeneket az AJAX-kérésekhez és átirányításokhoz. A Tracy saját munkameneteket hoz létre, az adatokat saját ideiglenes fájljaiban tárolja, és a `tracy-session` cookie-t használja.
 
 A Tracy úgy is beállítható, hogy natív PHP munkamenetet használjon, amely a Tracy bekapcsolása előtt indul el:
 
diff --git a/tracy/it/guide.texy b/tracy/it/guide.texy
index 4657d2e8d7..7f0953121f 100644
--- a/tracy/it/guide.texy
+++ b/tracy/it/guide.texy
@@ -79,9 +79,9 @@ o eccezione non catturata:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Versioni PHP supportate .[#toc-supported-php-versions]
 
 | Tracy | compatibile con PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/it/open-files-in-ide.texy b/tracy/it/open-files-in-ide.texy
index 4250065585..4d2c2c77ae 100644
--- a/tracy/it/open-files-in-ide.texy
+++ b/tracy/it/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Fate attenzione a mantenere le doppie barre nei percorsi.
 
 Questo si fa eseguendo `install.cmd`. **Lo script `open-editor.js` servirà ora il protocollo `editor://`.
 
+Per aprire i link generati su altri server, come un server di produzione o Docker, aggiungere una mappatura dell'URL da remoto a locale a `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/it/recipes.texy b/tracy/it/recipes.texy
index a0c3ddee66..0a7236e249 100644
--- a/tracy/it/recipes.texy
+++ b/tracy/it/recipes.texy
@@ -42,10 +42,35 @@ La soluzione è inserire `<?php Tracy\Debugger::renderLoader() ?>` nel template
 ```
 
 
-AJAX e richieste reindirizzate .[#toc-ajax-and-redirected-requests]
-===================================================================
+Debug delle richieste AJAX .[#toc-debugging-ajax-requests]
+==========================================================
+
+Tracy cattura automaticamente le richieste AJAX effettuate con jQuery o con l'API nativa `fetch`. Queste richieste vengono visualizzate come righe aggiuntive nella barra di Tracy, consentendo un debug AJAX facile e conveniente.
+
+Se non si desidera catturare automaticamente le richieste AJAX, è possibile disabilitare questa funzione impostando la variabile JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Per il monitoraggio manuale di specifiche richieste AJAX, aggiungete l'intestazione HTTP `X-Tracy-Ajax` con il valore restituito da `Tracy.getAjaxHeader()`. Ecco un esempio di utilizzo con la funzione `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Questo approccio consente un debug selettivo delle richieste AJAX.
+
+
+Memorizzazione dei dati .[#toc-data-storage]
+============================================
 
-Tracy può visualizzare la barra di Debug e le Bluescreen per le richieste AJAX e di reindirizzamento. Tracy crea le proprie sessioni, memorizza i dati nei propri file temporanei e utilizza un cookie `tracy-session`.
+Tracy può visualizzare pannelli a barre e Bluescreen per le richieste AJAX e i reindirizzamenti. Tracy crea le proprie sessioni, memorizza i dati nei propri file temporanei e utilizza il cookie `tracy-session`.
 
 Tracy può anche essere configurato per utilizzare una sessione PHP nativa, che viene avviata prima dell'attivazione di Tracy:
 
diff --git a/tracy/pl/guide.texy b/tracy/pl/guide.texy
index b59b619280..4d59d1db60 100644
--- a/tracy/pl/guide.texy
+++ b/tracy/pl/guide.texy
@@ -79,9 +79,9 @@ lub gdy wyjątek nie zostanie złapany:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Obsługiwane wersje PHP .[#toc-supported-php-versions]
 
 | Tracy | kompatybilny z PHP
 |-----------|-------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/pl/open-files-in-ide.texy b/tracy/pl/open-files-in-ide.texy
index c53061cae1..238b907b86 100644
--- a/tracy/pl/open-files-in-ide.texy
+++ b/tracy/pl/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Uważaj, aby zostawić podwójne ukośniki w ścieżkach.
 
 Robisz to uruchamiając plik `install.cmd`. **Musisz uruchomić go jako Administrator.** Skrypt `open-editor.js` będzie teraz obsługiwał protokół `editor://`.
 
+Aby otworzyć linki wygenerowane na innych serwerach, takich jak serwer produkcyjny lub Docker, należy dodać mapowanie zdalnego adresu URL na lokalny do `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/pl/recipes.texy b/tracy/pl/recipes.texy
index 23c6f24718..60aa9f3f62 100644
--- a/tracy/pl/recipes.texy
+++ b/tracy/pl/recipes.texy
@@ -42,10 +42,35 @@ Rozwiązaniem jest umieszczenie `<?php Tracy\Debugger::renderLoader() ?>` w swoi
 ```
 
 
-AJAX i przekierowane żądania .[#toc-ajax-and-redirected-requests]
-=================================================================
+Debugowanie żądań AJAX .[#toc-debugging-ajax-requests]
+======================================================
 
-Tracy może wyświetlać pasek Debug i Bluescreens dla żądań AJAX i przekierowań. Tracy tworzy własne sesje, przechowuje dane we własnych plikach tymczasowych i używa pliku cookie `tracy-session`.
+Tracy automatycznie przechwytuje żądania AJAX wykonane przy użyciu jQuery lub natywnego interfejsu API `fetch`. Żądania te są wyświetlane jako dodatkowe wiersze na pasku Tracy, umożliwiając łatwe i wygodne debugowanie AJAX.
+
+Jeśli nie chcesz automatycznie przechwytywać żądań AJAX, możesz wyłączyć tę funkcję, ustawiając zmienną JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+W celu ręcznego monitorowania określonych żądań AJAX, dodaj nagłówek HTTP `X-Tracy-Ajax` z wartością zwracaną przez `Tracy.getAjaxHeader()`. Oto przykład użycia go z funkcją `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Takie podejście pozwala na selektywne debugowanie żądań AJAX.
+
+
+Przechowywanie danych .[#toc-data-storage]
+==========================================
+
+Tracy może wyświetlać panele paska Tracy i ekrany Bluescreens dla żądań AJAX i przekierowań. Tracy tworzy własne sesje, przechowuje dane we własnych plikach tymczasowych i używa pliku cookie `tracy-session`.
 
 Tracy może być również skonfigurowany do korzystania z natywnej sesji PHP, która jest uruchamiana przed włączeniem Tracy:
 
diff --git a/tracy/pt/guide.texy b/tracy/pt/guide.texy
index 5350ab840e..5e54d1f839 100644
--- a/tracy/pt/guide.texy
+++ b/tracy/pt/guide.texy
@@ -79,9 +79,9 @@ ou exceção não cautelosa:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Versões PHP suportadas .[#toc-supported-php-versions]
 
 | Tracy | compatível com PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/pt/open-files-in-ide.texy b/tracy/pt/open-files-in-ide.texy
index ad4fa053af..1e2a6b8f91 100644
--- a/tracy/pt/open-files-in-ide.texy
+++ b/tracy/pt/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Tenha cuidado e mantenha os cortes duplos nos caminhos.
 
 Isto é feito através da `install.cmd`. ** Você precisa executá-lo como Administrador.** O script `open-editor.js` servirá agora ao protocolo `editor://`.
 
+Para abrir links gerados em outros servidores, como um servidor de produção ou o Docker, adicione um mapeamento de URL remoto para local em `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/pt/recipes.texy b/tracy/pt/recipes.texy
index 80afa1234c..d1e09b6f9a 100644
--- a/tracy/pt/recipes.texy
+++ b/tracy/pt/recipes.texy
@@ -42,10 +42,35 @@ A solução é colocar `<?php Tracy\Debugger::renderLoader() ?>` em seu modelo a
 ```
 
 
-AJAX e Pedidos Redirecionados .[#toc-ajax-and-redirected-requests]
-==================================================================
+Depuração de solicitações AJAX .[#toc-debugging-ajax-requests]
+==============================================================
 
-Tracy pode exibir a barra Debug e Bluescreens para pedidos e redirecionamentos AJAX. Tracy cria suas próprias sessões, armazena dados em seus próprios arquivos temporários, e utiliza um cookie `tracy-session`.
+O Tracy captura automaticamente as solicitações AJAX feitas com jQuery ou com a API nativa `fetch`. Essas solicitações são exibidas como linhas adicionais na barra do Tracy, permitindo uma depuração AJAX fácil e conveniente.
+
+Se não quiser capturar automaticamente as solicitações AJAX, você poderá desativar esse recurso definindo a variável JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Para o monitoramento manual de solicitações AJAX específicas, adicione o cabeçalho HTTP `X-Tracy-Ajax` com o valor retornado por `Tracy.getAjaxHeader()`. Aqui está um exemplo de uso com a função `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Essa abordagem permite a depuração seletiva de solicitações AJAX.
+
+
+Armazenamento de dados .[#toc-data-storage]
+===========================================
+
+O Tracy pode exibir painéis de barras Tracy e Bluescreens para solicitações e redirecionamentos AJAX. O Tracy cria suas próprias sessões, armazena dados em seus próprios arquivos temporários e usa um cookie `tracy-session`.
 
 Tracy também pode ser configurado para usar uma sessão PHP nativa, que é iniciada antes de Tracy ser ligado:
 
diff --git a/tracy/ro/guide.texy b/tracy/ro/guide.texy
index d289faf636..9e70b28ccf 100644
--- a/tracy/ro/guide.texy
+++ b/tracy/ro/guide.texy
@@ -79,9 +79,9 @@ sau o excepție neînregistrată:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Versiuni PHP acceptate .[#toc-supported-php-versions]
 
 | Tracy | compatibil cu PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/ro/open-files-in-ide.texy b/tracy/ro/open-files-in-ide.texy
index b59ff680af..b4613e5e07 100644
--- a/tracy/ro/open-files-in-ide.texy
+++ b/tracy/ro/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Fiți atenți și păstrați barierele duble în căile de acces.
 
 Acest lucru se face prin rularea `install.cmd`. **Trebuie să îl rulați ca administrator.** Scriptul `open-editor.js` va servi acum protocolul `editor://`.
 
+Pentru a deschide linkuri generate pe alte servere, cum ar fi un server de producție sau Docker, adăugați o corespondență URL de la distanță la local la `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/ro/recipes.texy b/tracy/ro/recipes.texy
index 0cd95f51c4..76ac87403e 100644
--- a/tracy/ro/recipes.texy
+++ b/tracy/ro/recipes.texy
@@ -42,10 +42,35 @@ Soluția este să plasați `<?php Tracy\Debugger::renderLoader() ?>` în șablon
 ```
 
 
-AJAX și cereri redirecționate .[#toc-ajax-and-redirected-requests]
-==================================================================
+Depanarea cererilor AJAX .[#toc-debugging-ajax-requests]
+========================================================
 
-Tracy poate afișa Debug bar și Bluescreens pentru cererile AJAX și redirecționări. Tracy își creează propriile sesiuni, stochează datele în propriile fișiere temporare și utilizează un cookie `tracy-session`.
+Tracy captează automat solicitările AJAX efectuate cu ajutorul jQuery sau al API-ului nativ `fetch`. Aceste cereri sunt afișate ca rânduri suplimentare în bara Tracy, permițând o depanare AJAX ușoară și convenabilă.
+
+Dacă nu doriți să capturați automat solicitările AJAX, puteți dezactiva această funcție prin setarea variabilei JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Pentru monitorizarea manuală a unor cereri AJAX specifice, adăugați antetul HTTP `X-Tracy-Ajax` cu valoarea returnată de `Tracy.getAjaxHeader()`. Iată un exemplu de utilizare a acestuia cu funcția `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Această abordare permite depanarea selectivă a cererilor AJAX.
+
+
+Stocarea datelor .[#toc-data-storage]
+=====================================
+
+Tracy poate afișa panouri de bare Tracy și Bluescreens pentru cereri AJAX și redirecționări. Tracy își creează propriile sesiuni, stochează datele în propriile fișiere temporare și utilizează un cookie `tracy-session`.
 
 Tracy poate fi configurat, de asemenea, să utilizeze o sesiune PHP nativă, care este inițiată înainte ca Tracy să fie pornit:
 
diff --git a/tracy/ru/guide.texy b/tracy/ru/guide.texy
index 93f029345a..4e8a61f44c 100644
--- a/tracy/ru/guide.texy
+++ b/tracy/ru/guide.texy
@@ -79,9 +79,9 @@ or uncaught exception:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com';
 
 | Tracy | совместимые с PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Трейси 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/ru/open-files-in-ide.texy b/tracy/ru/open-files-in-ide.texy
index deb1328d5a..e4579a7dbf 100644
--- a/tracy/ru/open-files-in-ide.texy
+++ b/tracy/ru/open-files-in-ide.texy
@@ -41,6 +41,15 @@ var settings = {
 
 Это делается путем запуска скрипта `install.cmd`. **Вы должны запустить его от имени администратора.** Скрипт `open-editor.js` теперь будет обслуживать протокол `editor://`.
 
+Для того чтобы открывать ссылки, созданные на других серверах, например, на рабочем сервере или в Docker, добавьте сопоставление удаленных и локальных URL-адресов на `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/ru/recipes.texy b/tracy/ru/recipes.texy
index 4131f8fb8a..76d7819596 100644
--- a/tracy/ru/recipes.texy
+++ b/tracy/ru/recipes.texy
@@ -42,10 +42,35 @@ header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic';");
 ```
 
 
-AJAX и перенаправленные запросы .[#toc-ajax-and-redirected-requests]
-====================================================================
+Отладка AJAX-запросов .[#toc-debugging-ajax-requests]
+=====================================================
 
-Tracy может отображать панель отладки и блюскрины для AJAX-запросов и перенаправлений. Tracy создает собственные сессии, хранит данные в собственных временных файлах и использует cookie `tracy-session`.
+Tracy автоматически перехватывает AJAX-запросы, выполненные с помощью jQuery или собственного API `fetch`. Эти запросы отображаются в виде дополнительных строк в панели Tracy, что позволяет легко и просто отлаживать AJAX.
+
+Если вы не хотите автоматически перехватывать AJAX-запросы, вы можете отключить эту функцию, установив переменную JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Для ручного мониторинга определенных AJAX-запросов добавьте HTTP-заголовок `X-Tracy-Ajax` со значением, возвращаемым функцией `Tracy.getAjaxHeader()`. Вот пример его использования с функцией `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Такой подход позволяет выборочно отлаживать AJAX-запросы.
+
+
+Хранение данных .[#toc-data-storage]
+====================================
+
+Tracy может отображать панели Tracy bar и Bluescreens для AJAX-запросов и редиректов. Tracy создает собственные сессии, хранит данные в собственных временных файлах и использует cookie `tracy-session`.
 
 Tracy также может быть настроен на использование собственной сессии PHP, которая запускается до включения Tracy:
 
diff --git a/tracy/sl/guide.texy b/tracy/sl/guide.texy
index 3a411e57c7..1ba75ead61 100644
--- a/tracy/sl/guide.texy
+++ b/tracy/sl/guide.texy
@@ -79,9 +79,9 @@ ali nezajeta izjema:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Podprte različice PHP .[#toc-supported-php-versions]
 
 | Tracy | združljivo s PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/sl/open-files-in-ide.texy b/tracy/sl/open-files-in-ide.texy
index f616ef9d31..ee0233abd4 100644
--- a/tracy/sl/open-files-in-ide.texy
+++ b/tracy/sl/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Bodite previdni in ohranite dvojne poševnice v poteh.
 
 To storite tako, da zaženete `install.cmd`. **Zažeti ga morate kot skrbnik.** Skripta `open-editor.js` bo zdaj služila protokolu `editor://`.
 
+Če želite odpreti povezave, ustvarjene v drugih strežnikih, na primer produkcijskem strežniku ali strežniku Docker, v spletno mesto `open-editor.js` dodajte preslikavo oddaljenega v lokalni naslov URL:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/sl/recipes.texy b/tracy/sl/recipes.texy
index 7288e81350..a32cec05c0 100644
--- a/tracy/sl/recipes.texy
+++ b/tracy/sl/recipes.texy
@@ -42,10 +42,35 @@ Rešitev je, da postavite `<?php Tracy\Debugger::renderLoader() ?>` v predlogo p
 ```
 
 
-AJAX in preusmerjeni zahtevki .[#toc-ajax-and-redirected-requests]
-==================================================================
+Razhroščevanje zahtevkov AJAX .[#toc-debugging-ajax-requests]
+=============================================================
 
-Tracy lahko prikaže Debug bar in Bluescreens za zahteve AJAX in preusmeritve. Tracy ustvarja lastne seje, shranjuje podatke v lastne začasne datoteke in uporablja piškotek `tracy-session`.
+Tracy samodejno zajame zahteve AJAX, opravljene z uporabo programa jQuery ali izvornega vmesnika API `fetch`. Ti zahtevki so prikazani kot dodatne vrstice v vrstici Tracy, kar omogoča enostavno in priročno razhroščevanje AJAX.
+
+Če ne želite samodejno zajemati zahtevkov AJAX, lahko to funkcijo onemogočite z nastavitvijo spremenljivke JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Za ročno spremljanje določenih zahtevkov AJAX dodajte glavo HTTP `X-Tracy-Ajax` z vrednostjo, ki jo vrne funkcija `Tracy.getAjaxHeader()`. Tukaj je primer uporabe s funkcijo `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Ta pristop omogoča selektivno razhroščevanje zahtevkov AJAX.
+
+
+Shranjevanje podatkov .[#toc-data-storage]
+==========================================
+
+Tracy lahko prikaže Tracy bar plošče in Bluescreens za zahteve AJAX in preusmeritve. Tracy ustvarja lastne seje, shranjuje podatke v lastne začasne datoteke in uporablja piškotek `tracy-session`.
 
 Tracy je mogoče konfigurirati tudi za uporabo izvorne seje PHP, ki se zažene, preden je Tracy vklopljen:
 
diff --git a/tracy/tr/guide.texy b/tracy/tr/guide.texy
index 30b5ded8b0..d6176e28ac 100644
--- a/tracy/tr/guide.texy
+++ b/tracy/tr/guide.texy
@@ -79,9 +79,9 @@ veya yakalanmamış istisna:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Desteklenen PHP Sürümleri .[#toc-supported-php-versions]
 
 | Tracy | PHP ile uyumlu
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/tr/open-files-in-ide.texy b/tracy/tr/open-files-in-ide.texy
index b9b4900fb2..50fab80666 100644
--- a/tracy/tr/open-files-in-ide.texy
+++ b/tracy/tr/open-files-in-ide.texy
@@ -41,6 +41,15 @@ Dikkatli olun ve çift eğik çizgileri yollarda tutun.
 
 Bu işlem `install.cmd` çalıştırılarak yapılır. **Yönetici olarak çalıştırmanız gerekir.** `open-editor.js` betiği artık `editor://` protokolüne hizmet edecektir.
 
+Üretim sunucusu veya Docker gibi diğer sunucularda oluşturulan bağlantıları açmak için `open-editor.js` adresine bir uzak-yerel URL eşlemesi ekleyin:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/tr/recipes.texy b/tracy/tr/recipes.texy
index 31495801b3..4e68ff3f9c 100644
--- a/tracy/tr/recipes.texy
+++ b/tracy/tr/recipes.texy
@@ -42,10 +42,35 @@ Temel entegrasyon basittir, ancak web sayfasında yavaş engelleyen komut dosyal
 ```
 
 
-AJAX ve Yönlendirilmiş İstekler .[#toc-ajax-and-redirected-requests]
-====================================================================
+AJAX İsteklerinde Hata Ayıklama .[#toc-debugging-ajax-requests]
+===============================================================
 
-Tracy, AJAX istekleri ve yönlendirmeleri için Hata Ayıklama çubuğu ve Mavi Ekranlar görüntüleyebilir. Tracy kendi oturumlarını oluşturur, verileri kendi geçici dosyalarında saklar ve bir `tracy-session` çerezi kullanır.
+Tracy, jQuery veya yerel `fetch` API kullanılarak yapılan AJAX isteklerini otomatik olarak yakalar. Bu istekler Tracy çubuğunda ek satırlar olarak görüntülenerek kolay ve kullanışlı AJAX hata ayıklama olanağı sağlar.
+
+AJAX isteklerini otomatik olarak yakalamak istemiyorsanız, JavaScript değişkenini ayarlayarak bu özelliği devre dışı bırakabilirsiniz:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Belirli AJAX isteklerinin manuel olarak izlenmesi için, `Tracy.getAjaxHeader()` tarafından döndürülen değerle `X-Tracy-Ajax` HTTP başlığını ekleyin. `fetch` işleviyle birlikte kullanımına ilişkin bir örnek aşağıda verilmiştir:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Bu yaklaşım, AJAX isteklerinin seçici olarak hata ayıklamasına olanak tanır.
+
+
+Veri Depolama .[#toc-data-storage]
+==================================
+
+Tracy, AJAX istekleri ve yönlendirmeleri için Tracy çubuk panellerini ve Bluescreens'i görüntüleyebilir. Tracy kendi oturumlarını oluşturur, verileri kendi geçici dosyalarında saklar ve bir `tracy-session` çerezi kullanır.
 
 Tracy, Tracy açılmadan önce başlatılan yerel bir PHP oturumu kullanacak şekilde de yapılandırılabilir:
 
diff --git a/tracy/uk/guide.texy b/tracy/uk/guide.texy
index 6761dcd4bb..09ea1d6417 100644
--- a/tracy/uk/guide.texy
+++ b/tracy/uk/guide.texy
@@ -79,9 +79,9 @@ or uncaught exception:
 <b>Fatal error</b>:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
 Stack trace:
 #0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
-#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
-#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create()
-#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm')
+#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
+#2 /sandbox/app/UI/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
+#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\UI\Sign\SignPresenter->createComponentSignInForm('signInForm')
 #4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
 #5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in <b>/sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php</b> on line <b>100</b><br />
 \--
@@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com';
 
 | Tracy | сумісні з PHP
 |-----------|--------------------
-| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2
+| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3
 | Tracy 2.9 | PHP 7.2 - 8.2
 | Tracy 2.8 | PHP 7.2 - 8.1
 | Трейсі 2.6 - 2.7 | PHP 7.1 - 8.0
diff --git a/tracy/uk/open-files-in-ide.texy b/tracy/uk/open-files-in-ide.texy
index b1272d7225..42681cc378 100644
--- a/tracy/uk/open-files-in-ide.texy
+++ b/tracy/uk/open-files-in-ide.texy
@@ -41,6 +41,15 @@ var settings = {
 
 Це робиться шляхом запуску скрипта `install.cmd`. **Ви повинні запустити його від імені адміністратора.** Скрипт `open-editor.js` тепер буде обслуговувати протокол `editor://`.
 
+Щоб відкрити посилання, створені на інших серверах, таких як продакшн-сервер або Docker, додайте віддалене до локального зіставлення URL-адрес до `open-editor.js`:
+
+```js
+	mappings: {
+		// remote path: local path
+		'/var/www/nette.app': 'W:\\Nette.web\\_web',
+	}
+```
+
 
 Linux .[#toc-linux]
 ===================
diff --git a/tracy/uk/recipes.texy b/tracy/uk/recipes.texy
index ca817ea99c..54ea67bc07 100644
--- a/tracy/uk/recipes.texy
+++ b/tracy/uk/recipes.texy
@@ -42,10 +42,35 @@ header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic';");
 ```
 
 
-AJAX та перенаправлення запитів .[#toc-ajax-and-redirected-requests]
-====================================================================
+Налагодження AJAX-запитів .[#toc-debugging-ajax-requests]
+=========================================================
+
+Tracy автоматично перехоплює AJAX-запити, виконані за допомогою jQuery або власного API `fetch`. Ці запити відображаються у вигляді додаткових рядків у панелі Tracy, що дозволяє легко і зручно налагоджувати AJAX.
+
+Якщо ви не бажаєте автоматично перехоплювати AJAX-запити, ви можете вимкнути цю функцію, задавши змінну JavaScript:
+
+```js
+window.TracyAutoRefresh = false;
+```
+
+Для ручного моніторингу конкретних AJAX-запитів додайте HTTP-заголовок `X-Tracy-Ajax` зі значенням, яке повертає функція `Tracy.getAjaxHeader()`. Ось приклад його використання з функцією `fetch`:
+
+```js
+fetch(url, {
+    headers: {
+        'X-Requested-With': 'XMLHttpRequest',
+        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
+    }
+})
+```
+
+Такий підхід дозволяє вибірково налагоджувати AJAX-запити.
+
+
+Зберігання даних .[#toc-data-storage]
+=====================================
 
-Tracy може відображати панель налагодження та сині екрани для AJAX-запитів і перенаправлень. Tracy створює власні сесії, зберігає дані у власних тимчасових файлах і використовує файли cookie `tracy-session`.
+Tracy може відображати панелі Tracy і сині екрани для AJAX-запитів і перенаправлень. Tracy створює власні сесії, зберігає дані у власних тимчасових файлах і використовує файли cookie `tracy-session`.
 
 Tracy також можна налаштувати на використання власного сеансу PHP, який запускається перед ввімкненням Tracy:
 
diff --git a/utils/bg/@home.texy b/utils/bg/@home.texy
index 25520611d9..34852da426 100644
--- a/utils/bg/@home.texy
+++ b/utils/bg/@home.texy
@@ -11,15 +11,16 @@
 | [Генериране на случайни низове |random] | Nette\Utils\Random
 | [Дата и час |datetime] | Nette\Utils\DateTime
 | [Nette\Utils\Image |images]
-| [Модел на обекта |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Пагинация |paginator] | Nette\Utils\Paginator
 | [Парсинг и генериране на JSON |json] | Nette\Utils\Json
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [Полета |arrays] | Nette\Utils\Arrays
 | [Низове |strings] | Nette\Utils\Strings
 | [Тип Nette\Utils\Type |type]
 | [Файлова система |filesystem] | Nette\Utils\FileSystem
 | [Полезни функции | Nette\Utils\Helpers |helpers]
 | [HTML елементи |html-elements] | Nette\Utils\Html
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [PHP Reflection |reflection] | Nette\Utils\Reflection
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | PHP съвместима версия
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/bg/@left-menu.texy b/utils/bg/@left-menu.texy
index 9d14fb22d2..8c8dc979e3 100644
--- a/utils/bg/@left-menu.texy
+++ b/utils/bg/@left-menu.texy
@@ -8,6 +8,7 @@
 - [Снимки |images]
 - [Обратни извиквания |callback]
 - [Пагинатор |paginator]
+- [Iterables |iterables]
 - [Поле |arrays]
 - [Случайни низове |random]
 - [Струни |strings]
@@ -15,8 +16,9 @@
 - [Файлова система |filesystem]
 - [Помощни функции |helpers]
 - [Елементи на HTML |html-elements]
+- [SmartObject]
+- [StaticClass]
 - [Размисли за PHP |reflection]
-- [SmartObject |smartobject]
 
 
 Други инструменти
diff --git a/utils/bg/arrays.texy b/utils/bg/arrays.texy
index 820513e2e8..d0942f4322 100644
--- a/utils/bg/arrays.texy
+++ b/utils/bg/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Масиви .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] е статичен клас, който съдържа полезни функции за работа с масиви.
+[api:Nette\Utils\Arrays] е статичен клас, който съдържа няколко удобни функции за масиви. Неговият еквивалент за итератори е [Nette\Utils\Iterables |iterables].
 
 Следващите примери предполагат, че псевдонимът вече е създаден:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Функцията гъвкаво трансформира `$array` в асоциативен масив или обекти в съответствие със зададения път `$path`. Пътят може да бъде низ или масив. Той се състои от имената на ключовете във входния масив и оператори като "[]", "->", "=" и "|". Изхвърля `Nette\InvalidArgumentException`, ако пътят е невалиден.
+
+```php
+// конвертиране в асоциативен масив с помощта на прост ключ
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// присвояване на стойности от един ключ към друг с помощта на оператора =
+$result = Arrays::associate($arr, 'name=age'); // или ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// създаване на обект с помощта на оператора ->
+$result = Arrays::associate($arr, '->name'); // или ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// комбиниране на клавиши с помощта на оператора |
+$result = Arrays::associate($arr, 'name|age'); // или ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// добавяне към масив с помощта на []
+$result = Arrays::associate($arr, 'name[]'); // или ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,10 +76,10 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
-Проверява дали всички елементи в масива са преминали теста, реализиран в `$callback` с подпис `function ($value, $key, array $array): bool`.
+Проверява дали всички елементи в масива са преминали теста, реализиран в `$predicate` с подпис `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 30, 39, 29, 10, 13];
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Вижте [some( |#some]).
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Връща нов масив, съдържащ всички двойки ключ-стойност, отговарящи на зададения `$predicate`. Обратното извикване има сигнатурата `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Връща първия запис в масива или null, ако масивът е празен. Не променя вътрешния указател, за разлика от `reset()`.
+Връща първия елемент (отговарящ на зададеното предсказание, ако е дадено). Ако няма такъв елемент, връща резултата от извикването на `$else` или null.
+ `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`.
+
+Той не променя вътрешния указател за разлика от `reset()`. Параметрите `$predicate` и `$else` съществуват от версия 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Вижте [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Връща ключа на първия елемент (отговарящ на зададения предикат, ако е зададен) или null, ако няма такъв елемент. `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Масиви::first([]); // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Вижте [lastKey( |#lastKey()]).
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Връща елемент `$array[$key]`. Ако той не съществува, се изписва изключение `Nette\InvalidArgumentException` или, ако е зададен трети параметър `$default`, се връща този параметър.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Връща последния елемент (отговарящ на зададения предикат, ако е зададен). Ако няма такъв елемент, връща резултата от извикването на `$else` или null.
+ `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`.
+
+Той не променя вътрешния указател за разлика от `end()`. Параметрите `$predicate` и `$else` съществуват от версия 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Вижте [first( |#first()]).
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Връща последния запис на масива или null, ако масивът е празен. Не променя вътрешния указател, за разлика от `end()`.
+Връща ключа на последния елемент (отговарящ на зададения предикат, ако е зададен) или null, ако няма такъв елемент. `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Вижте [firstKey( |#firstKey()]).
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Извиква `$callback` върху всички елементи на масив и връща масив от върнати стойности. Обратното извикване има сигнатура `function ($value, $key, array $array): bool`.
+Извиква `$transformer` върху всички елементи на масив и връща масив от върнати стойности. Обратното извикване има сигнатура `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Създава нов масив, като трансформира стойностите и ключовете на оригиналния масив. Функцията `$transformer` има сигнатура `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Ако `$transformer` върне `null`, елементът се пропуска. За запазените елементи първият елемент от върнатия масив се използва като нов ключ, а вторият елемент - като нова стойност.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Този метод е полезен в ситуации, в които трябва да се промени структурата на масив (едновременно и ключове, и стойности) или да се филтрират елементите по време на преобразуването (чрез връщане на null за нежелани елементи).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Стойностите от втория масив винаги се добавят към края на първия масив. Изчезването на стойността `10` от второто поле може да изглежда малко объркващо. Обърнете внимание, че тази стойност е същата като стойността `5` v poli prvním mají přiřazený stejný numerický klíč `0`, така че само елементът от първото поле влиза в получения масив.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Нормализира масива до асоциативен масив. Заменя ключовете с числа с техните стойности, като новата стойност е `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Връща и премахва стойността на елемент от масива. Ако не съществува, се хвърля изключение или се връща стойността `$default`, ако съществува.
 
@@ -284,10 +397,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
-Проверява се дали поне един елемент от масива е преминал теста, реализиран в `$callback`, с подпис `function ($value, $key, array $array): bool`.
+Проверява се дали поне един елемент от масива е преминал теста, реализиран в `$predicate`, с подпис `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 2, 3, 4];
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Извежда всеки елемент от масива в низ и го обвива с префикс `$prefix` и суфикс `$suffix`.
 
diff --git a/utils/bg/datetime.texy b/utils/bg/datetime.texy
index 7c98e521c0..21c5c119fb 100644
--- a/utils/bg/datetime.texy
+++ b/utils/bg/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Разширява функцията [DateTime::createFromFormat( |https://www.php.net/manual/en/datetime.createfromformat.php] ) с възможност за въвеждане на часовата зона като низ.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
diff --git a/utils/bg/filesystem.texy b/utils/bg/filesystem.texy
index c17d8ffb79..ea12aa182e 100644
--- a/utils/bg/filesystem.texy
+++ b/utils/bg/filesystem.texy
@@ -2,9 +2,11 @@
 ****************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] е статичен клас, който съдържа полезни функции за работа с файлова система. Едно от предимствата им пред нативните функции на PHP е, че те хвърлят изключения в случай на грешки.
+[api:Nette\Utils\FileSystem] е клас, който съдържа полезни функции за работа с файлова система. Едно от предимствата им пред нативните функции на PHP е, че те хвърлят изключения в случай на грешки.
 
 
+Ако трябва да търсите файлове на диска, използвайте [Finder |finder].
+
 Инсталация:
 
 ```shell
@@ -174,3 +176,26 @@ platformSlashes(string $path): string .[method]
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Статичен срещу нестатичен подход .[#toc-static-vs-non-static-approach]
+======================================================================
+
+За да замените лесно класа `FileSystem` с друг клас, например за целите на тестването, използвайте го нестатично:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/bg/finder.texy b/utils/bg/finder.texy
index b7d2b8f193..267cd5a7ea 100644
--- a/utils/bg/finder.texy
+++ b/utils/bg/finder.texy
@@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // всички директории
 
 Можете да използвате [заместващи символи |#wildcards] `*`, `**`, `?` and `[...]` в маската. Можете дори да посочите директории, например `src/*.php` ще търси всички PHP файлове в директорията `src`.
 
+Симлинковете също се считат за директории или файлове.
+
 
 Къде да търсим? .[#toc-where-to-search]
 ---------------------------------------
diff --git a/utils/bg/floats.texy b/utils/bg/floats.texy
index bb50d2f0ba..8842030811 100644
--- a/utils/bg/floats.texy
+++ b/utils/bg/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 При опит за сравняване на `NAN` се получава изключение `\LogicException`.
 
+.[tip]
+Класът `Floats` толерира разлики, по-малки от `1e-10`. Ако трябва да работите с по-голяма точност, използвайте вместо това библиотеката BCMath.
+
 
 Сравнение на плаващи стойности .[#toc-float-comparison]
 =======================================================
diff --git a/utils/bg/html-elements.texy b/utils/bg/html-elements.texy
index bb2856bba9..c2d3163f58 100644
--- a/utils/bg/html-elements.texy
+++ b/utils/bg/html-elements.texy
@@ -219,10 +219,10 @@ $el = Html::el('span')
 Друг начин за създаване и вмъкване на нов възел `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('první');
-// <ul><li class="first">první</li></ul>
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
+// <ul><li class="first">hello</li></ul>
 ```
 
 Можете да работите с възли, сякаш са масиви. Тоест адресирайте всеки от тях с квадратни скоби, пребройте ги с `count()` и извършете итерация:
diff --git a/utils/bg/images.texy b/utils/bg/images.texy
index ea5a079c9e..053c5bf5da 100644
--- a/utils/bg/images.texy
+++ b/utils/bg/images.texy
@@ -17,6 +17,8 @@ composer require nette/utils
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 По желание можете да зададете цвят на фона (по подразбиране е черен):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Или да качите изображение от файл:
@@ -41,17 +43,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
 $image = Image::fromFile('nette.jpg');
 ```
 
-Поддържаните формати са JPEG, PNG, GIF, WebP, AVIF и BMP, но вашата версия на PHP също трябва да ги поддържа (проверете `phpinfo()`, раздел GD). Анимациите не се поддържат.
-
-Трябва ли да определям формата на изображението при качване? Методът го връща във втория параметър:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type е Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF или Image::BMP
-```
-
-Само откриването без зареждане на изображението се извършва от `Image::detectTypeFromFile()`.
-
 
 Запазване на изображения .[#toc-save-the-image]
 ===============================================
@@ -68,25 +59,45 @@ $image->save('resampled.jpg');
 $image->save('resampled.jpg', 80); // JPEG, 80% качество
 ```
 
-Ако форматът не е очевиден от разширението на файла, той може да бъде посочен с една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`:
+Ако форматът не е очевиден от файловото разширение, той може да бъде посочен с [константа |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Изображението може да бъде записано на променлива вместо на диск:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, 80% качество
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, 80% качество
 ```
 
 или се изпраща директно на браузъра със съответния HTTP хедър `Content-Type`:
 
 ```php
 // изпраща заглавие Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Формати .[#toc-formats]
+=======================
+
+Поддържаните формати са JPEG, PNG, GIF, WebP, AVIF и BMP. Те обаче трябва да се поддържат и от вашата версия на PHP, което може да се провери чрез функцията [isTypeSupported(). |#isTypeSupported()] Анимациите не се поддържат.
+
+Форматите са представени от константите `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` и `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Трябва да определите формата на дадено изображение при зареждане? Методът го връща във втория параметър:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Действителното откриване, без да се зарежда изображението, се извършва от `Image::detectTypeFromFile()`.
+
 
 Промяна на размера .[#toc-image-resize]
 =======================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Методът `cropAuto()` е заместител на обект на функцията `imagecropauto()`, за повече подробности вижте [нейната документация |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Цветове .[#toc-colors]
+======================
+
+Методът `ImageColor::rgb()` ви позволява да дефинирате цвят, като използвате червени, зелени и сини (RGB) стойности. По желание можете да зададете и стойност за прозрачност, варираща от 0 (напълно прозрачен) до 1 (напълно непрозрачен), точно както в CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Методът `ImageColor::hex()` ви позволява да дефинирате цвят, като използвате шестнадесетичен формат, подобно на CSS. Той поддържа форматите `#rgb`, `#rrggbb`, `#rgba` и `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Цветовете могат да се използват и в други методи, като например `ellipse()`, `fill()` и т.н.
+
+
 Рисуване и редактиране .[#toc-drawing-and-editing]
 ==================================================
 
-Можете да рисувате, можете да пишете, но не разкъсвайте страниците. Всички функции за изображения на PHP, като например [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], са достъпни за вас, но в обектно-ориентиран вид:
+Можете да рисувате, да пишете, да използвате всички функции на PHP за манипулиране на изображения, вижте [Преглед на методите |#Overview of methods], но в обектно-ориентирана обвивка:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Вижте [Преглед на методите |#Overview-of-Methods].
+Тъй като функциите на PHP за изчертаване на правоъгълници са непрактични поради задаването на координати, класът `Image` предлага техни заместители под формата на функциите [rectangleWH() |#rectangleWH()] и [filledRectangleWH() |#filledRectangleWH()].
 
 
 Комбиниране на няколко изображения .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // координатите отново могат да бъдат зададени като процент
 $blank->place($logo, '80%', '80%'); // вмъкване в долния десен ъгъл
@@ -219,53 +250,68 @@ $blank->place($image, '80%', '80%', 25); // прозрачността е 25%
 ===============================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Създава ново истинско цветно изображение със зададени размери. Цветът по подразбиране е черен.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Чете изображение от файл и връща неговия тип в `$detectedFormat`. Поддържаните типове са `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Чете изображение от файл и връща неговия [тип |#Formats] в `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Чете изображение от низ и връща неговия тип в `$detectedFormat`. Поддържаните типове са `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Чете изображение от низ и връща неговия [тип |#Formats] в `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Създава цвят, който може да се използва в други методи, като например `ellipse()`, `fill()` и т.н.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Тази функция е заменена от класа `ImageColor`, вижте [цветовете |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Връща разширението на файла за дадената константа `Image::XXX`.
+Връща разширението на файла за дадения [тип |#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Връща типа mime за дадената константа `Image::XXX`.
+Връща типа mime за дадения [тип |#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Връща типа mime като константа `Image::XXX` според разширението на файла.
+Връща [типа на |#Formats] изображението в съответствие с разширението на файла.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Връща типа на изображението като константа `Image::XXX`, а размерите му - като `$width` и `$height`.
+Връща [типа на |#Formats] файла с изображение, а в параметрите `$width` и `$height` - и неговите размери.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Връща типа на изображението от символния низ като константа `Image::XXX` и размерите му в параметрите `$width` и `$height`.
+Връща [типа на |#Formats] изображението от низ, а в параметрите `$width` и `$height` - и неговите размери.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Определя дали даденият [тип |#Formats] изображение се поддържа.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Връща масив от поддържаните типове изображения (константи `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Изчислява размерите на правоъгълника, който огражда текст с определен шрифт и размер. Връща асоциативен масив, съдържащ ключовете `left`, `top`, `width`, `height`. Лявото поле може да бъде отрицателно, ако текстът започва с ляв надвес.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Връща изображение, съдържащо афинно-трансформирано src изображение, като се използва опционална област на изрязване. ([повече информация |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Връща конкатенацията на две матрици за афинна трансформация, което е полезно, ако трябва да се приложат няколко трансформации към едно и също изображение. ([повече подробности |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Връща матричната трансформационна матрица. ([повече подробности |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ antialias(bool $on): void .[method]
 Използването на изгладения примитив с прозрачен цвят на фона може да доведе до неочаквани резултати. Методът на смесване използва цвета на фона като всеки друг цвят. ([повече подробности |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Изчертава дъга от окръжност с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Изчертава първия символ `$char` в изображението с горен ляв ъгъл `$x`, `$y` (горният ляв ъгъл е равен на 0, 0), цвят `$color`. ([повече подробности |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Изчертава символа `$char` вертикално в посочената координата в посоченото изображение. ([повече подробности |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Връща идентификатор на цвят, представляващ цвят, съставен от дадените компоненти RGB. Трябва да се извика, за да се създаде всеки цвят, който ще се използва в изображението. ([повече подробности |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Връща броя на цветовете в палитрата на изображението. ([повече подробности |https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Получава или задава прозрачен цвят за изображението. ([повече подробности |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Изрязване на изображението до определена правоъгълна област. Размерът може да бъде зададен като цяло число в пиксели или като низ в проценти (напр. `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Автоматично изрязване на изображението в съответствие със зададеното `$mode`. ([прочети повече) |https://www.php.net/manual/en/function.imagecropauto]
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Изчертава елипса с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Запълва областта, започваща от зададената координата (горе вляво 0, 0), със зададеното `$color`. ([повече подробности |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Изчертава непълна дъга с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Изчертава елипса с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Създава запълнен многоъгълник върху изображението. ([повече подробности |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Създава правоъгълник, запълнен с `$color` в изображението, като започва от точка 1 и завършва в точка 2. Точка 0, 0 е горният ляв ъгъл на изображението. ([повече подробности |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Създава правоъгълник, запълнен с `$color` в изображението, започващ от `$x1` & `$y1` и завършващ на `$x2` & `$y2`. Точка 0, 0 е горният ляв ъгъл на изображението. ([още) |https://www.php.net/manual/en/function.imagefilledrectangle]
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Създава правоъгълник, запълнен с `$color` в изображението, започващ от точките `$left` и `$top`, с ширина `$width` и височина `$height`. Точка 0, 0 е горният ляв ъгъл на изображението.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Създава запълване, чийто цвят на границата се определя от `$border`. Началната точка на запълването е `$x`, `$y` (горният ляв ъгъл - 0, 0), а областта се запълва с цвета `$color`. ([повече подробности |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Инвертира изображението на посочения адрес `$mode`. ([прочети повече) |https://www.php.net/manual/en/function.imageflip]
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Напишете текст върху изображението, като използвате шрифтове FreeType 2. ([още) |https://www.php.net/manual/en/function.imagefttext]
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Напишете текста на картинката. ([повече) |https://www.php.net/manual/en/function.imagefttext]
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Връща ширината на изображението.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Включва или изключва режима с преливане. Ако е зададен режим с преплитане и изображението е записано във формат JPEG, изображението ще бъде записано като прогресивен JPEG. ([повече подробности |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Задайте флага за алфа смесване, за да използвате ефекти на наслояване. ([повече подробности |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Начертава линия между две дадени точки. ([повече подробности |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Начертава отворен многоъгълник в изображението. За разлика от `polygon()`, между последната и първата точка не се прокарва линия. ([повече подробности |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Копира `$image` в изображението с координати `$left` и `$top`. Координатите могат да бъдат зададени като цели числа в пиксели или като низове в проценти (напр. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Създава многоъгълник в изображението. ([повече подробности |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Създава правоъгълник със зададени координати. ([повече подробности |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Създава правоъгълник със зададените координати.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Промяна на размера на изображението, [допълнителна информация |#Image-Resize]. Размерите могат да бъдат зададени като цели числа в пиксели или като низове в проценти (напр. `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Задава или връща разделителната способност на изображението в DPI (точки на инч). Ако не е посочен нито един от незадължителните параметри, текущата резолюция се връща като индексирано поле. Ако е посочен само `$resX`, хоризонталната и вертикалната разделителна способност се задава на тази стойност. Ако са зададени и двата незадължителни параметъра, хоризонталната и вертикалната разделителна способност се настройват на тези стойности.
 
 Разделителната способност се използва като метаинформация само при четене и запис на изображения във формати, които поддържат такава информация (понастоящем PNG и JPEG). Тя не оказва влияние върху операциите по боядисване. Разделителната способност по подразбиране за нови изображения е 96 DPI. ([прочети повече) |https://www.php.net/manual/en/function.imageresolution]
@@ -582,11 +628,11 @@ rotate(float $angle, int $backgroundColor): Image .[method]
 Изисква *Пълен GD разширение*, така че може да не работи навсякъде.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Записва изображението във файл.
 
-Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Ако типът не е очевиден от разширението на файла, можете да го посочите, като използвате една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Ако типът не е очевиден от разширението на файла, можете да го посочите, като използвате една от константите на `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Мащабирайте изображението, като използвате зададения алгоритъм за интерполация. ([повече подробности |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Извежда изображението в браузъра.
 
-Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Типът е една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Задава метода на интерполация, който влияе на методите `rotate()` и `affine()`. ([повече подробности |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Изчертава пиксел в зададена координата. ([повече подробности |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ sharpen(): Image .[method]
 Изисква *Пълен GD разширение*, така че може да не работи навсякъде.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Извежда низ в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Извежда низ по вертикала в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Записва изображението в низ.
 
-Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Типът е една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Преобразува истинско цветно изображение в палитра. ([прочети повече) |https://www.php.net/manual/en/function.imagetruecolortopalette]
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Отпечатва зададен текст в изображение, като използва шрифтове TrueType. ([повече подробности |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Записва дадения текст в изображението. ([още) |https://www.php.net/manual/en/function.imagettftext]
diff --git a/utils/bg/iterables.texy b/utils/bg/iterables.texy
new file mode 100644
index 0000000000..a7fe192151
--- /dev/null
+++ b/utils/bg/iterables.texy
@@ -0,0 +1,170 @@
+Функции на итератора
+********************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] е статичен клас с функции за работа с итератори. Неговият аналог за масиви е [Nette\Utils\Arrays |arrays].
+
+
+Инсталация:
+
+```shell
+composer require nette/utils
+```
+
+Всички примери предполагат, че е създаден следният псевдоним:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Търси дадена стойност в итератор. Използва стриктно сравнение (`===`), за да провери за съвпадение. Връща `true`, ако стойността е намерена, в противен случай `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Този метод е полезен, когато трябва бързо да определите дали определена стойност присъства в итератора, без да преминавате ръчно през всички елементи.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Търси даден ключ в итератор. Използва стриктно сравнение (`===`), за да провери за съвпадение. Връща `true`, ако ключът е намерен, в противен случай `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Проверява дали всички елементи на итератора отговарят на условието, дефинирано в `$predicate`. Функцията `$predicate` има сигнатура `function ($value, $key, iterable $iterable): bool` и трябва да връща `true` за всеки елемент, за да може методът `every()` да връща `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Този метод е полезен за проверка дали всички елементи в дадена колекция отговарят на определено условие, например дали всички числа са под определена стойност.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Създава нов итератор, който съдържа само елементите от оригиналния итератор, които отговарят на условието, дефинирано в `$predicate`. Функцията `$predicate` има сигнатура `function ($value, $key, iterable $iterable): bool` и трябва да връща `true` за елементите, които трябва да бъдат запазени.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Методът използва генератор, което означава, че филтрирането се извършва инкрементално по време на итерацията. Това е ефективно по отношение на паметта и позволява работа с много големи колекции. Ако не итерирате през всички елементи на получения итератор, спестявате изчислителни усилия, тъй като не всички елементи на първоначалния итератор се обработват.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Връща първия елемент на итератора. Ако е предоставен `$predicate`, се връща първият елемент, който отговаря на даденото условие. Функцията `$predicate` има сигнатура `function ($value, $key, iterable $iterable): bool`. Ако не бъде намерен съответстващ елемент, се извиква функцията `$else` (ако е предоставена) и се връща нейният резултат. Ако не е предоставена `$else`, се връща `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Този метод е полезен, когато трябва бързо да се извлече първият елемент от дадена колекция или първият елемент, който отговаря на определено условие, без да се налага ръчно да се итерира цялата колекция.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Връща ключа на първия елемент на итератора. Ако е зададен `$predicate`, връща ключа на първия елемент, който отговаря на даденото условие. Функцията `$predicate` има сигнатура `function ($value, $key, iterable $iterable): bool`. Ако не е намерен съответстващ елемент, се извиква функцията `$else` (ако е предоставена) и се връща нейният резултат. Ако не е предоставена `$else`, се връща `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Създава нов итератор, като прилага функцията `$transformer` към всеки елемент на оригиналния итератор. Функцията `$transformer` има сигнатура `function ($value, $key, iterable $iterable): mixed` и нейната върната стойност се използва като нова стойност на елемента.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Методът използва генератор, което означава, че трансформацията се извършва инкрементално по време на итерацията. Това е ефективно по отношение на паметта и позволява работа с много големи колекции. Ако не итерирате през всички елементи на получения итератор, спестявате изчислителни усилия, тъй като не всички елементи на първоначалния итератор се обработват.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Създава нов итератор, като трансформира стойностите и ключовете на оригиналния итератор. Функцията `$transformer` има сигнатура `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Ако `$transformer` върне `null`, елементът се прескача. За запазените елементи първият елемент от върнатия масив се използва като нов ключ, а вторият елемент - като нова стойност.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Подобно на `map()`, този метод използва генератор за поетапна обработка и ефективност на паметта. Това позволява работа с големи колекции и спестяване на изчислителни усилия чрез обработване само на част от резултата.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Създава обвивка около итератор, която кешира ключовете и стойностите му по време на итерацията. Това позволява многократно итериране на данните, без да се налага да се обработва отново оригиналният източник на данни.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Този метод е полезен в ситуации, в които е необходимо да се итерира многократно един и същ набор от данни, но оригиналният итератор не поддържа многократна итерация или многократната итерация би била скъпа (например четене на данни от база данни или файл).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Проверява дали поне един елемент от итератора отговаря на условието, дефинирано в `$predicate`. Функцията `$predicate` има сигнатура `function ($value, $key, iterable $iterable): bool` и трябва да върне `true` за поне един елемент, за да може методът `some()` да върне `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Този метод е полезен за бърза проверка дали в дадена колекция има поне един елемент, който отговаря на определено условие, например дали колекцията съдържа поне едно четно число.
+
+Вижте [every(). |#every()]
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Преобразува всеки обект с итерации (масив, Traversable) в итератор. Ако входният обект вече е Iterator, той се връща непроменен.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Този метод е полезен, когато трябва да се уверите, че имате Iterator, независимо от типа на входните данни. Това може да бъде полезно при създаване на функции, които работят с различни типове итерационни данни.
diff --git a/utils/bg/json.texy b/utils/bg/json.texy
index ae3f5f104c..170f2117f4 100644
--- a/utils/bg/json.texy
+++ b/utils/bg/json.texy
@@ -77,7 +77,7 @@ decode(string $json, bool $forceArray=false): mixed .[method]
 
 ```php
 Json::decode('{"variable": true}'); // връща обект от тип stdClass
-Json::decode('{"variable": true}', forceArray: true); // return array
+Json::decode('{"variable": true}', forceArrays: true); // return array
 ```
 
 Ако възникне грешка, се изхвърля изключение на адрес `Nette\Utils\JsonException`.
diff --git a/utils/bg/smartobject.texy b/utils/bg/smartobject.texy
index 471bf25ce9..9e32435002 100644
--- a/utils/bg/smartobject.texy
+++ b/utils/bg/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject и StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject добавя поддръжка на *свойства* към класовете на PHP. StaticClass се използва за обозначаване на статични класове.
+SmartObject поправяше поведението на обектите по много начини, но днешният PHP вече включва повечето от тези подобрения. Въпреки това той все още добавя поддръжка за *собственост*.
 
 
 Настройка:
@@ -65,31 +65,16 @@ echo $circle->visible; // извиква isVisible()
 Свойствата са преди всичко "синтактична захар" и са предназначени да направят живота на програмиста по-сладък, като опростят кода. Ако нямате нужда от тях, не е нужно да ги използвате.
 
 
-Статични класове .[#toc-static-classes]
-=======================================
+Поглед към историята .[#toc-a-glimpse-into-history]
+===================================================
 
-Статичните класове, т.е. класовете, които не са предназначени да бъдат инстанцирани, могат да бъдат маркирани с `Nette\StaticClass`:
+SmartObject усъвършенстваше поведението на обектите по множество начини, но днес PHP вече включва повечето от тези подобрения на роден език. Следващият текст е носталгичен поглед назад към историята, който ни напомня как са се развивали нещата.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Когато се опитате да създадете инстанция, се появява изключение `Error`, което показва, че класът е статичен.
-
-
-Поглед към историята .[#toc-a-look-into-the-history]
-====================================================
-
-SmartObject е използван за подобряване и коригиране на поведението на класовете по много начини, но развитието на PHP направи повечето от първоначалните функции излишни. Затова по-долу ще разгледаме историята на развитието на тези функции.
-
-От самото начало обектният модел на PHP страдаше от някои сериозни недостатъци и неефективност. Това доведе до създаването на класа `Nette\Object` (през 2007 г.), който се опита да коригира тези проблеми и да подобри работата на потребителите на PHP. Това беше достатъчно, за да могат други класове да го наследят и да се възползват от предимствата му. Когато в PHP 5.4 беше въведена поддръжка на черти, класът `Nette\Object` беше заменен с `Nette\SmartObject`. По този начин вече не е било необходимо да се наследява от общ прародител. Освен това чертата може да се използва в класове, които вече са наследени от друг клас. Окончателният край на `Nette\Object` настъпи с излизането на PHP 7.2, който забрани именуването на класове `Object`.
+От самото си създаване обектният модел на PHP страдаше от множество сериозни недостатъци и пропуски. Това доведе до създаването на класа `Nette\Object` (през 2007 г.), който имаше за цел да поправи тези проблеми и да повиши удобството при използването на PHP. Всичко, което беше необходимо, беше други класове да наследят от него и да получат предимствата, които той предлагаше. Когато PHP 5.4 въведе поддръжка на черти, класът `Nette\Object` беше заменен с чертата `Nette\SmartObject`. Това премахна необходимостта от наследяване от общ предшественик. Освен това чертата можеше да се използва в класове, които вече наследяваха от друг клас. Окончателният край на `Nette\Object` настъпи с излизането на PHP 7.2, който забрани на класовете да се наричат `Object`.
 
-С развитието на PHP обектният модел и функциите на езика се усъвършенстваха. Някои характеристики на класа `SmartObject` станаха излишни. След излизането на PHP 8.2 единствената функция, която все още не се поддържа директно в PHP, е възможността за използване на т.нар. [свойства |#Properties, getters and setters].
+С развитието на PHP обектният модел и възможностите на езика се усъвършенстваха. Различните функции на класа `SmartObject` станаха излишни. След излизането на PHP 8.2 остана само една функция, която не се поддържа директно в PHP: възможността да се използват така наречените [свойства |#Properties, getters, and setters].
 
-Какви функции предлагат `Nette\Object` и `Nette\Object`? Ето един преглед. (В примерите е използван класът `Nette\Object`, но повечето от свойствата се отнасят и за `Nette\SmartObject` ).
+Какви функции предлагаха `Nette\Object` и, като следствие, `Nette\SmartObject`? Ето един преглед. (В примерите е използван класът `Nette\Object`, но повечето функции се отнасят и за признака `Nette\SmartObject` ).
 
 
 Непоследователни грешки .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Съвременният PHP може и да не разполага с формата "Искахте ли да кажете?", но [Трейси |tracy:] добавя тази добавка към грешките. Той дори може сам да [коригира |tracy:open-files-in-ide#toc-demos] такива грешки.
+Въпреки че днешният PHP не разполага с функция "Искахте ли да кажете?", тази фраза може да бъде добавена към грешките от [Tracy |tracy:]. Тя дори може да [коригира такива грешки автоматично |tracy:open-files-in-ide#toc-demos].
 
 
 Методи за разширение .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // връща 'John Doe
+$reflection->getAnnotation('author'); // връща 'John Doe'
 ```
 
 От версия 8.0 на PHP вече е възможен достъп до метаинформация под формата на атрибути:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/bg/staticclass.texy b/utils/bg/staticclass.texy
new file mode 100644
index 0000000000..4b65d4e728
--- /dev/null
+++ b/utils/bg/staticclass.texy
@@ -0,0 +1,21 @@
+Статични класове
+****************
+
+.[perex]
+StaticClass се използва за обозначаване на статични класове.
+
+
+Инсталация:
+
+```shell
+composer require nette/utils
+```
+
+Статичните класове, т.е. класовете, които не са предназначени да бъдат инстанцирани, могат да бъдат маркирани с признака [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/bg/strings.texy b/utils/bg/strings.texy
index dde4e47a1e..787b4fa6e9 100644
--- a/utils/bg/strings.texy
+++ b/utils/bg/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Променя низът UTF-8 до формата, използван в URL адресите, т.е. премахва диакритичните знаци и заменя всички символи с изключение на английските букви и цифри с дефис.
 
@@ -129,8 +129,8 @@ Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
 Изисква разширението на PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Орязва белите символи (или други символи, посочени от втория параметър) от началото и края на низ в UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Връща UTF-8 частта на низа `$s`, зададена от началната позиция `$start` и дължината `$length`. Ако `$start` е отрицателна стойност, върнатият низ ще започне със символа -`$start` символа от края.
 
@@ -266,8 +266,8 @@ Strings::length('červená'); // 7
 \--
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Сравняване на два низа в UTF-8 или части от низове, които не се различават по размер. Ако `$length` съдържа null, се сравняват цели низове, ако е отрицателен, се сравняват съответния брой символи от края на низовете, в противен случай се сравняват съответния брой символи от началото.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Претърсва низ за всички срещания, съответстващи на регулярен израз, и връща масив, съдържащ намерения израз и всеки подизраз.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Ако `$lazy` е `true`, функцията връща `Generator` вместо масив, което осигурява значителни ползи за производителността при работа с големи низове. Генераторът позволява съвпаденията да се намират постепенно, вместо да се обработва целият низ наведнъж. Това позволява ефективна работа с изключително големи входни текстове. Освен това можете да прекъснете обработката по всяко време, ако откриете желаното съвпадение, което спестява изчислително време.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/bg/validators.texy b/utils/bg/validators.texy
index 15acdcebd1..d1d45bc29c 100644
--- a/utils/bg/validators.texy
+++ b/utils/bg/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Проверява се дали елементът под ключа `$key` в полето `$array` е един от [очакваните типове |#Expected-Types], разделени със звездичка. В противен случай се изхвърля изключение [api:Nette\Utils\AssertionException]. Реда `item '%' in array` в текста на изключението може да бъде заменен с друг параметър `$label`.
 
diff --git a/utils/cs/@home.texy b/utils/cs/@home.texy
index bf462b878e..dc49180f14 100644
--- a/utils/cs/@home.texy
+++ b/utils/cs/@home.texy
@@ -8,9 +8,9 @@ V balíčku `nette/utils` najdete sadu užitečných tříd pro každodenní pou
 | [Datum a čas |datetime] | Nette\Utils\DateTime
 | [Finder] | Nette\Utils\Finder
 | [HTML elementy |html-elements] | Nette\Utils\Html
+| [Iterátory |iterables] | Nette\Utils\Iterables
 | [JSON |json] | Nette\Utils\Json
 | [Náhodné řetězce |random] | Nette\Utils\Random
-| [Objektový model |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Obrázky |images] | Nette\Utils\Image
 | [PHP reflexe |reflection] | Nette\Utils\Reflection
 | [PHP typy |type] | Nette\Utils\Type
@@ -20,6 +20,7 @@ V balíčku `nette/utils` najdete sadu užitečných tříd pro každodenní pou
 | [Řetězce |strings] | Nette\Utils\Strings
 | [Souborový systém |filesystem] | Nette\Utils\FileSystem
 | [Stránkování |paginator] | Nette\Utils\Paginator
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validátor |validators] | Nette\Utils\Validators
 
 
@@ -34,9 +35,12 @@ composer require nette/utils
 
 | verze     | kompatibilní s PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 – 8.2
-| Nette Utils 3.2 | PHP 7.2 – 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.4
 | Nette Utils 3.0 – 3.1 | PHP 7.1 – 8.0
 | Nette Utils 2.5 | PHP 5.6 – 8.0
 
 Platí pro poslední patch verze.
+
+
+Pokud aktualizujte balíček na novější verzi, podívejte se na stránku [upgrade|upgrading].
diff --git a/utils/cs/@left-menu.texy b/utils/cs/@left-menu.texy
index 94c90f1dd2..387fe25685 100644
--- a/utils/cs/@left-menu.texy
+++ b/utils/cs/@left-menu.texy
@@ -5,6 +5,7 @@ Balíček nette/utils
 - [Finder]
 - [Floats]
 - [HTML elementy |html-elements]
+- [Iterátory |iterables]
 - [JSON]
 - [Náhodné řetězce |random]
 - [Obrázky |images]
@@ -14,7 +15,8 @@ Balíček nette/utils
 - [Pole |arrays]
 - [Pomocné funkce |helpers]
 - [Řetězce |strings]
-- [SmartObject |smartobject]
+- [SmartObject]
+- [StaticClass]
 - [Souborový systém |filesystem]
 - [Validátor |validators]
 
diff --git a/utils/cs/arrays.texy b/utils/cs/arrays.texy
index de80e0c0cf..7e93b2a73d 100644
--- a/utils/cs/arrays.texy
+++ b/utils/cs/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays
 ======
 
-[api:Nette\Utils\Arrays] je statická třída obsahující užitečné funkce pro práci s poli.
+[api:Nette\Utils\Arrays] je statická třída obsahující užitečné funkce pro práci s poli. Její obdobou pro iterátory je [Nette\Utils\Iterables|iterables].
 
 Následující příklady předpokládají vytvořený alias:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Funkce flexibilně transformuje pole `$array` na asociativní pole nebo objekty podle zadané cesty `$path`. Cesta může být řetězec nebo pole. Tvoří ji názvy klíčů vstupního pole a operátory jako '[]', '->', '=', a '|'. Vyhazuje `Nette\InvalidArgumentException` v případě, že cesta je neplatná.
+
+```php
+// převod na asociativní pole podle jednoduchého klíče
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    // ...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// přiřazení hodnot z jednoho klíče k jinému s použitím operátoru =
+$result = Arrays::associate($arr, 'name=age'); // nebo ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// vytvoření objektu s použitím operátoru ->
+$result = Arrays::associate($arr, '->name'); // nebo ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// kombinace klíčů pomocí operátoru |
+$result = Arrays::associate($arr, 'name|age'); // nebo ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// přidání do pole s použitím []
+$result = Arrays::associate($arr, 'name[]'); // nebo ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,10 +76,10 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
-Testuje, zda všechny prvky v poli projdou testem implementovaným v `$callback` se signaturou `function ($value, $key, array $array): bool`.
+Testuje, zda všechny prvky v poli projdou testem implementovaným v `$predicate` se signaturou `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 30, 39, 29, 10, 13];
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Viz [#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Vrací nové pole obsahující všechny dvojice klíč-hodnota odpovídající zadanému predikátu. Callback má signaturu `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Vrátí první položku z pole nebo null, pokud je pole prázdné. Nezmění vnitřní ukazatel narozdíl od `reset()`.
+Vrátí první položku (odpovídající predikátu, je-li zadán). Pokud taková položka neexistuje, vrátí výsledek volání `$else` nebo null.
+Parametr `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`.
+
+Nezmění vnitřní ukazatel narozdíl od `reset()`. Parametry `$predicate` a `$else` existují od verze 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Viz [#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Vrací klíč první položky (odpovídající predikátu, pokud je uveden) nebo null, pokud taková položka neexistuje. Predikát `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Viz [#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Vrací prvek `$array[$key]`. Pokud neexistuje, vyhodí buď výjimku `Nette\InvalidArgumentException`, nebo je-li uveden třetí parametr `$default`, vrátí ten.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Vrátí poslední položku (odpovídající predikátu, je-li zadán). Pokud taková položka neexistuje, vrátí výsledek volání `$else` nebo null.
+Parametr `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`.
+
+Nezmění vnitřní ukazatel narozdíl od `end()`. Parametry `$predicate` a `$else` existují od verze 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Viz [#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Vrátí poslední položku z pole nebo null, pokud je pole prázdné. Nezmění vnitřní ukazatel narozdíl od `end()`.
+Vrací klíč poslední položky (odpovídající predikátu, pokud je uveden) nebo null, pokud taková položka neexistuje. Predikát `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Viz [#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Zavolá `$callback` na všechny prvky v poli a vrátí pole vrácených hodnot. Callback má signaturu `function ($value, $key, array $array): bool`.
+Zavolá `$transformer` na všechny prvky v poli a vrátí pole vrácených hodnot. Callback má signaturu `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Vytváří nové pole transformací hodnot a klíčů původního pole. Funkce `$transformer` má signaturu `function ($value, $key, array $array): ?array{$newKey, $newValue}`. Pokud `$transformer` vrátí `null`, prvek je přeskočen. Pro zachované prvky se první prvek vráceného pole použije jako nový klíč a druhý prvek jako nová hodnota.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Tato metoda je užitečná v situacích, kdy potřebujete změnit strukturu pole (klíče i hodnoty současně) nebo filtrovat prvky při transformaci (vracením null pro nežádoucí prvky).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Hodnoty z druhého pole jsou vždy přidány na konec prvního. Jako trošku matoucí se může zdát zmizení hodnoty `10` z druhého pole. Je třeba si uvědomit, že tato hodnota a stejně tak hodnota `5` v poli prvním mají přiřazený stejný numerický klíč `0`, proto ve výsledném poli je jen prvek z prvního pole.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizuje pole na asociativní pole. Numerické klíče nahradí jejich hodnotami, novou hodnotou bude `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Vrátí a odstraní hodnotu prvku z pole. Pokud neexistuje, vyhodí výjimku, nebo vrátí hodnotu `$default`, pokud je uvedena.
 
@@ -284,10 +397,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
-Testuje, zda alespoň jeden prvek v poli projde testem implementovaným v `$callback` se signaturou `function ($value, $key, array $array): bool`.
+Testuje, zda alespoň jeden prvek v poli projde testem implementovaným v `$predicate` se signaturou `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 2, 3, 4];
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Každou položku v poli přetypuje na řetězec a obalí předponou `$prefix` a příponou `$suffix`.
 
diff --git a/utils/cs/datetime.texy b/utils/cs/datetime.texy
index ea1c626e56..6b2788d3e1 100644
--- a/utils/cs/datetime.texy
+++ b/utils/cs/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Rozšiřuje [DateTime::createFromFormat()|https://www.php.net/manual/en/datetime.createfromformat.php] o možnost zadat timezone jako řetězec.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
diff --git a/utils/cs/filesystem.texy b/utils/cs/filesystem.texy
index 03a950b5e2..d1a844fffd 100644
--- a/utils/cs/filesystem.texy
+++ b/utils/cs/filesystem.texy
@@ -2,9 +2,11 @@ Souborový systém
 ****************
 
 .[perex]
-[api:Nette\Utils\FileSystem] je statická třída s užitečnými funkcemi pro práci se souborovým systémem. Jednou z výhod oproti nativním PHP funkcím je, že v případě chyb vyhazují výjimky.
+[api:Nette\Utils\FileSystem] je třída s užitečnými funkcemi pro práci se souborovým systémem. Jednou z výhod oproti nativním PHP funkcím je, že v případě chyby vyhazují výjimky.
 
 
+Pokud potřebujete hledat soubory na disku, použijte [Finder|finder].
+
 Instalace:
 
 ```shell
@@ -174,3 +176,26 @@ Převede lomítka na znaky specifické pro aktuální platformu, tj. `\` ve Wind
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Statický vs nestatický přístup
+==============================
+
+Abyste kupříkladu pro účely testování mohli třídu snadno nahradit jinou (mockem), používejte ji nestaticky:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/cs/finder.texy b/utils/cs/finder.texy
index b7748df578..1a4bbe3327 100644
--- a/utils/cs/finder.texy
+++ b/utils/cs/finder.texy
@@ -61,6 +61,8 @@ Alternativou statických metod je vytvoření instance pomocí `new Finder` (tak
 
 V masce můžete používat [zástupné znaky|#Zástupné znaky] `*`, `**`, `?` a `[...]`. Dokonce můžete specifikovat i v adresáře, například `src/*.php` vyhledá všechny PHP soubory v adresáři `src`.
 
+Symlinky jsou také považovány za adresáře nebo soubory.
+
 
 Kde se má hledat?
 -----------------
diff --git a/utils/cs/floats.texy b/utils/cs/floats.texy
index b8d71ef7e2..6616523bba 100644
--- a/utils/cs/floats.texy
+++ b/utils/cs/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Při pokusu porovnávat `NAN` vyhodí výjimku `\LogicException`.
 
+.[tip]
+Třída `Floats` toleruje rozdíly menší než `1e-10`. Pokud potřebujete pracovat s větší přesností, použijte raději knihovnu BCMath.
+
 
 Porovnávání floatů
 ==================
diff --git a/utils/cs/html-elements.texy b/utils/cs/html-elements.texy
index 4a4153962c..f3176c076e 100644
--- a/utils/cs/html-elements.texy
+++ b/utils/cs/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Další způsob pro vytvoření a vložení nového `Html` uzlu:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('první');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('první');
 // <ul><li class="first">první</li></ul>
 ```
 
diff --git a/utils/cs/images.texy b/utils/cs/images.texy
index 0e16ebff54..2b6411eebd 100644
--- a/utils/cs/images.texy
+++ b/utils/cs/images.texy
@@ -17,6 +17,8 @@ Všechny příklady předpokládají vytvořený alias:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Volitelně lze určit barvu pozadí (výchozí je černá):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Nebo obrázek načteme ze souboru:
@@ -41,17 +43,6 @@ Nebo obrázek načteme ze souboru:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Podporované formáty jsou JPEG, PNG, GIF, WebP, AVIF a BMP, nicméně musí je podporovat i vaše verze PHP (ověříte ve výpisu `phpinfo()` v sekci GD). Animace podporované nejsou.
-
-Potřebujete při načtení detekovat formát obrázku? Metoda ho vrátí v druhém parametru:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type bude Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF nebo Image::BMP
-```
-
-Samotnou detekci bez načtení obrázku provádí `Image::detectTypeFromFile()`.
-
 
 Uložení obrázku
 ===============
@@ -68,26 +59,46 @@ Můžeme určit kvalitu komprese v rozsahu 0..100 pro JPEG (výchozí 85), WEBP
 $image->save('resampled.jpg', 80); // JPEG, kvalita 80%
 ```
 
-Pokud z přípony souboru není zřejmý formát, lze ho určit jednou z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`:
+Pokud z přípony souboru není zřejmý formát, lze ho určit [konstantou|#Formáty]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Obrázek lze místo na disk zapsat do proměnné:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, kvalita 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, kvalita 80%
 ```
 
 nebo poslat přímo do prohlížeče s příslušnou HTTP hlavičkou `Content-Type`:
 
 ```php
 // odešle hlavičku Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
 ```
 
 
+Formáty
+=======
+
+Podporované formáty jsou JPEG, PNG, GIF, WebP, AVIF a BMP, nicméně musí je podporovat i vaše verze PHP, což ověříte funkcí [#isTypeSupported()]. Animace podporované nejsou.
+
+Formát představují konstanty `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` a `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
+```
+
+Potřebujete při načtení detekovat formát obrázku? Metoda ho vrátí v druhém parametru:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Samotnou detekci bez načtení obrázku provádí `Image::detectTypeFromFile()`.
+
+
 Změna velikosti
 ===============
 
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Metoda `cropAuto()` je objektovou náhradou funkce `imagecropauto()`, v [její dokumentaci|https://www.php.net/manual/en/function.imagecropauto] najdete další informace.
 
 
+Barvy .{data-version:4.0.2}
+===========================
+
+Metoda `ImageColor::rgb()` vám umožňuje definovat barvu pomocí hodnot červené, zelené a modré (RGB). Volitelně můžete také specifikovat hodnotu průhlednosti v rozmezí 0 (naprosto průhledné) až 1 (zcela neprůhledné), tedy stejně jako v CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Červená
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Poloprůhledná modrá
+```
+
+Metoda `ImageColor::hex()` umožňuje definovat barvu pomocí hexadecimálního formátu, podobně jako v CSS. Podporuje formáty `#rgb`, `#rrggbb`, `#rgba` a `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Červená
+$transparentGreen = ImageColor::hex("#00FF0080"); // Poloprůhledná zelená
+```
+
+Barvy lze použít v dalších metodách, jako třeba `ellipse()`, `fill()` atd.
+
+
 Kreslení a úpravy
 =================
 
-Můžeš kreslit, můžeš psát, ale listy netrhat. Jsou vám k dispozici všechny funkce PHP pro práci s obrázky, jako například [imagefilledellipse|https://www.php.net/manual/en/function.imagefilledellipse.php], ale v objektovém hávu:
+Můžeš kreslit, můžeš psát, ale listy netrhat. Jsou vám k dispozici všechny funkce PHP pro práci s obrázky, viz [#Přehled metod], ale v objektovém hávu:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Viz [#Přehled metod].
+Protože PHP funkce pro kreslení obdelníků jsou nepraktické kvůli určení souřadnic, nabízí třída `Image` jejich náhrady v podobě funkcí [#rectangleWH()] a [#filledRectangleWH()].
 
 
 Spojení více obrázků
@@ -200,7 +231,7 @@ Do obrázku lze snadno vložit jiný obrázek:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // souřadnice lze uvést opět v procentech
 $blank->place($logo, '80%', '80%'); // vložíme poblíž pravého dolního rohu
@@ -219,53 +250,68 @@ Přehled metod
 =============
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Vytvoří nový true color obrázek daných rozměrů. Výchozí barva je černá.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Načte obrázek ze souboru a vrací jeho typ v `$detectedFormat`. Podporované typy jsou `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`.
+Načte obrázek ze souboru a vrací jeho [typ|#Formáty] v `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Načte obrázek z řetezce a vrací jeho typ v `$detectedFormat`. Podporované typy jsou `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`.
+Načte obrázek z řetezce a vrací jeho [typ|#Formáty] v `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Vytvoří barvu, kterou lze použít v dalších metodách, jako třeba `ellipse()`, `fill()` atd.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Tuto funkci nahradila třída `ImageColor`, viz [barvy|#Barvy].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Vrátí příponu souboru pro danou konstantu `Image::XXX`.
+Vrátí příponu souboru pro daný [typ|#Formáty].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Vrátí mime type pro danou konstantu `Image::XXX`.
+Vrátí mime type pro daný [typ|#Formáty].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Vrátí typ obrázku jako konstantu `Image::XXX` podle přípony souboru.
+Vrátí [typ|#Formáty] obrázku podle přípony souboru.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Vrátí typ obrázku jako konstantu `Image::XXX` a v parametrech `$width` a `$height` také jeho rozměry.
+Vrátí [typ|#Formáty] obrázku a v parametrech `$width` a `$height` také jeho rozměry.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Vrátí typ obrázku z řetězce jako konstantu `Image::XXX` a v parametrech `$width` a `$height` také jeho rozměry.
+Vrátí [typ|#Formáty] obrázku z řetězce a v parametrech `$width` a `$height` také jeho rozměry.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Zjišťuje, zda je podporovaný daný [typ|#Formáty] obrázku.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Vrací pole podporovaných [typů|#Formáty] obrázku.
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Spočítá rozměry obdélníku, který obepne text v určitém písmu a velikosti. Vrací asociativní pole obsahující klíče `left`, `top`, `width`, `height`. Levý okraj může být i záporný, pokud text začíná levým podřezáváním.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Vraťte obrázek obsahující afinně transformovaný obraz src pomocí volitelné oblasti oříznutí. ([více |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Vrací zřetězení dvou afinních transformačních matic, což je užitečné, pokud by se na stejný obrázek mělo najednou použít více transformací. ([více |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Vrátí maticovou transformační matici. ([více |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Aktivujte kreslení vyhlazených čar a polygonů. Nepodporuje alfa kanály. Fun
 Použití antialiased primitiv s průhlednou barvou pozadí může skončit s některými neočekávanými výsledky. Metoda prolnutí používá barvu pozadí jako všechny ostatní barvy. ([více |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Nakreslí oblouk kruhu se středem v daných souřadnicích. ([více |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Nakreslí první znak `$char` do obrázku s jeho levým horním rohem na `$x`, `$y` (vlevo nahoře je 0, 0) s barvou `$color`. ([více |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Nakreslí znak `$char` svisle na určenou souřadnici na daném obrázku. ([více |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Vrací identifikátor barvy představující barvu složenou z daných komponent RGB. Musí být volána pro vytvoření každé barvy, která má být použita v obrázku. ([více |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Vrátí počet barev v obrazové paletě. ([více |https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Získá nebo nastaví průhlednou barvu v obrázku. ([více |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Ořízne obrázek do dané obdélníkové oblasti. Rozměry je možné zadávat jako integery v pixelech nebo řetězce v procentech (například `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Automaticky ořízne obrázek podle daného `$mode`. ([více |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Nakreslí elipsu se středem na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Výplní oblast počínaje danou souřadnicí (vlevo nahoře je 0, 0) s daným `$color`. ([více |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Nakreslí částečný oblouk se středem na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Nakreslí elipsu se středem na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Vytvoří v obraze vyplněný mnohoúhelník. ([více |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Vytvoří obdélník vyplněný `$color` v obrázku počínaje bodem 1 a končící bodem 2. Bod 0, 0 je levý horní roh obrázku. ([více |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Vytvoří obdélník vyplněný `$color` v obrázku počínaje bodem `$x1` & `$y1` a končící bodem `$x2` & `$y2`. Bod 0, 0 je levý horní roh obrázku. ([více |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Vytvoří obdélník vyplněný `$color` v obrázku počínaje bodem `$left` & `$top` o šířce `$width` a výšce `$height`. Bod 0, 0 je levý horní roh obrázku.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Vykreslí výplň, jejíž barva okraje je definována pomocí `$border`. Výchozím bodem výplně je `$x`, `$y` (vlevo nahoře je 0, 0) a oblast je vyplněna barvou `$color`. ([více |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Převrátí obrázek pomocí daného `$mode`. ([více |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Napište text do obrázku pomocí písem pomocí FreeType 2. ([více |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Napište text do obrázku. ([více |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Vrátí šířku obrázku.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Zapíná nebo vypíná prokládaný režim. Pokud je prokládaný režim nastaven a obrázek je uložen jako JPEG, bude uložen jako progresivní JPEG. ([více |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Nastavte příznak prolnutí alfa tak, aby používal efekty vrstvení. ([více |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Nakreslí čáru mezi dvěma danými body. ([více |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Nakreslí na obrázek otevřený mnohoúhelník. Na rozdíl od `polygon()` není mezi posledním a prvním bodem nakreslena žádná čára. ([více |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Zkopíruje `$image` do obrázku na souřadnice `$left` a `$top`. Souřadnice je možné zadávat jako integery v pixelech nebo řetězce v procentech (například `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Vytvoří v obrazu mnohoúhelník. ([více |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Vytvoří obdélník na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Vytvoří obdélník na zadaných souřadnicích.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Změní velikost obrázku, [více informací|#Změna velikosti]. Rozměry je možné zadávat jako integery v pixelech nebo řetězce v procentech (například `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Nastaví nebo vrátí rozlišení obrázku v DPI (tečky na palec). Pokud není zadán žádný z volitelných parametrů, je aktuální rozlišení vráceno jako indexované pole. Pokud je zadáno pouze `$resX`, horizontální a vertikální rozlišení se nastaví na tuto hodnotu. Pokud jsou zadány oba volitelné parametry, horizontální a vertikální rozlišení se nastaví na tyto hodnoty.
 
 Rozlišení se používá pouze jako meta informace, když jsou obrázky čteny a zapisovány do formátů podporujících tento druh informací (aktuálně PNG a JPEG). Nemá to vliv na žádné operace kreslení. Výchozí rozlišení nových snímků je 96 DPI. ([více |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Otočí obrázek pomocí zadaného `$angle` ve stupních. Střed otáčení je s
 Vyžaduje přítomnost *Bundled GD extension*, nemusí tedy fungovat všude.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Uloží obrázek do souboru.
 
-Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Pokud typ není zřejmý z přípony souboru, můžete jej zadat pomocí jedné z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`.
+Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Pokud typ není zřejmý z přípony souboru, můžete jej zadat pomocí jedné z konstant `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Měřítko obrázku pomocí daného interpolačního algoritmu. ([více |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Vypíše obrázek do prohlížeče.
 
-Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Typ je jednou z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`.
+Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Nastaví metodu interpolace, která ovlivní metody `rotate()` a `affine()`. ([více |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Nakreslí pixel na zadané souřadnici. ([více |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Doostří obrázek.
 Vyžaduje přítomnost *Bundled GD extension*, nemusí tedy fungovat všude.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Vypíše řetězec na zadané souřadnice. ([více |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Vypíše řetězec svisle na dané souřadnice. ([více |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Uloží obrázek do řetezce.
 
-Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Typ je jednou z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`.
+Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Převede obraz truecolor na paletový. ([více |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Vypíše daný text do obrázku pomocí písem TrueType. ([více |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Vypíše daný text do obrázku. ([více |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/cs/iterables.texy b/utils/cs/iterables.texy
new file mode 100644
index 0000000000..77af7696df
--- /dev/null
+++ b/utils/cs/iterables.texy
@@ -0,0 +1,170 @@
+Práce s iterátory
+*****************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] je statická třída s funkcemi pro práci s iterátory. Její obdobou pro pole je [Nette\Utils\Arrays|arrays].
+
+
+Instalace:
+
+```shell
+composer require nette/utils
+```
+
+Všechny příklady předpokládají vytvořený alias:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Hledá zadanou hodnotu v iterátoru. Používá striktní porovnání (`===`) pro ověření shody. Vrací `true`, pokud je hodnota nalezena, jinak `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Tato metoda je užitečná, když potřebujete rychle zjistit, zda se konkrétní hodnota v iterátoru nachází, aniž byste museli procházet všechny prvky ručně.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Hledá zadaný klíč v iterátoru. Používá striktní porovnání (`===`) pro ověření shody. Vrací `true`, pokud je klíč nalezen, jinak `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Ověřuje, zda všechny prvky iterátoru splňují podmínku definovanou v `$predicate`. Funkce `$predicate` má signaturu `function ($value, $key, iterable $iterable): bool` a musí vracet `true` pro každý prvek, aby metoda `every()` vrátila `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Tato metoda je užitečná pro ověření, zda všechny prvky v kolekci splňují určitou podmínku, například zda jsou všechna čísla menší než určitá hodnota.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Vytváří nový iterátor, který obsahuje pouze ty prvky z původního iterátoru, které splňují podmínku definovanou v `$predicate`. Funkce `$predicate` má signaturu `function ($value, $key, iterable $iterable): bool` a musí vracet `true` pro prvky, které mají být zachovány.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Metoda využívá generátor, což znamená, že filtrování probíhá postupně při procházení výsledku. To je efektivní z hlediska paměti a umožňuje zpracovávat i velmi velké kolekce. Pokud neprojdete všechny prvky výsledného iterátoru, ušetříte výpočetní výkon, protože se nezpracují všechny prvky původního iterátoru.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Vrací první prvek iterátoru. Pokud je zadán `$predicate`, vrací první prvek, který splňuje danou podmínku. Funkce `$predicate` má signaturu `function ($value, $key, iterable $iterable): bool`. Pokud není nalezen žádný vyhovující prvek, volá se funkce `$else` (pokud je zadána) a vrací se její výsledek. Pokud `$else` není zadáno, vrací se `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Tato metoda je užitečná, když potřebujete rychle získat první prvek kolekce nebo první prvek splňující určitou podmínku, aniž byste museli procházet celou kolekci ručně.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Vrací klíč prvního prvku iterátoru. Pokud je zadán `$predicate`, vrací klíč prvního prvku, který splňuje danou podmínku. Funkce `$predicate` má signaturu `function ($value, $key, iterable $iterable): bool`. Pokud není nalezen žádný vyhovující prvek, volá se funkce `$else` (pokud je zadána) a vrací se její výsledek. Pokud `$else` není zadáno, vrací se `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Vytváří nový iterátor aplikováním funkce `$transformer` na každý prvek původního iterátoru. Funkce `$transformer` má signaturu `function ($value, $key, iterable $iterable): mixed` a její návratová hodnota se použije jako nová hodnota prvku.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Metoda využívá generátor, což znamená, že transformace probíhá postupně při procházení výsledku. To je efektivní z hlediska paměti a umožňuje zpracovávat i velmi velké kolekce. Pokud neprojdete všechny prvky výsledného iterátoru, ušetříte výpočetní výkon, protože se nezpracují všechny prvky původního iterátoru.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Vytváří nový iterátor transformací hodnot a klíčů původního iterátoru. Funkce `$transformer` má signaturu `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Pokud `$transformer` vrátí `null`, prvek je přeskočen. Pro zachované prvky se první prvek vráceného pole použije jako nový klíč a druhý prvek jako nová hodnota.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Stejně jako `map()`, tato metoda využívá generátor pro postupné zpracování a efektivní práci s pamětí. To umožňuje pracovat s velkými kolekcemi a šetřit výpočetní výkon při částečném průchodu výsledkem.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Vytváří obal kolem iterátoru, který během iterace ukládá do mezipaměti jeho klíče a hodnoty. To umožňuje opakovanou iteraci dat bez nutnosti znovu procházet původní zdroj dat.
+
+```php
+$iterator = /* data, která nelze iterovat vícekrát */
+$memoized = Iterables::memoize($iterator);
+// Nyní můžete iterovat $memoized vícekrát bez ztráty dat
+```
+
+Tato metoda je užitečná v situacích, kdy potřebujete vícekrát projít stejnou sadu dat, ale původní iterátor neumožňuje opakovanou iteraci nebo by opakované procházení bylo nákladné (např. při čtení dat z databáze nebo souboru).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Ověřuje, zda alespoň jeden prvek iterátoru splňuje podmínku definovanou v `$predicate`. Funkce `$predicate` má signaturu `function ($value, $key, iterable $iterable): bool` a musí vracet `true` pro alespoň jeden prvek, aby metoda `some()` vrátila `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Tato metoda je užitečná pro rychlé ověření, zda v kolekci existuje alespoň jeden prvek splňující určitou podmínku, například zda kolekce obsahuje alespoň jedno sudé číslo.
+
+Viz [#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Převádí jakýkoliv iterovatelný objekt (array, Traversable) na Iterator. Pokud je vstup již Iterator, vrátí ho beze změny.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Nyní máte Iterator místo pole
+```
+
+Tato metoda je užitečná, když potřebujete zajistit, že máte k dispozici Iterator, bez ohledu na typ vstupních dat. To může být užitečné při vytváření funkcí, které pracují s různými typy iterovatelných dat.
diff --git a/utils/cs/json.texy b/utils/cs/json.texy
index 4d8cf928a5..e35420ef55 100644
--- a/utils/cs/json.texy
+++ b/utils/cs/json.texy
@@ -77,7 +77,7 @@ Nastavení `$forceArray` vynutí vrácení polí místo objektů:
 
 ```php
 Json::decode('{"variable": true}'); // vrací objekt typu stdClass
-Json::decode('{"variable": true}', forceArray: true); // vrací pole
+Json::decode('{"variable": true}', forceArrays: true); // vrací pole
 ```
 
 Při chybě vyhazuje výjimku `Nette\Utils\JsonException`.
diff --git a/utils/cs/smartobject.texy b/utils/cs/smartobject.texy
index 63cc12a241..7aeca5b7b2 100644
--- a/utils/cs/smartobject.texy
+++ b/utils/cs/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject a StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject přidává PHP třídám podporu pro tzv. *property*. StaticClass slouží pro označení statických tříd.
+SmartObject opravovala chování objektů v mnoha směrech, ale dnešní PHP již obsahuje většinu vylepšení nativně. Stále však přidává podporu pro tzv. *property*.
 
 
 Instalace:
@@ -65,25 +65,10 @@ echo $circle->visible; // volá isVisible()
 Properties jsou především "syntaktickým cukříkem"((syntactic sugar)), jehož smyslem je zpřehlednit kód a osladit tak programátorovi život. Pokud nechcete, nemusíte je používat.
 
 
-Statické třídy
-==============
-
-Statické třídy, tedy třídy, které nejsou určené k vytváření instancí, můžete označit traitou `Nette\StaticClass`:
-
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Při pokusu o vytvoření instance se vyhodí výjimka `Error` s informací, že uvedená třída je statická.
-
-
 Pohled do historie
 ==================
 
-SmartObject dříve vylepšovala a opravovala chování tříd v mnoha směrech, ale díky vývoji PHP se většina původních funkcí stala zbytečnou. Následující text je tak pohledem do historie, jak se věci vyvíjely.
+SmartObject opravovala chování objektů v mnoha směrech, ale dnešní PHP již obsahuje většinu vylepšení nativně. Následující text je tak nostalgickým pohledem do historie a připomínkou toho, jak se věci vyvíjely.
 
 Objektový model PHP trpěl od počátku celou řadou vážných nedostatků a necnostní. To byl důvod vzniku třídy `Nette\Object` (v roce 2007), která se je pokoušela napravovat a zlepšit komfort při používání PHP. Stačilo, aby ostatní třídy od ní dědily, a získaly výhody, které přinášela. Když PHP 5.4 přišlo s podporou trait, byla třída `Nette\Object` nahrazena traitou `Nette\SmartObject`. Nebylo tak nutné už dědit od společného předka. Navíc traita se dala použít i ve třídách, které již dědily od jiné třídy. Definitivní konec `Nette\Object` přišel s vydáním PHP 7.2, které zakázalo třídám jmenovat se `Object`.
 
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // vrátí 'John Doe
+$reflection->getAnnotation('author'); // vrátí 'John Doe'
 ```
 
 Od PHP 8.0 je možné přistupovat k metainformacím v podobě atributů:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/cs/staticclass.texy b/utils/cs/staticclass.texy
new file mode 100644
index 0000000000..ea757f58f9
--- /dev/null
+++ b/utils/cs/staticclass.texy
@@ -0,0 +1,21 @@
+Statické třídy
+**************
+
+.[perex]
+StaticClass slouží pro označení statických tříd.
+
+
+Instalace:
+
+```shell
+composer require nette/utils
+```
+
+Statické třídy, tedy třídy, které nejsou určené k vytváření instancí, můžete označit traitou [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/cs/strings.texy b/utils/cs/strings.texy
index 18eb2fcd7b..83d63a73d2 100644
--- a/utils/cs/strings.texy
+++ b/utils/cs/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Upraví UTF-8 řetězec do tvaru používaného v URL, tj. odstraní diakritiku a všechny znaky, kromě písmen anglické abecedy a číslic, nahradí spojovníkem.
 
@@ -129,8 +129,8 @@ Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
 Vyžaduje PHP rozšíření `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Ořízne mezery (nebo jiné znaky určené druhým parametrem) ze začátku a konce UTF-8 řetězce.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Vrátí část UTF-8 řetězce `$s` zadanou počáteční pozicí `$start` a délkou `$length`. Pokud je `$start` záporný, bude vrácený řetězec začínat znakem -`$start` znakem od konce.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Používejte nativní `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Porovnání dvou UTF-8 řetězců nebo jejich částí bez ohledu na velikost písmen. Pokud `$length` obsahuje null, porovnávají se celé řetězce, pokud je záporný, porovnává se příslušný počet znaků od konce řetězců, jinak se porovnává příslušný počet znaků od začátku.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Hledá v řetězci všechny výskyty odpovídající regulárnímu výrazu a vrátí pole polí s nalezeným výrazem a jednotlivými podvýrazy.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Pokud `$lazy` je `true`, funkce vrací `Generator` místo pole, což přináší významné výkonnostní výhody při práci s velkými řetězci. Generátor umožňuje vyhledávat shody postupně, místo celého řetězce najednou. To umožňuje efektivně pracovat i s extrémně velkými vstupními texty. Navíc můžete kdykoliv přerušit zpracování, pokud najdete hledanou shodu, což šetří výpočetní čas.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Nalezeno: $match[0]\n";
+    // Zpracování může být kdykoli přerušeno
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/cs/upgrading.texy b/utils/cs/upgrading.texy
new file mode 100644
index 0000000000..e69260c8f7
--- /dev/null
+++ b/utils/cs/upgrading.texy
@@ -0,0 +1,34 @@
+Upgrade
+*******
+
+
+Přechod z verze 3.x na 4.0
+==========================
+
+Minimální požadovaná verze PHP je 8.0.
+
+Třída `Nette\Utils\Reflection` poskytovala metody pro práci s typy `getParameterType()`, `getPropertyType()` a `getReturnType()`. Metody vznikly v době, kdy PHP nemělo union, intersection nebo nejnovější disjunctive normal form typy, se kterými už nefungují a nahradila je [třída Type |utils:type]. Od verze 4.0 jsou tyto metody odstraněné.
+
+Metoda `Nette\Utils\Reflection::getParameterDefaultValue()` je deprecated, protože nativní `ReflectionParameter::getDefaultValue()` už funguje správně.
+
+Zrušená je proměnná `Nette\Utils\Html::$xhtml`.
+
+
+Finder
+------
+
+Finder se přestěhoval do balíčku `nette/utils`, původní odstraňte:
+
+```shell
+composer remove nette/finder
+```
+
+Na Linuxu se nově chová v režimu case-sensitive.
+
+V předchozí verzi platilo, že metody `exclude()` a `filter()` fungovaly jinak, když byly zavolány **před** `from()` resp. `in()` a **po** ní. Tohle už neplatí, `exclude()` a `filter()` fungují vždy stejně. Dřívější `filter()` volaný *až po* nahradila nová metoda `descentFilter()`.
+
+Finder již neimplementuje rozhraní Countable.
+
+Řetězec začínající lomítkem ve `Finder::findFiles('/f*')` se nově považuje za absolutní cestu, je potřeba ho nahradit např. za `Finder::findFiles('./f*')`.
+
+Pokud adresář, ve kterém hledáte, neexistuje, vyhodí se `Nette\InvalidStateException` (místo `UnexpectedValueException`).
diff --git a/utils/cs/validators.texy b/utils/cs/validators.texy
index f29e003c3f..6be0c1a0bd 100644
--- a/utils/cs/validators.texy
+++ b/utils/cs/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Ověřuje, zda prvek pod klíčem `$key` v poli `$array` je jedním z [očekávaných typů|#Očekávané typy] oddělených svislítkem. Pokud ne, vyhodí výjimku [api:Nette\Utils\AssertionException]. Řetězec `item '%' in array` v textu výjimky lze nahradit za jiný parametrem `$label`.
 
diff --git a/utils/de/@home.texy b/utils/de/@home.texy
index a0eb54a00f..ce02f3392e 100644
--- a/utils/de/@home.texy
+++ b/utils/de/@home.texy
@@ -13,13 +13,14 @@ Im Paket `nette/utils` finden Sie eine Reihe von nützlichen Klassen für den t
 | [Generieren von HTML-Code |html-elements] | Nette\Utils\Html
 | [Helferfunktionen |helpers] | Nette\Utils\Helfer
 | [JSON] | Nette\Utils\Json
-| [Objektmodell |smartobject] | Nette\SmartObject & Nette\StaticClass
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [Paginator] | Nette\Utils\Paginator
 | [PHP-Reflexion |reflection] | Nette\Utils\Reflexion
 | [Rückruf |Callback] | Nette\Utils\Callback
 | [Typen |type] | Nette\Utils\Type
 | [Validatoren |Validators] | Nette\Utils\Validatoren
 | [Zeichenketten |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Zufällige Zeichenketten generieren |random] | Nette\Utils\Random
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | Version | kompatibel mit PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.3
+| Nette Utils 3.2 | PHP 7.2 – 8.4
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/de/@left-menu.texy b/utils/de/@left-menu.texy
index f820e0f6ce..e94adaa3c3 100644
--- a/utils/de/@left-menu.texy
+++ b/utils/de/@left-menu.texy
@@ -8,13 +8,15 @@ Paket nette/utils
 - [Finder]
 - [Floats]
 - [Hilfsfunktionen |helpers]
+- [Iterabilien |iterables]
 - [HTML-Elemente |HTML Elements]
 - [JSON]
 - [Paginator |paginator]
 - [PHP-Reflexion |reflection]
 - [PHP Typen |type]
-- [SmartObject]
 - [Strings]
+- [SmartObject]
+- [StaticClass]
 - [Validatoren |validators]
 - [Zufällige Zeichenketten |random]
 
diff --git a/utils/de/arrays.texy b/utils/de/arrays.texy
index 7aea115b2e..9b7a2b8b77 100644
--- a/utils/de/arrays.texy
+++ b/utils/de/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] ist eine statische Klasse, die eine Handvoll praktischer Array-Funktionen enthält.
+[api:Nette\Utils\Arrays] ist eine statische Klasse, die eine Handvoll praktischer Array-Funktionen enthält. Ihre Entsprechung für Iteratoren ist [Nette\Utils\Iterables |iterables].
 
 Die folgenden Beispiele setzen voraus, dass der folgende Klassenalias definiert ist:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Die Funktion wandelt die `$array` flexibel in ein assoziatives Array oder Objekte entsprechend dem angegebenen Pfad `$path` um. Der Pfad kann eine Zeichenkette oder ein Array sein. Er besteht aus den Namen der Schlüssel im Eingabe-Array und Operatoren wie '[]', '->', '=' und '|'. Wirft `Nette\InvalidArgumentException`, wenn der Pfad ungültig ist.
+
+```php
+// Umwandlung in ein assoziatives Array unter Verwendung eines einfachen Schlüssels
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// Zuweisung von Werten von einem Schlüssel zu einem anderen mit dem Operator =
+$result = Arrays::associate($arr, 'name=age'); // oder ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// Erstellen eines Objekts mit dem ->-Operator
+$result = Arrays::associate($arr, '->name'); // oder ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// Schlüssel mit dem Operator | kombinieren
+$result = Arrays::associate($arr, 'name|age'); // oder ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// Hinzufügen zu einem Array mit []
+$result = Arrays::associate($arr, 'name[]'); // oder ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Prüft, ob alle Elemente im Array den Test bestehen, der von der angegebenen Funktion mit der Signatur `function ($value, $key, array $array): bool` implementiert wird.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Siehe [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Gibt ein neues Array zurück, das alle Schlüssel-Wert-Paare enthält, die mit dem angegebenen `$predicate` übereinstimmen. Der Callback hat die Signatur `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Gibt das erste Element aus dem Array zurück oder null, wenn Array leer ist. Im Gegensatz zu `reset()` wird der interne Zeiger nicht verändert.
+Gibt das erste Element zurück (das dem angegebenen Prädikat entspricht, falls angegeben). Wenn es kein solches Element gibt, wird das Ergebnis des Aufrufs von `$else` oder null zurückgegeben.
+ `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`.
+
+Im Gegensatz zu `reset()` wird der interne Zeiger nicht verändert. Die Parameter `$predicate` und `$else` gibt es seit Version 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Siehe [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Gibt den Schlüssel des ersten Elements zurück (das mit dem angegebenen Prädikat übereinstimmt, falls gegeben) oder null, wenn es kein solches Element gibt. `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Siehe [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Gibt `$array[$key]` Element. Wenn es nicht existiert, wird `Nette\InvalidArgumentException` ausgelöst, es sei denn, ein Standardwert wird als drittes Argument angegeben.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Gibt das letzte Element zurück (das dem angegebenen Prädikat entspricht, falls angegeben). Wenn es kein solches Element gibt, wird das Ergebnis des Aufrufs von `$else` oder null zurückgegeben.
+ `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`.
+
+Im Gegensatz zu `end()` wird der interne Zeiger nicht verändert. Die Parameter `$predicate` und `$else` gibt es seit Version 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Siehe [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Gibt das letzte Element des Arrays zurück oder null, wenn das Array leer ist. Im Gegensatz zu `end()` wird der interne Zeiger nicht verändert.
+Gibt den Schlüssel des letzten Elements zurück (das mit dem angegebenen Prädikat übereinstimmt, falls angegeben) oder null, wenn es kein solches Element gibt. `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Siehe [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Ruft `$callback` für alle Elemente im Array auf und gibt das Array der Rückgabewerte zurück. Der Callback hat die Signatur `function ($value, $key, array $array): bool`.
+Ruft `$transformer` für alle Elemente im Array auf und gibt das Array der Rückgabewerte zurück. Der Callback hat die Signatur `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Erzeugt ein neues Array durch Umwandlung der Werte und Schlüssel des ursprünglichen Arrays. Die Funktion `$transformer` hat die Signatur `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Wenn `$transformer` `null` zurückgibt, wird das Element übersprungen. Bei beibehaltenen Elementen wird das erste Element des zurückgegebenen Arrays als neuer Schlüssel und das zweite Element als neuer Wert verwendet.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Diese Methode ist in Situationen nützlich, in denen Sie die Struktur eines Arrays (Schlüssel und Werte gleichzeitig) ändern oder Elemente während der Transformation filtern müssen (indem Sie für unerwünschte Elemente null zurückgeben).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Werte aus dem zweiten Array werden immer an das erste angehängt. Das Verschwinden des Wertes `10` aus dem zweiten Array mag ein wenig verwirrend erscheinen. Es sollte beachtet werden, dass dieser Wert sowie der Wert `5` in the first array have the same numeric key `0`, also im resultierenden Feld nur ein Element aus dem ersten Array vorhanden ist.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalisiert ein Array zu einem assoziativen Array. Ersetzen Sie numerische Schlüssel durch ihre Werte, der neue Wert wird `$filling` sein.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Liefert und entfernt den Wert eines Elements aus einem Array. Wenn es nicht existiert, wird eine Exception geworfen oder `$default` zurückgegeben, falls angegeben.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Prüft, ob mindestens ein Element im Array den Test besteht, der durch den angegebenen Callback mit der Signatur `function ($value, $key, array $array): bool` implementiert wird.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Jedes Element des Arrays wird in einen String umgewandelt und mit `$prefix` und `$suffix` umschlossen.
 
diff --git a/utils/de/datetime.texy b/utils/de/datetime.texy
index 18d573bc6b..d2f5776e62 100644
--- a/utils/de/datetime.texy
+++ b/utils/de/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Extends [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] with the ability to specify a timezone as a string.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // Erstellung mit benutzerdefinierter Zeitzone
diff --git a/utils/de/filesystem.texy b/utils/de/filesystem.texy
index be0bd14ff5..dde00658a2 100644
--- a/utils/de/filesystem.texy
+++ b/utils/de/filesystem.texy
@@ -2,9 +2,11 @@ Dateisystem-Funktionen
 **********************
 
 .[perex]
-[api:Nette\Utils\FileSystem] ist eine statische Klasse, die nützliche Funktionen für die Arbeit mit einem Dateisystem enthält. Ein Vorteil gegenüber nativen PHP-Funktionen ist, dass sie im Fehlerfall Ausnahmen auslösen.
+[api:Nette\Utils\FileSystem] ist eine Klasse, die nützliche Funktionen für die Arbeit mit einem Dateisystem enthält. Ein Vorteil gegenüber nativen PHP-Funktionen ist, dass sie im Fehlerfall Ausnahmen auslösen.
 
 
+Wenn Sie nach Dateien auf dem Datenträger suchen müssen, verwenden Sie den [Finder |finder].
+
 Installation:
 
 ```shell
@@ -174,3 +176,26 @@ Konvertiert Schrägstriche in Zeichen, die für die aktuelle Plattform spezifisc
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Statischer vs. nicht-statischer Ansatz .[#toc-static-vs-non-static-approach]
+============================================================================
+
+Um die Klasse `FileSystem` einfach durch eine andere Klasse zu ersetzen, z. B. zu Testzwecken, verwenden Sie sie nicht-statisch:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/de/finder.texy b/utils/de/finder.texy
index 0964f17a52..5970de6800 100644
--- a/utils/de/finder.texy
+++ b/utils/de/finder.texy
@@ -61,6 +61,8 @@ Eine Alternative zu statischen Methoden besteht darin, mit `new Finder` eine Ins
 
 Sie können [Wildcards |#wildcards] `*`, `**` verwenden, `?` and `[...]` in der Maske verwenden. Sie können sogar Verzeichnisse angeben, z. B. `src/*.php` sucht nach allen PHP-Dateien im Verzeichnis `src`.
 
+Symlinks werden auch als Verzeichnisse oder Dateien betrachtet.
+
 
 Wo soll gesucht werden? .[#toc-where-to-search]
 -----------------------------------------------
diff --git a/utils/de/floats.texy b/utils/de/floats.texy
index 89fe22cfa3..31d68bc1ea 100644
--- a/utils/de/floats.texy
+++ b/utils/de/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'gleich' : 'nicht gleich'; // gleich
 
 Beim Versuch, `NAN` zu vergleichen, kommt es zu einer `\LogicException` Ausnahme.
 
+.[tip]
+Die Klasse `Floats` toleriert Unterschiede, die kleiner sind als `1e-10`. Wenn Sie mit größerer Genauigkeit arbeiten müssen, verwenden Sie stattdessen die BCMath-Bibliothek.
+
 
 Float-Vergleich .[#toc-float-comparison]
 ========================================
diff --git a/utils/de/html-elements.texy b/utils/de/html-elements.texy
index 695a3f416e..50974caa0f 100644
--- a/utils/de/html-elements.texy
+++ b/utils/de/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Eine andere Möglichkeit, einen neuen `Html` Knoten zu erstellen und einzufügen:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/de/images.texy b/utils/de/images.texy
index 30354d6095..2f913e5f65 100644
--- a/utils/de/images.texy
+++ b/utils/de/images.texy
@@ -17,6 +17,8 @@ Die folgenden Beispiele gehen davon aus, dass der folgende Klassenalias definier
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Optional können Sie eine Hintergrundfarbe angeben (Standard ist schwarz):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Oder wir laden das Bild aus einer Datei:
@@ -41,17 +43,6 @@ Oder wir laden das Bild aus einer Datei:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Unterstützte Formate sind JPEG, PNG, GIF, WebP, AVIF und BMP, aber Ihre PHP-Version muss diese Formate ebenfalls unterstützen (siehe `phpinfo()`, Abschnitt GD). Animationen werden nicht unterstützt.
-
-Müssen Sie das Bildformat beim Laden erkennen? Die Methode gibt das Format im zweiten Parameter zurück:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type ist Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF oder Image::BMP
-```
-
-Nur die Erkennung ohne Laden des Bildes wird von `Image::detectTypeFromFile()` durchgeführt.
-
 
 Speichern Sie das Bild .[#toc-save-the-image]
 =============================================
@@ -68,25 +59,45 @@ Wir können die Komprimierungsqualität im Bereich 0..100 für JPEG (Standard 85
 $image->save('resampled.jpg', 80); // JPEG, Qualität 80%
 ```
 
-Wenn das Format nicht aus der Dateierweiterung ersichtlich ist, kann es durch eine der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP` angegeben werden:
+Wenn das Format nicht aus der Dateierweiterung ersichtlich ist, kann es durch eine [Konstante |#Formats] angegeben werden:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Das Bild kann in eine Variable statt auf die Festplatte geschrieben werden:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, Qualität 80%.
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, Qualität 80%.
 ```
 
 oder direkt an den Browser mit dem entsprechenden HTTP-Header `Content-Type` senden:
 
 ```php
 // sendet Kopfzeile Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formate .[#toc-formats]
+=======================
+
+Unterstützte Formate sind JPEG, PNG, GIF, WebP, AVIF, und BMP. Sie müssen jedoch auch von Ihrer PHP-Version unterstützt werden, was mit der Funktion [isTypeSupported() |#isTypeSupported()] überprüft werden kann. Animationen werden nicht unterstützt.
+
+Die Formate werden durch die Konstanten `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, und `ImageType::BMP` dargestellt.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Müssen Sie das Format eines Bildes beim Laden erkennen? Die Methode gibt es im zweiten Parameter zurück:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Die eigentliche Erkennung ohne Laden des Bildes wird von `Image::detectTypeFromFile()` durchgeführt.
+
 
 Bildgröße ändern .[#toc-image-resize]
 =====================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Die Methode `cropAuto()` ist eine Objektkapselung der Funktion `imagecropauto()`, weitere Informationen finden Sie in der [zugehörigen Dokumentation |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Farben .[#toc-colors]
+=====================
+
+Mit der Methode `ImageColor::rgb()` können Sie eine Farbe anhand von Rot-, Grün- und Blauwerten (RGB) definieren. Optional können Sie auch einen Transparenzwert angeben, der von 0 (völlig transparent) bis 1 (völlig undurchsichtig) reicht, genau wie in CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Mit der Methode `ImageColor::hex()` können Sie eine Farbe im Hexadezimalformat definieren, ähnlich wie in CSS. Sie unterstützt die Formate `#rgb`, `#rrggbb`, `#rgba` und `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Farben können auch in anderen Methoden verwendet werden, z. B. `ellipse()`, `fill()`, usw.
+
+
 Zeichnen und Editieren .[#toc-drawing-and-editing]
 ==================================================
 
-Sie können zeichnen, Sie können schreiben, Sie können alle PHP-Funktionen für die Arbeit mit Bildern verwenden, wie z.B. [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], aber im Objektstil:
+Sie können zeichnen, Sie können schreiben, Sie können alle PHP-Funktionen zur Bildmanipulation verwenden, siehe [Übersicht der Methoden |#Overview of methods], aber in einem objektorientierten Wrapper:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Siehe [Überblick über die Methoden |#Overview of Methods].
+Da PHP-Funktionen zum Zeichnen von Rechtecken aufgrund der Angabe von Koordinaten unpraktisch sind, bietet die Klasse `Image` deren Ersatz in Form der Funktionen [rectangleWH() |#rectangleWH()] und [filledRectangleWH() |#filledRectangleWH()].
 
 
 Mehrere Bilder zusammenführen .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Sie können problemlos ein anderes Bild in das Bild einfügen:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // Koordinaten können auch in Prozent angegeben werden
 $blank->place($logo, '80%', '80%'); // in der Nähe der rechten unteren Ecke
@@ -219,53 +250,68 @@ Eine solche API ist wirklich ein Vergnügen, nicht wahr?
 =======================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Erzeugt ein neues Echtfarbbild mit den angegebenen Abmessungen. Die Standardfarbe ist Schwarz.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Liest ein Bild aus einer Datei und gibt seinen Typ in `$detectedFormat` zurück. Die unterstützten Typen sind `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP`.
+Liest ein Bild aus einer Datei und gibt seinen [Typ |#Formats] in `$detectedFormat` zurück.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Liest ein Bild aus einer Zeichenkette und gibt seinen Typ in `$detectedFormat` zurück. Die unterstützten Typen sind `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, und `Image::BMP`.
+Liest ein Bild aus einer Zeichenkette und gibt dessen [Typ |#Formats] in `$detectedFormat` zurück.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Erzeugt eine Farbe, die in anderen Methoden verwendet werden kann, z. B. `ellipse()`, `fill()`, usw.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Diese Funktion wurde durch die Klasse `ImageColor` ersetzt, siehe [Farben |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Gibt die Dateierweiterung für die angegebene Konstante `Image::XXX` zurück.
+Gibt die Dateierweiterung für den angegebenen [Typ |#Formats] zurück.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Gibt den Mime-Typ für die angegebene Konstante `Image::XXX` zurück.
+Gibt den Mime-Typ für den angegebenen [Typ |#Formats] zurück.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Gibt den Bildtyp als Konstante `Image::XXX` entsprechend der Dateierweiterung zurück.
+Gibt den [Bildtyp |#Formats] entsprechend der Dateierweiterung zurück.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Gibt den Typ der Bilddatei als Konstante `Image::XXX` zurück und in den Parametern `$width` und `$height` auch ihre Abmessungen.
+Gibt den [Typ |#Formats] der Bilddatei und in den Parametern `$width` und `$height` auch die Abmessungen zurück.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Gibt den Typ des Bildes von string als `Image::XXX` Konstante zurück und in den Parametern `$width` und `$height` auch seine Abmessungen.
+Gibt den [Typ |#Formats] des Bildes aus der Zeichenkette zurück und in den Parametern `$width` und `$height` auch seine Abmessungen.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Ermittelt, ob der angegebene [Bildtyp |#Formats] unterstützt wird.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Gibt ein Array der unterstützten Bildtypen zurück (Konstanten `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Berechnet die Abmessungen des Rechtecks, das den Text in einer bestimmten Schriftart und -größe umschließt. Sie gibt ein assoziatives Array zurück, das die Schlüssel `left`, `top`, `width`, `height` enthält. Der linke Rand kann negativ sein, wenn der Text mit einem linken Überhang beginnt.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Gibt ein Bild zurück, das das affin transformierte Ausgangsbild enthält, wobei ein optionaler Beschneidungsbereich verwendet wird. ([mehr |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Gibt die Verkettung von zwei affinen Transformationsmatrizen zurück, was nützlich ist, wenn mehrere Transformationen in einem Durchgang auf dasselbe Bild angewendet werden sollen. ([mehr |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Gibt eine affine Transformationsmatrix zurück. ([mehr |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Aktivieren Sie die Methoden zum schnellen Zeichnen von Linien und verdrahteten P
 Die Verwendung von Primitiven mit Antialiasing und transparenter Hintergrundfarbe kann zu unerwarteten Ergebnissen führen. Bei der Mischmethode wird die Hintergrundfarbe wie jede andere Farbe verwendet. Die fehlende Unterstützung von Alphakomponenten erlaubt keine alphabasierte Antialiasing-Methode. ([mehr |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Zeichnet einen Kreisbogen, dessen Mittelpunkt die angegebenen Koordinaten sind. ([mehr |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Zeichnet das erste Zeichen von `$char` im Bild mit seiner oberen linken Seite auf `$x`,`$y` (oben links ist 0, 0) mit der Farbe `$color`. ([mehr |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Zeichnet das Zeichen `$char` vertikal an der angegebenen Koordinate auf dem angegebenen Bild. ([mehr |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Gibt einen Farbbezeichner zurück, der die aus den angegebenen RGB-Komponenten zusammengesetzte Farbe darstellt. Sie muss aufgerufen werden, um jede Farbe, die im Bild verwendet werden soll, zu erzeugen. ([mehr |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Gibt die Anzahl der Farben in einer Bildpalette zurück ([mehr |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Liest oder setzt die transparente Farbe des Bildes. ([mehr |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Beschneidet ein Bild auf den angegebenen rechteckigen Bereich. Die Abmessungen können als ganze Zahlen in Pixeln oder als Strings in Prozent (z. B. `'50%'`) übergeben werden.
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Beschneidet ein Bild automatisch entsprechend der angegebenen `$mode`. ([mehr |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Zeichnet eine Ellipse, deren Mittelpunkt die angegebenen Koordinaten sind. ([mehr |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Führt eine Flutfüllung durch, beginnend an der angegebenen Koordinate (oben links ist 0, 0) mit der angegebenen `$color` im Bild. ([mehr |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Zeichnet einen Teilbogen, der auf die angegebene Koordinate im Bild zentriert ist. ([mehr |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Zeichnet eine Ellipse, deren Mittelpunkt die angegebene Koordinate im Bild ist. ([mehr |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Erzeugt ein gefülltes Polygon im $image. ([mehr |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Erzeugt ein Rechteck, das im Bild mit `$color` gefüllt ist und bei Punkt 1 beginnt und bei Punkt 2 endet. 0, 0 ist die linke obere Ecke des Bildes. ([mehr |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Erzeugt ein mit `$color` gefülltes Rechteck im Bild, das bei `$x1` & `$y1` beginnt und bei `$x2` & `$y2` endet. Punkt 0, 0 ist die linke obere Ecke des Bildes. ([mehr |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Erzeugt ein mit `$color` gefülltes Rechteck im Bild ausgehend von den Punkten `$left` & `$top` mit der Breite `$width` und der Höhe `$height`. Der Punkt 0, 0 ist die linke obere Ecke des Bildes.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Führt eine Flutfüllung aus, deren Randfarbe durch `$border` definiert ist. Der Startpunkt für die Füllung ist `$x`, `$y` (oben links ist 0, 0) und der Bereich wird mit der Farbe `$color` gefüllt. ([mehr |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Spiegelt das Bild unter Verwendung der angegebenen `$mode`. ([mehr |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Schreiben Sie Text in das Bild mit Hilfe von FreeType 2-Schriftarten. ([mehr |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Schreiben Sie den Text in das Bild. ([mehr |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Gibt die Breite des Bildes zurück.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Schaltet das Zeilensprungbit ein oder aus. Wenn das Interlace-Bit gesetzt ist und das Bild als JPEG-Bild verwendet wird, wird das Bild als progressives JPEG erstellt. ([mehr |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Setzen Sie das Alpha-Blending-Flag, um Überlagerungseffekte zu verwenden. ([mehr |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Zeichnet eine Linie zwischen den beiden angegebenen Punkten. ([mehr |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Zeichnet ein offenes Polygon auf das Bild. Im Gegensatz zu `polygon()` wird keine Linie zwischen dem letzten und dem ersten Punkt gezogen. ([mehr |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Kopiert `$image` in das Bild an den Koordinaten `$left` und `$top`. Die Koordinaten können als ganze Zahlen in Pixeln oder als Zeichenketten in Prozent übergeben werden (z. B. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Erzeugt ein Polygon im Bild. ([mehr |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Erzeugt ein Rechteck, das an den angegebenen Koordinaten beginnt. ([mehr |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Erzeugt ein Rechteck mit den angegebenen Koordinaten.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Skaliert ein Bild, siehe [weitere Informationen |#Image Resize]. Die Abmessungen können als ganze Zahlen in Pixeln oder als Strings in Prozent (z. B. `'50%'`) übergeben werden.
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Ermöglicht das Einstellen und Abrufen der Auflösung eines Bildes in DPI (dots per inch). Wenn keiner der optionalen Parameter angegeben wird, wird die aktuelle Auflösung als indiziertes Array zurückgegeben. Wenn nur `$resX` angegeben wird, werden die horizontale und vertikale Auflösung auf diesen Wert gesetzt. Wenn beide optionalen Parameter angegeben werden, werden die horizontale und vertikale Auflösung auf diese Werte gesetzt.
 
 Die Auflösung wird nur als Metainformation verwendet, wenn Bilder aus Formaten gelesen und in Formate geschrieben werden, die diese Art von Information unterstützen (derzeit PNG und JPEG). Sie hat keinen Einfluss auf die Zeichenoperationen. Die Standardauflösung für neue Bilder beträgt 96 DPI. ([mehr |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Dreht das Bild unter Verwendung der angegebenen `$angle` in Grad. Das Zentrum de
 Erfordert *GD-Erweiterung*, daher ist nicht sicher, dass sie überall funktioniert.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Speichert ein Bild in einer Datei.
 
-Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Wenn der Typ nicht aus der Dateierweiterung ersichtlich ist, können Sie ihn mit einer der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP` angeben.
+Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Wenn der Typ nicht aus der Dateierweiterung ersichtlich ist, können Sie ihn mit einer der Konstanten `ImageType` angeben.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Skaliert ein Bild unter Verwendung des angegebenen Interpolationsalgorithmus. ([mehr |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Gibt ein Bild an den Browser aus.
 
-Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Typ ist eine der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP`.
+Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Legt die Interpolationsmethode fest, die sich auf die Methoden `rotate()` und `affine()` auswirkt. ([mehr |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Zeichnet ein Pixel an der angegebenen Koordinate. (mehr |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Schärft das Bild ein wenig.
 Erfordert *GD-Erweiterung*, daher ist nicht sicher, dass sie überall funktioniert.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Zeichnet eine Zeichenkette an den angegebenen Koordinaten. ([mehr |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Zeichnet eine Zeichenkette vertikal an den angegebenen Koordinaten. ([mehr |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Gibt ein Bild als String aus.
 
-Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Typ ist eine der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP`.
+Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Konvertiert ein Truecolor-Bild in ein Palettenbild. ([mehr |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Schreibt den angegebenen Text mit TrueType-Schriften in das Bild. ([mehr |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Schreibt den angegebenen Text in das Bild. ([mehr |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/de/iterables.texy b/utils/de/iterables.texy
new file mode 100644
index 0000000000..ca35b3e441
--- /dev/null
+++ b/utils/de/iterables.texy
@@ -0,0 +1,170 @@
+Iterator-Funktionen
+*******************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] ist eine statische Klasse mit Funktionen für die Arbeit mit Iteratoren. Ihr Gegenstück für Arrays ist [Nette\Utils\Arrays |arrays].
+
+
+Installation:
+
+```shell
+composer require nette/utils
+```
+
+Bei allen Beispielen wird davon ausgegangen, dass der folgende Alias erstellt wurde:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Sucht nach einem bestimmten Wert in einem Iterator. Verwendet einen strengen Vergleich (`===`), um nach einer Übereinstimmung zu suchen. Gibt `true` zurück, wenn der Wert gefunden wird, andernfalls `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Diese Methode ist nützlich, wenn Sie schnell feststellen müssen, ob ein bestimmter Wert in einem Iterator vorhanden ist, ohne manuell durch alle Elemente zu iterieren.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Sucht nach einem bestimmten Schlüssel in einem Iterator. Verwendet einen strikten Vergleich (`===`), um nach einer Übereinstimmung zu suchen. Gibt `true` zurück, wenn der Schlüssel gefunden wird, andernfalls `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Überprüft, ob alle Elemente des Iterators die in `$predicate` definierte Bedingung erfüllen. Die Funktion `$predicate` hat die Signatur `function ($value, $key, iterable $iterable): bool` und muss für jedes Element `true` zurückgeben, damit die Methode `every()` `true` zurückgibt.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Diese Methode ist nützlich, um zu überprüfen, ob alle Elemente in einer Sammlung eine bestimmte Bedingung erfüllen, z. B. ob alle Zahlen unter einem bestimmten Wert liegen.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Erzeugt einen neuen Iterator, der nur die Elemente des ursprünglichen Iterators enthält, die die in `$predicate` definierte Bedingung erfüllen. Die Funktion `$predicate` hat die Signatur `function ($value, $key, iterable $iterable): bool` und muss für Elemente, die beibehalten werden sollen, `true` zurückgeben.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Die Methode verwendet einen Generator, was bedeutet, dass die Filterung während der Iteration inkrementell erfolgt. Dies ist speichereffizient und ermöglicht die Verarbeitung sehr großer Sammlungen. Wenn Sie nicht durch alle Elemente des resultierenden Iterators iterieren, sparen Sie Rechenaufwand, da nicht alle Elemente des ursprünglichen Iterators verarbeitet werden.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Gibt das erste Element des Iterators zurück. Wenn `$predicate` angegeben ist, wird das erste Element zurückgegeben, das die angegebene Bedingung erfüllt. Die Funktion `$predicate` hat die Signatur `function ($value, $key, iterable $iterable): bool`. Wenn kein übereinstimmendes Element gefunden wird, wird die Funktion `$else` (falls angegeben) aufgerufen und ihr Ergebnis zurückgegeben. Wenn `$else` nicht angegeben ist, wird `null` zurückgegeben.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Diese Methode ist nützlich, wenn Sie schnell das erste Element einer Sammlung oder das erste Element, das eine bestimmte Bedingung erfüllt, abrufen möchten, ohne die gesamte Sammlung manuell durchlaufen zu müssen.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Gibt den Schlüssel des ersten Elements des Iterators zurück. Wenn `$predicate` angegeben ist, wird der Schlüssel des ersten Elements zurückgegeben, das die angegebene Bedingung erfüllt. Die Funktion `$predicate` hat die Signatur `function ($value, $key, iterable $iterable): bool`. Wird kein passendes Element gefunden, wird die Funktion `$else` (falls angegeben) aufgerufen und ihr Ergebnis zurückgegeben. Wenn `$else` nicht angegeben ist, wird `null` zurückgegeben.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Erzeugt einen neuen Iterator durch Anwendung der Funktion `$transformer` auf jedes Element des ursprünglichen Iterators. Die Funktion `$transformer` hat die Signatur `function ($value, $key, iterable $iterable): mixed` und ihr Rückgabewert wird als neuer Wert des Elements verwendet.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Die Methode verwendet einen Generator, was bedeutet, dass die Umwandlung während der Iteration inkrementell erfolgt. Dies ist speichereffizient und ermöglicht den Umgang mit sehr großen Sammlungen. Wenn Sie nicht durch alle Elemente des resultierenden Iterators iterieren, sparen Sie Rechenaufwand, da nicht alle Elemente des ursprünglichen Iterators verarbeitet werden.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Erzeugt einen neuen Iterator durch Umwandlung der Werte und Schlüssel des ursprünglichen Iterators. Die Funktion `$transformer` hat die Signatur `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Wenn `$transformer` `null` zurückgibt, wird das Element übersprungen. Bei beibehaltenen Elementen wird das erste Element des zurückgegebenen Arrays als neuer Schlüssel und das zweite Element als neuer Wert verwendet.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Wie `map()` verwendet diese Methode einen Generator für inkrementelle Verarbeitung und Speichereffizienz. Dies ermöglicht die Arbeit mit großen Sammlungen und spart Rechenaufwand, indem nur ein Teil des Ergebnisses verarbeitet wird.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Erzeugt einen Wrapper um einen Iterator, der seine Schlüssel und Werte während der Iteration zwischenspeichert. Dies ermöglicht eine wiederholte Iteration über die Daten, ohne dass die ursprüngliche Datenquelle erneut verarbeitet werden muss.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Diese Methode ist in Situationen nützlich, in denen Sie denselben Datensatz mehrmals durchlaufen müssen, der ursprüngliche Iterator jedoch keine wiederholte Iteration unterstützt oder eine wiederholte Iteration zu kostspielig wäre (z. B. beim Lesen von Daten aus einer Datenbank oder Datei).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Prüft, ob mindestens ein Element des Iterators die in `$predicate` definierte Bedingung erfüllt. Die Funktion `$predicate` hat die Signatur `function ($value, $key, iterable $iterable): bool` und muss für mindestens ein Element `true` zurückgeben, damit die Methode `some()` `true` zurückgibt.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Diese Methode ist nützlich, um schnell zu überprüfen, ob es mindestens ein Element in einer Sammlung gibt, das eine bestimmte Bedingung erfüllt, z. B. ob die Sammlung mindestens eine gerade Zahl enthält.
+
+Siehe [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Konvertiert ein beliebiges iterierbares Objekt (Array, Traversable) in einen Iterator. Wenn die Eingabe bereits ein Iterator ist, wird er unverändert zurückgegeben.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Diese Methode ist nützlich, wenn Sie sicherstellen müssen, dass Sie einen Iterator haben, unabhängig vom Typ der Eingabedaten. Dies kann bei der Erstellung von Funktionen nützlich sein, die mit verschiedenen Typen von Iterationsdaten arbeiten.
diff --git a/utils/de/json.texy b/utils/de/json.texy
index 75a70b407e..e17543165f 100644
--- a/utils/de/json.texy
+++ b/utils/de/json.texy
@@ -77,7 +77,7 @@ Die Einstellung `$forceArray` erzwingt die Rückgabe von Arrays anstelle von Obj
 
 ```php
 Json::decode('{"variable": true}'); // liefert ein Objekt vom Typ stdClass
-Json::decode('{"variable": true}', forceArray: true); // gibt ein Array zurück
+Json::decode('{"variable": true}', forceArrays: true); // gibt ein Array zurück
 ```
 
 Im Fehlerfall wird eine `Nette\Utils\JsonException` Exception ausgelöst.
diff --git a/utils/de/smartobject.texy b/utils/de/smartobject.texy
index 783015895d..65643bc2e0 100644
--- a/utils/de/smartobject.texy
+++ b/utils/de/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject und StaticClass
-***************************
+SmartObject
+***********
 
 .[perex]
-SmartObject fügt PHP-Klassen Unterstützung für *Eigenschaften* hinzu. StaticClass wird verwendet, um statische Klassen zu bezeichnen.
+SmartObject hat das Verhalten von Objekten in vielerlei Hinsicht verbessert, aber das heutige PHP enthält die meisten dieser Verbesserungen bereits von Haus aus. Es fügt jedoch noch Unterstützung für *Property* hinzu.
 
 
 Installation:
@@ -65,31 +65,16 @@ echo $circle->visible; // calls isVisible()
 Eigenschaften sind in erster Linie "syntaktischer Zucker" ((syntactic sugar)), der das Leben des Programmierers durch Vereinfachung des Codes versüßen soll. Wenn Sie sie nicht wollen, müssen Sie sie nicht verwenden.
 
 
-Statische Klassen .[#toc-static-classes]
-========================================
+Ein Blick in die Geschichte .[#toc-a-glimpse-into-history]
+==========================================================
 
-Statische Klassen, d.h. Klassen, die nicht instanziiert werden sollen, können mit dem Trait `Nette\StaticClass` gekennzeichnet werden:
+SmartObject verfeinerte das Verhalten von Objekten auf zahlreiche Arten, aber das heutige PHP enthält die meisten dieser Erweiterungen bereits von Haus aus. Der folgende Text ist ein nostalgischer Blick zurück in die Geschichte, der uns daran erinnert, wie sich die Dinge entwickelt haben.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Wenn Sie versuchen, eine Instanz zu erstellen, wird die Ausnahme `Error` ausgelöst, die angibt, dass die Klasse statisch ist.
-
-
-Ein Blick in die Geschichte .[#toc-a-look-into-the-history]
-===========================================================
-
-SmartObject hat das Verhalten von Klassen in vielerlei Hinsicht verbessert und korrigiert, aber die Entwicklung von PHP hat die meisten der ursprünglichen Funktionen überflüssig gemacht. Im Folgenden werfen wir einen Blick in die Geschichte, wie sich die Dinge entwickelt haben.
-
-Von Anfang an litt das PHP-Objektmodell unter einer Reihe von schwerwiegenden Mängeln und Ineffizienzen. Dies war der Grund für die Schaffung der Klasse `Nette\Object` (im Jahr 2007), mit der versucht wurde, diese zu beheben und die Benutzung von PHP zu verbessern. Es reichte aus, dass andere Klassen von ihr erbten und von den Vorteilen profitierten, die sie mit sich brachte. Als PHP 5.4 mit Trait-Unterstützung kam, wurde die Klasse `Nette\Object` durch `Nette\SmartObject` ersetzt. Somit war es nicht mehr notwendig, von einem gemeinsamen Vorfahren zu erben. Darüber hinaus konnte Trait in Klassen verwendet werden, die bereits von einer anderen Klasse geerbt hatten. Das endgültige Ende von `Nette\Object` kam mit der Veröffentlichung von PHP 7.2, die es verbot, Klassen den Namen `Object` zu geben.
+Seit seinen Anfängen litt das Objektmodell von PHP unter einer Vielzahl von ernsthaften Mängeln und Unzulänglichkeiten. Dies führte zur Schaffung der Klasse `Nette\Object` (im Jahr 2007), die diese Probleme beheben und den Komfort bei der Verwendung von PHP erhöhen sollte. Andere Klassen brauchten nur von dieser Klasse zu erben, um die Vorteile zu nutzen, die sie bot. Als mit PHP 5.4 die Unterstützung für Traits eingeführt wurde, wurde die Klasse `Nette\Object` durch den Trait `Nette\SmartObject` ersetzt. Damit entfiel die Notwendigkeit, von einem gemeinsamen Vorfahren zu erben. Außerdem konnte der Trait in Klassen verwendet werden, die bereits von einer anderen Klasse geerbt hatten. Das endgültige Ende von `Nette\Object` kam mit der Veröffentlichung von PHP 7.2, die es verbot, Klassen den Namen `Object` zu geben.
 
-Im weiteren Verlauf der PHP-Entwicklung wurden das Objektmodell und die Sprachfähigkeiten verbessert. Die einzelnen Funktionen der Klasse `SmartObject` wurden überflüssig. Seit der Veröffentlichung von PHP 8.2 ist die einzige Funktion, die noch nicht direkt in PHP unterstützt wird, die Möglichkeit, sogenannte [Properties |#Properties, getters and setters] zu verwenden.
+Mit der weiteren Entwicklung von PHP wurden das Objektmodell und die Sprachfähigkeiten verbessert. Verschiedene Funktionen der Klasse `SmartObject` wurden überflüssig. Seit der Veröffentlichung von PHP 8.2 gibt es nur noch eine Funktion, die in PHP nicht direkt unterstützt wird: die Möglichkeit, so genannte [Properties |#Properties, getters, and setters] zu verwenden.
 
-Welche Funktionen boten `Nette\Object` und `Nette\Object` früher? Hier ist ein Überblick. (Die Beispiele verwenden die Klasse `Nette\Object`, aber die meisten der Eigenschaften gelten auch für die Eigenschaft `Nette\SmartObject` ).
+Welche Funktionen boten `Nette\Object` und in der Folge `Nette\SmartObject`? Hier ist ein Überblick. (In den Beispielen wird die Klasse `Nette\Object` verwendet, aber die meisten Funktionen gelten auch für den Trait `Nette\SmartObject` ).
 
 
 Inkonsistente Fehler .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Das heutige PHP hat zwar keine Form von "did you mean?", aber [Tracy |tracy:] fügt diesen Zusatz zu Fehlern hinzu. Und es kann solche Fehler sogar selbst [beheben |tracy:open-files-in-ide#toc-demos].
+Das heutige PHP hat zwar keine "Meinten Sie?"-Funktion, aber dieser Satz kann von [Tracy |tracy:] zu Fehlern hinzugefügt werden. Es kann [solche Fehler |tracy:open-files-in-ide#toc-demos] sogar [automatisch korrigieren |tracy:open-files-in-ide#toc-demos].
 
 
 Erweiterungsmethoden .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // returns 'John Doe
+$reflection->getAnnotation('author'); // returns 'John Doe'
 ```
 
 Seit PHP 8.0 ist es möglich, auf Metainformationen in Form von Attributen zuzugreifen:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/de/staticclass.texy b/utils/de/staticclass.texy
new file mode 100644
index 0000000000..c5831c1c0d
--- /dev/null
+++ b/utils/de/staticclass.texy
@@ -0,0 +1,21 @@
+Statische Klassen
+*****************
+
+.[perex]
+StaticClass wird verwendet, um statische Klassen zu bezeichnen.
+
+
+Installation:
+
+```shell
+composer require nette/utils
+```
+
+Statische Klassen, d.h. Klassen, die nicht instanziiert werden sollen, können mit dem Trait [api:Nette\StaticClass] gekennzeichnet werden:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/de/strings.texy b/utils/de/strings.texy
index f5d0d29c12..da18d37dfd 100644
--- a/utils/de/strings.texy
+++ b/utils/de/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Ändert die UTF-8-Zeichenkette in die Form, die in der URL verwendet wird, d. h. entfernt diakritische Zeichen und ersetzt alle Zeichen außer Buchstaben des englischen Alphabets und Zahlen durch einen Bindestrich.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Erfordert die PHP-Erweiterung `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Entfernt alle links- und rechtsseitigen Leerzeichen (oder die als zweites Argument übergebenen Zeichen) aus einer UTF-8-kodierten Zeichenkette.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Gibt einen Teil der UTF-8-Zeichenkette zurück, der durch die Startposition `$start` und die Länge `$length` angegeben wird. Wenn `$start` negativ ist, beginnt die zurückgegebene Zeichenkette am `$start`'ten Zeichen vom Ende der Zeichenkette.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Verwenden Sie die native `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Vergleicht zwei UTF-8-Zeichenketten oder deren Teile, ohne Berücksichtigung der Groß- und Kleinschreibung. Ist `$length` gleich null, werden ganze Zeichenketten verglichen, ist er negativ, wird die entsprechende Anzahl von Zeichen vom Ende der Zeichenketten verglichen, andernfalls die entsprechende Anzahl von Zeichen vom Anfang.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Durchsucht die Zeichenkette nach allen Vorkommen, die mit dem regulären Ausdruck übereinstimmen, und gibt ein Array von Arrays zurück, das den gefundenen Ausdruck und jeden Unterausdruck enthält.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Wenn `$lazy` `true` ist, gibt die Funktion ein `Generator` anstelle eines Arrays zurück, was bei der Arbeit mit großen Zeichenketten erhebliche Leistungsvorteile bietet. Der Generator ermöglicht es, dass Übereinstimmungen schrittweise gefunden werden, anstatt die gesamte Zeichenkette auf einmal zu verarbeiten. Dies ermöglicht einen effizienten Umgang mit extrem großen Eingabetexten. Außerdem können Sie die Verarbeitung jederzeit unterbrechen, wenn Sie die gewünschte Übereinstimmung gefunden haben, was Rechenzeit spart.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/de/validators.texy b/utils/de/validators.texy
index 7128ff2c8e..6ec5fb1fa3 100644
--- a/utils/de/validators.texy
+++ b/utils/de/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Überprüft, ob das Element `$key` im Array `$array` die [erwarteten |#expected types], durch Pipe getrennten [Typen |#expected types] enthält. Wenn nicht, wird die Ausnahme [api:Nette\Utils\AssertionException] ausgelöst. Die Zeichenkette `item '%' in array` in der Ausnahmemeldung kann durch den Parameter `$label` ersetzt werden.
 
diff --git a/utils/el/@home.texy b/utils/el/@home.texy
index 049f6689d3..1e5c416b70 100644
--- a/utils/el/@home.texy
+++ b/utils/el/@home.texy
@@ -13,13 +13,14 @@
 | [Helpers |helpers] | Nette\Utils\Helpers
 | [Στοιχεία HTML |HTML Elements] | Nette\Utils\Html
 | [Images |Images] | Nette\Utils\Image
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [JSON |JSON] | Nette\Utils\Json
-| [Μοντέλο αντικειμένων |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginator |paginator] | Nette\Utils\Paginator
 | [PHP Reflection |reflection] | Nette\Utils\Reflection
 | [PHP Types |type] | Nette\Utils\Type
 | [Τυχαίες συμβολοσειρές |random] | Nette\Utils\Random
 | [Strings |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validators |validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | έκδοση | συμβατό με PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.3
+| Nette Utils 3.2 | PHP 7.2 – 8.4
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/el/@left-menu.texy b/utils/el/@left-menu.texy
index c262d9deb2..1f5380b7a1 100644
--- a/utils/el/@left-menu.texy
+++ b/utils/el/@left-menu.texy
@@ -8,13 +8,15 @@
 - [Βοηθοί |helpers]
 - [Στοιχεία HTML |HTML Elements]
 - [Εικόνες |Images]
+- [Iterables |iterables]
 - [JSON |JSON]
 - [Σελιδοποιητής |paginator]
 - [Τυχαίες συμβολοσειρές |random]
-- [SmartObject |SmartObject]
 - [PHP Reflection |reflection]
 - [Συμβολοσειρές |Strings]
 - [Floats |Floats]
+- [SmartObject]
+- [StaticClass]
 - [Τύποι PHP |type]
 - [Επικυρωτές |validators]
 
diff --git a/utils/el/arrays.texy b/utils/el/arrays.texy
index 29b06248e0..788f31ed6d 100644
--- a/utils/el/arrays.texy
+++ b/utils/el/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] είναι μια στατική κλάση, η οποία περιέχει μια χούφτα από εύχρηστες συναρτήσεις συστοιχιών.
+[api:Nette\Utils\Arrays] είναι μια στατική κλάση, η οποία περιέχει μια χούφτα από εύχρηστες συναρτήσεις πίνακα. Το ισοδύναμό της για τους επαναλήπτες είναι η [Nette\Utils\Iterables |iterables].
 
 Τα παραδείγματα που ακολουθούν υποθέτουν ότι έχει οριστεί το ακόλουθο ψευδώνυμο της κλάσης:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Η συνάρτηση μετατρέπει ευέλικτα το `$array` σε συσχετιστικό πίνακα ή αντικείμενα σύμφωνα με την καθορισμένη διαδρομή `$path`. Η διαδρομή μπορεί να είναι μια συμβολοσειρά ή ένας πίνακας. Αποτελείται από τα ονόματα των κλειδιών του πίνακα εισόδου και τελεστές όπως '[]', '->', '=' και '|'. Πετάει το `Nette\InvalidArgumentException` αν η διαδρομή είναι άκυρη.
+
+```php
+// μετατροπή σε συσχετιστικό πίνακα χρησιμοποιώντας ένα απλό κλειδί
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// ανάθεση τιμών από ένα κλειδί σε ένα άλλο με χρήση του τελεστή =
+$result = Arrays::associate($arr, 'name=age'); // ή ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// δημιουργία ενός αντικειμένου με χρήση του τελεστή ->
+$result = Arrays::associate($arr, '->name'); // ή ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// συνδυασμός κλειδιών με χρήση του τελεστή |
+$result = Arrays::associate($arr, 'name|age'); // ή ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// προσθήκη σε έναν πίνακα χρησιμοποιώντας []
+$result = Arrays::associate($arr, 'name[]'); // ή ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Ελέγχει αν όλα τα στοιχεία του πίνακα περνούν τον έλεγχο που υλοποιείται από την παρεχόμενη συνάρτηση, η οποία έχει την υπογραφή `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Βλέπε [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Επιστρέφει έναν νέο πίνακα που περιέχει όλα τα ζεύγη κλειδιών-τιμών που ταιριάζουν με το δεδομένο `$predicate`. Το callback έχει την υπογραφή `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Επιστρέφει το πρώτο στοιχείο από τον πίνακα ή null αν ο πίνακας είναι άδειος. Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `reset()`.
+Επιστρέφει το πρώτο στοιχείο (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται). Εάν δεν υπάρχει τέτοιο στοιχείο, επιστρέφει το αποτέλεσμα της κλήσης του `$else` ή null.
+Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`.
+
+Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `reset()`. Οι παράμετροι `$predicate` και `$else` υπάρχουν από την έκδοση 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Βλέπε [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Επιστρέφει το κλειδί του πρώτου στοιχείου (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται) ή null αν δεν υπάρχει τέτοιο στοιχείο. Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Βλέπε [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Επιστρέφει `$array[$key]` item. Εάν δεν υπάρχει, απορρίπτεται το `Nette\InvalidArgumentException`, εκτός εάν έχει οριστεί μια προεπιλεγμένη τιμή ως τρίτο όρισμα.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Επιστρέφει το τελευταίο στοιχείο (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται). Εάν δεν υπάρχει τέτοιο στοιχείο, επιστρέφει το αποτέλεσμα της κλήσης του `$else` ή null.
+Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`.
+
+Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `end()`. Οι παράμετροι `$predicate` και `$else` υπάρχουν από την έκδοση 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Βλέπε [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Επιστρέφει το τελευταίο στοιχείο από τον πίνακα ή null αν ο πίνακας είναι άδειος. Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `end()`.
+Επιστρέφει το κλειδί του τελευταίου στοιχείου (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται) ή null αν δεν υπάρχει τέτοιο στοιχείο. Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Βλέπε [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Καλεί το `$callback` σε όλα τα στοιχεία του πίνακα και επιστρέφει τον πίνακα των τιμών επιστροφής. Η ανάκληση έχει την υπογραφή `function ($value, $key, array $array): bool`.
+Καλεί το `$transformer` σε όλα τα στοιχεία του πίνακα και επιστρέφει τον πίνακα των τιμών επιστροφής. Η ανάκληση έχει την υπογραφή `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Δημιουργεί έναν νέο πίνακα μετασχηματίζοντας τις τιμές και τα κλειδιά του αρχικού πίνακα. Η συνάρτηση `$transformer` έχει την υπογραφή `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Εάν η `$transformer` επιστρέφει `null`, το στοιχείο παραλείπεται. Για στοιχεία που διατηρούνται, το πρώτο στοιχείο του επιστρεφόμενου πίνακα χρησιμοποιείται ως το νέο κλειδί και το δεύτερο στοιχείο ως η νέα τιμή.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Αυτή η μέθοδος είναι χρήσιμη σε περιπτώσεις όπου πρέπει να αλλάξετε τη δομή ενός πίνακα (και τα κλειδιά και τις τιμές ταυτόχρονα) ή να φιλτράρετε στοιχεία κατά τη διάρκεια του μετασχηματισμού (επιστρέφοντας null για ανεπιθύμητα στοιχεία).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Οι τιμές από τον δεύτερο πίνακα προστίθενται πάντα στον πρώτο. Η εξαφάνιση της τιμής `10` από τον δεύτερο πίνακα μπορεί να φαίνεται λίγο συγκεχυμένη. Θα πρέπει να σημειωθεί ότι αυτή η τιμή καθώς και η τιμή `5` in the first array have the same numeric key `0`, οπότε στο πεδίο που προκύπτει υπάρχει μόνο ένα στοιχείο από τον πρώτο πίνακα.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Κανονικοποιεί τον πίνακα σε συσχετιστικό πίνακα. Αντικαθιστά τα αριθμητικά κλειδιά με τις τιμές τους, η νέα τιμή θα είναι `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Επιστρέφει και αφαιρεί την τιμή ενός στοιχείου από έναν πίνακα. Εάν δεν υπάρχει, πετάει μια εξαίρεση ή επιστρέφει `$default`, εάν παρέχεται.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // επιστρέφει
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Ελέγχει αν τουλάχιστον ένα στοιχείο του πίνακα περνάει το τεστ που υλοποιείται από την παρεχόμενη κλήση με υπογραφή `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // θέτει $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Μετατρέπει κάθε στοιχείο του πίνακα σε συμβολοσειρά και το περικλείει με τα `$prefix` και `$suffix`.
 
diff --git a/utils/el/datetime.texy b/utils/el/datetime.texy
index b024149658..f9ebeb7d9c 100644
--- a/utils/el/datetime.texy
+++ b/utils/el/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Επεκτείνει την [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] με τη δυνατότητα καθορισμού μιας ζώνης ώρας ως συμβολοσειρά.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // δημιουργία με προσαρμοσμένη ζώνη ώρας
diff --git a/utils/el/filesystem.texy b/utils/el/filesystem.texy
index 2c7b28f09c..7219be059f 100644
--- a/utils/el/filesystem.texy
+++ b/utils/el/filesystem.texy
@@ -2,9 +2,11 @@
 ******************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] είναι μια στατική κλάση, η οποία περιέχει χρήσιμες συναρτήσεις για την εργασία με ένα σύστημα αρχείων. Ένα πλεονέκτημα σε σχέση με τις εγγενείς συναρτήσεις της PHP είναι ότι πετάνε εξαιρέσεις σε περίπτωση σφαλμάτων.
+[api:Nette\Utils\FileSystem] είναι μια κλάση, η οποία περιέχει χρήσιμες λειτουργίες για την εργασία με ένα σύστημα αρχείων. Ένα πλεονέκτημα σε σχέση με τις εγγενείς συναρτήσεις της PHP είναι ότι σε περίπτωση σφαλμάτων πετάνε εξαιρέσεις.
 
 
+Αν θέλετε να αναζητήσετε αρχεία στο δίσκο, χρησιμοποιήστε το [Finder |finder].
+
 Εγκατάσταση:
 
 ```shell
@@ -174,3 +176,26 @@ platformSlashes(string $path): string .[method]
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Στατική έναντι μη στατικής προσέγγισης .[#toc-static-vs-non-static-approach]
+============================================================================
+
+Για να αντικαταστήσετε εύκολα την κλάση `FileSystem` με μια άλλη κλάση, για παράδειγμα για σκοπούς δοκιμών, χρησιμοποιήστε τη μη στατική:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/el/finder.texy b/utils/el/finder.texy
index fc541178a9..8c554fbd45 100644
--- a/utils/el/finder.texy
+++ b/utils/el/finder.texy
@@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // όλοι οι κατάλογοι
 
 Μπορείτε να χρησιμοποιήσετε [μπαλαντέρ |#wildcards] `*`, `**`, `?` and `[...]` στη μάσκα. Μπορείτε ακόμη και να καθορίσετε σε καταλόγους, για παράδειγμα, το `src/*.php` θα αναζητήσει όλα τα αρχεία PHP στον κατάλογο `src`.
 
+Οι συμβολικοί σύνδεσμοι θεωρούνται επίσης κατάλογοι ή αρχεία.
+
 
 Πού να ψάξετε; .[#toc-where-to-search]
 --------------------------------------
diff --git a/utils/el/floats.texy b/utils/el/floats.texy
index 3125001c82..10682f5a1d 100644
--- a/utils/el/floats.texy
+++ b/utils/el/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same': 'not same'; // ίδιο
 
 Όταν προσπαθεί να συγκρίνει το `NAN`, πετάει μια εξαίρεση `\LogicException`.
 
+.[tip]
+Η κλάση `Floats` ανέχεται διαφορές μικρότερες από `1e-10`. Αν θέλετε να εργαστείτε με μεγαλύτερη ακρίβεια, χρησιμοποιήστε τη βιβλιοθήκη BCMath.
+
 
 Σύγκριση float .[#toc-float-comparison]
 =======================================
diff --git a/utils/el/html-elements.texy b/utils/el/html-elements.texy
index 289132e889..4f5c017368 100644
--- a/utils/el/html-elements.texy
+++ b/utils/el/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Ένας άλλος τρόπος δημιουργίας και εισαγωγής ενός νέου κόμβου `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/el/images.texy b/utils/el/images.texy
index 704d9f723c..07865c9ff2 100644
--- a/utils/el/images.texy
+++ b/utils/el/images.texy
@@ -17,6 +17,8 @@ composer require nette/utils
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Προαιρετικά, μπορείτε να καθορίσετε ένα χρώμα φόντου (το προεπιλεγμένο είναι μαύρο):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Ή φορτώνουμε την εικόνα από ένα αρχείο:
@@ -41,17 +43,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
 $image = Image::fromFile('nette.jpg');
 ```
 
-Οι υποστηριζόμενες μορφές είναι JPEG, PNG, GIF, WebP, AVIF και BMP, αλλά η έκδοση της PHP σας πρέπει επίσης να τις υποστηρίζει (ελέγξτε το `phpinfo()`, ενότητα GD). Τα κινούμενα σχέδια δεν υποστηρίζονται.
-
-Πρέπει να ανιχνεύσετε τη μορφή εικόνας κατά τη φόρτωση; Η μέθοδος επιστρέφει τη μορφή στη δεύτερη παράμετρο:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type είναι Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ή Image::BMP
-```
-
-Μόνο η ανίχνευση χωρίς φόρτωση της εικόνας γίνεται από το `Image::detectTypeFromFile()`.
-
 
 Αποθήκευση της εικόνας .[#toc-save-the-image]
 =============================================
@@ -68,25 +59,45 @@ $image->save('resampled.jpg');
 $image->save('resampled.jpg', 80); // JPEG, ποιότητα 80%
 ```
 
-Εάν η μορφή δεν είναι προφανής από την επέκταση του αρχείου, μπορεί να καθοριστεί με μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`:
+Εάν η μορφή δεν είναι προφανής από την επέκταση του αρχείου, μπορεί να καθοριστεί με [σταθερά |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Η εικόνα μπορεί να εγγραφεί σε μια μεταβλητή αντί στο δίσκο:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, ποιότητα 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, ποιότητα 80%
 ```
 
 ή να στείλετε απευθείας στο πρόγραμμα περιήγησης με την κατάλληλη επικεφαλίδα HTTP `Content-Type`:
 
 ```php
 // στέλνει επικεφαλίδα Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Μορφές .[#toc-formats]
+======================
+
+Οι υποστηριζόμενοι μορφότυποι είναι JPEG, PNG, GIF, WebP, AVIF και BMP. Ωστόσο, πρέπει επίσης να υποστηρίζονται από την έκδοση της PHP σας, κάτι που μπορεί να επαληθευτεί με τη χρήση της συνάρτησης [isTypeSupported() |#isTypeSupported()]. Τα κινούμενα σχέδια δεν υποστηρίζονται.
+
+Οι μορφές αναπαρίστανται από τις σταθερές `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` και `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Πρέπει να ανιχνεύσετε τη μορφή μιας εικόνας κατά τη φόρτωση; Η μέθοδος την επιστρέφει στη δεύτερη παράμετρο:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Η πραγματική ανίχνευση χωρίς φόρτωση της εικόνας πραγματοποιείται από τη διεύθυνση `Image::detectTypeFromFile()`.
+
 
 Αλλαγή μεγέθους εικόνας .[#toc-image-resize]
 ============================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Η μέθοδος `cropAuto()` είναι μια ενθυλάκωση αντικειμένου της συνάρτησης `imagecropauto()`, δείτε [την τεκμηρίωσή της |https://www.php.net/manual/en/function.imagecropauto] για περισσότερες πληροφορίες.
 
 
+Χρώματα .[#toc-colors]
+======================
+
+Η μέθοδος `ImageColor::rgb()` σας επιτρέπει να ορίσετε ένα χρώμα χρησιμοποιώντας τιμές κόκκινου, πράσινου και μπλε (RGB). Προαιρετικά, μπορείτε επίσης να καθορίσετε μια τιμή διαφάνειας που κυμαίνεται από 0 (εντελώς διαφανής) έως 1 (πλήρως αδιαφανής), όπως ακριβώς και στα CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Η μέθοδος `ImageColor::hex()` σάς επιτρέπει να ορίσετε ένα χρώμα χρησιμοποιώντας τη δεκαεξαδική μορφή, παρόμοια με τη CSS. Υποστηρίζει τις μορφές `#rgb`, `#rrggbb`, `#rgba` και `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Τα χρώματα μπορούν να χρησιμοποιηθούν σε άλλες μεθόδους, όπως `ellipse()`, `fill()`, κ.λπ.
+
+
 Σχεδίαση και επεξεργασία .[#toc-drawing-and-editing]
 ====================================================
 
-Μπορείτε να σχεδιάσετε, να γράψετε, να χρησιμοποιήσετε όλες τις συναρτήσεις της PHP για την εργασία με εικόνες, όπως η [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], αλλά χρησιμοποιώντας στυλ αντικειμένου:
+Μπορείτε να σχεδιάσετε, να γράψετε, να χρησιμοποιήσετε όλες τις συναρτήσεις της PHP για την επεξεργασία εικόνων, βλέπε [Επισκόπηση μεθόδων |#Overview of methods], αλλά σε ένα αντικειμενοστραφές περιτύλιγμα:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Βλέπε [Επισκόπηση των μεθόδων |#Overview of Methods].
+Δεδομένου ότι οι συναρτήσεις της PHP για τη σχεδίαση ορθογωνίων δεν είναι πρακτικές λόγω του καθορισμού συντεταγμένων, η κλάση `Image` προσφέρει την αντικατάστασή τους με τη μορφή των συναρτήσεων [rectangleWH() |#rectangleWH()] και [filledRectangleWH() |#filledRectangleWH()].
 
 
 Συγχώνευση πολλαπλών εικόνων .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // οι συντεταγμένες μπορούν να οριστούν επίσης σε ποσοστό
 $blank->place($logo, '80%', '80%'); // κοντά στην κάτω δεξιά γωνία
@@ -219,53 +250,68 @@ $blank->place($image, '80%', '80%', 25); // η διαφάνεια είναι 25
 ==================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Δημιουργεί μια νέα έγχρωμη εικόνα με τις δεδομένες διαστάσεις. Το προεπιλεγμένο χρώμα είναι το μαύρο.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Διαβάζει μια εικόνα από ένα αρχείο και επιστρέφει τον τύπο της σε `$detectedFormat`. Οι υποστηριζόμενοι τύποι είναι `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`.
+Διαβάζει μια εικόνα από ένα αρχείο και επιστρέφει τον [τύπο |#Formats] της σε `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Διαβάζει μια εικόνα από μια συμβολοσειρά και επιστρέφει τον τύπο της σε `$detectedFormat`. Οι υποστηριζόμενοι τύποι είναι `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`.
+Διαβάζει μια εικόνα από μια συμβολοσειρά και επιστρέφει τον [τύπο |#Formats] της σε `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Δημιουργεί ένα χρώμα που μπορεί να χρησιμοποιηθεί σε άλλες μεθόδους, όπως οι `ellipse()`, `fill()` κ.ο.κ.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Το χαρακτηριστικό αυτό έχει αντικατασταθεί από την κλάση `ImageColor`, βλέπε [χρώματα |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Επιστρέφει την επέκταση αρχείου για τη δεδομένη σταθερά `Image::XXX`.
+Επιστρέφει την επέκταση αρχείου για τον δεδομένο [τύπο |#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Επιστρέφει τον τύπο mime για τη δεδομένη σταθερά `Image::XXX`.
+Επιστρέφει τον τύπο mime για τον δεδομένο [τύπο |#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Επιστρέφει τον τύπο της εικόνας ως σταθερά `Image::XXX` σύμφωνα με την επέκταση του αρχείου.
+Επιστρέφει τον [τύπο |#Formats] της εικόνας σύμφωνα με την επέκταση του αρχείου.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Επιστρέφει τον τύπο του αρχείου εικόνας ως σταθερά `Image::XXX` και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις του.
+Επιστρέφει τον [τύπο |#Formats] του αρχείου εικόνας και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις του.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Επιστρέφει τον τύπο της εικόνας από τη συμβολοσειρά ως σταθερά `Image::XXX` και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις της.
+Επιστρέφει τον [τύπο |#Formats] της εικόνας από το αλφαριθμητικό και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις της.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Καθορίζει αν υποστηρίζεται ο συγκεκριμένος [τύπος |#Formats] εικόνας.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Επιστρέφει έναν πίνακα υποστηριζόμενων τύπων εικόνας (σταθερές `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Υπολογίζει τις διαστάσεις του ορθογωνίου που περικλείει το κείμενο σε καθορισμένη γραμματοσειρά και μέγεθος. Επιστρέφει έναν συσχετιστικό πίνακα που περιέχει τα κλειδιά `left`, `top`, `width`, `height`. Το αριστερό περιθώριο μπορεί να είναι αρνητικό εάν το κείμενο ξεκινά με αριστερή προεξοχή.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Επιστρέφει μια εικόνα που περιέχει την affine μετασχηματισμένη εικόνα src, χρησιμοποιώντας μια προαιρετική περιοχή αποκοπής. ([περισσότερα |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Επιστρέφει τη συνένωση δύο πινάκων μετασχηματισμού affine, η οποία είναι χρήσιμη εάν πρέπει να εφαρμοστούν πολλαπλοί μετασχηματισμοί στην ίδια εικόνα με μία κίνηση. ([περισσότερα |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Επιστρέφει έναν πίνακα μετασχηματισμού affine. ([περισσότερα |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ antialias(bool $on): void .[method]
 Η χρήση primitives με αντιδιαμετρική απεικόνιση και διαφανές χρώμα φόντου μπορεί να οδηγήσει σε απροσδόκητα αποτελέσματα. Η μέθοδος ανάμειξης χρησιμοποιεί το χρώμα φόντου όπως όλα τα άλλα χρώματα. Η έλλειψη υποστήριξης του συστατικού άλφα δεν επιτρέπει μια μέθοδο αντιδιαστολής με βάση το άλφα. ([περισσότερα |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Σχεδιάζει ένα τόξο κύκλου με κέντρο τις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Σχεδιάζει τον πρώτο χαρακτήρα του `$char` στην εικόνα με το πάνω αριστερό μέρος του στο `$x`,`$y` (το πάνω αριστερό μέρος είναι 0, 0) με το χρώμα `$color`. ([περισσότερα |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Σχεδιάζει τον χαρακτήρα `$char` κάθετα στην καθορισμένη συντεταγμένη της δεδομένης εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Επιστρέφει ένα αναγνωριστικό χρώματος που αντιπροσωπεύει το χρώμα που αποτελείται από τις δεδομένες συνιστώσες RGB. Πρέπει να κληθεί για να δημιουργήσει κάθε χρώμα που πρόκειται να χρησιμοποιηθεί στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Επιστρέφει τον αριθμό των χρωμάτων σε μια παλέτα εικόνας ([more |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Λαμβάνει ή ορίζει το διαφανές χρώμα της εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Περικόπτει μια εικόνα στη δεδομένη ορθογώνια περιοχή. Οι διαστάσεις μπορούν να μεταβιβαστούν ως ακέραιοι αριθμοί σε pixels ή συμβολοσειρές σε ποσοστό (π.χ. `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Αυτόματη περικοπή μιας εικόνας σύμφωνα με το δεδομένο `$mode`. ([περισσότερα |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Σχεδιάζει μια έλλειψη με κέντρο τις καθορισμένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Εκτελεί ένα γέμισμα πλημμύρας με αφετηρία τη δεδομένη συντεταγμένη (πάνω αριστερά είναι 0, 0) με το δεδομένο `$color` στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Σχεδιάζει ένα μερικό τόξο με κέντρο την καθορισμένη συντεταγμένη στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Σχεδιάζει μια έλλειψη με κέντρο την καθορισμένη συντεταγμένη στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Δημιουργεί ένα γεμάτο πολύγωνο στην εικόνα $image. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Δημιουργεί ένα ορθογώνιο γεμάτο με το `$color` στην εικόνα που ξεκινά από το σημείο 1 και καταλήγει στο σημείο 2. 0, 0 είναι η επάνω αριστερή γωνία της εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Δημιουργεί ένα ορθογώνιο γεμάτο με `$color` στην εικόνα που ξεκινά από τα σημεία `$x1` & `$y1` και καταλήγει στα σημεία `$x2` & `$y2`. Το σημείο 0, 0 είναι η επάνω αριστερή γωνία της εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Δημιουργεί ένα ορθογώνιο γεμάτο με `$color` στην εικόνα ξεκινώντας από τα σημεία `$left` & `$top` με πλάτος `$width` και ύψος `$height`. Το σημείο 0, 0 είναι η επάνω αριστερή γωνία της εικόνας.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Εκτελεί ένα γέμισμα πλημμύρας του οποίου το χρώμα των ορίων ορίζεται από το `$border`. Το σημείο εκκίνησης για το γέμισμα είναι `$x`, `$y` (πάνω αριστερά είναι 0, 0) και η περιοχή γεμίζεται με το χρώμα `$color`. ([περισσότερα |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Αναποδογυρίζει την εικόνα χρησιμοποιώντας το δεδομένο `$mode`. ([περισσότερα |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Γράψτε κείμενο στην εικόνα χρησιμοποιώντας γραμματοσειρές με το FreeType 2. ([περισσότερα |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Γράψτε το κείμενο στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Επιστρέφει το πλάτος της εικόνας.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Ενεργοποιεί ή απενεργοποιεί το bit interlace. Εάν το bit interlace είναι ρυθμισμένο και η εικόνα χρησιμοποιείται ως εικόνα JPEG, η εικόνα δημιουργείται ως προοδευτικό JPEG. ([περισσότερα |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Ορίστε τη σημαία ανάμειξης άλφα για να χρησιμοποιήσετε εφέ διαστρωμάτωσης. ([περισσότερα |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Σχεδιάζει μια γραμμή μεταξύ των δύο δοσμένων σημείων. ([περισσότερα |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Σχεδιάζει ένα ανοιχτό πολύγωνο στην εικόνα. Σε αντίθεση με το `polygon()`, δεν χαράσσεται γραμμή μεταξύ του τελευταίου και του πρώτου σημείου. ([περισσότερα |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Αντιγράφει το `$image` στην εικόνα στις συντεταγμένες `$left` και `$top`. Οι συντεταγμένες μπορούν να μεταβιβαστούν ως ακέραιοι αριθμοί σε pixels ή συμβολοσειρές σε ποσοστό (π.χ. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Δημιουργεί ένα πολύγωνο στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Δημιουργεί ένα ορθογώνιο που ξεκινά από τις καθορισμένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Δημιουργεί ένα ορθογώνιο στις δεδομένες συντεταγμένες.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Κλιμακώνει μια εικόνα, δείτε [περισσότερες πληροφορίες |#Image Resize]. Οι διαστάσεις μπορούν να μεταβιβαστούν ως ακέραιοι αριθμοί σε pixels ή συμβολοσειρές σε ποσοστό (π.χ. `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Επιτρέπει τον ορισμό και τη λήψη της ανάλυσης μιας εικόνας σε DPI (κουκκίδες ανά ίντσα). Εάν δεν δοθεί καμία από τις προαιρετικές παραμέτρους, η τρέχουσα ανάλυση επιστρέφεται ως πίνακας με ευρετήριο. Αν δοθεί μόνο η τιμή `$resX`, η οριζόντια και η κάθετη ανάλυση καθορίζονται σε αυτή την τιμή. Εάν δίνονται και οι δύο προαιρετικές παράμετροι, η οριζόντια και η κατακόρυφη ανάλυση τίθενται σε αυτές τις τιμές, αντίστοιχα.
 
 Η ανάλυση χρησιμοποιείται μόνο ως μεταπληροφορία όταν οι εικόνες διαβάζονται και εγγράφονται σε μορφές που υποστηρίζουν τέτοιου είδους πληροφορίες (επί του παρόντος PNG και JPEG). Δεν επηρεάζει καμία λειτουργία σχεδίασης. Η προεπιλεγμένη ανάλυση για νέες εικόνες είναι 96 DPI. ([περισσότερα |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ rotate(float $angle, int $backgroundColor): Image .[method]
 Απαιτεί *Επέκταση GD*, οπότε δεν είναι σίγουρο ότι θα λειτουργήσει παντού.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Αποθηκεύει μια εικόνα σε ένα αρχείο.
 
-Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Εάν ο τύπος δεν είναι προφανής από την επέκταση του αρχείου, μπορείτε να τον καθορίσετε χρησιμοποιώντας μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`.
+Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Εάν ο τύπος δεν είναι προφανής από την επέκταση του αρχείου, μπορείτε να τον καθορίσετε χρησιμοποιώντας μία από τις σταθερές `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Κλιμακώνει μια εικόνα χρησιμοποιώντας τον δεδομένο αλγόριθμο παρεμβολής. ([περισσότερα |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Εκδίδει μια εικόνα στο πρόγραμμα περιήγησης.
 
-Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Ο τύπος είναι μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`.
+Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Ορίζει τη μέθοδο παρεμβολής, η οποία επηρεάζει τις μεθόδους `rotate()` και `affine()`. ([περισσότερα |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Σχεδιάζει ένα εικονοστοιχείο στην καθορισμένη συντεταγμένη. ([περισσότερα |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ sharpen(): Image .[method]
 Απαιτεί *Επέκταση GD Bundled*, οπότε δεν είναι σίγουρο ότι θα λειτουργήσει παντού.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Σχεδιάζει μια συμβολοσειρά στις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Σχεδιάζει μια συμβολοσειρά κάθετα στις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Εξάγει μια εικόνα σε συμβολοσειρά.
 
-Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Ο τύπος είναι μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`.
+Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Μετατρέπει μια εικόνα πραγματικού χρώματος σε εικόνα παλέτας. ([περισσότερα |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Γράφει το δεδομένο κείμενο στην εικόνα χρησιμοποιώντας γραμματοσειρές TrueType. ([περισσότερα |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Γράφει το δεδομένο κείμενο στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/el/iterables.texy b/utils/el/iterables.texy
new file mode 100644
index 0000000000..1387184803
--- /dev/null
+++ b/utils/el/iterables.texy
@@ -0,0 +1,170 @@
+Λειτουργίες επαναλήπτη
+**********************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] είναι μια στατική κλάση με συναρτήσεις για την εργασία με επαναλήπτες. Η αντίστοιχη κλάση για πίνακες είναι η [Nette\Utils\Arrays |arrays].
+
+
+Εγκατάσταση:
+
+```shell
+composer require nette/utils
+```
+
+Όλα τα παραδείγματα υποθέτουν ότι έχει δημιουργηθεί το ακόλουθο ψευδώνυμο:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Αναζητά μια δεδομένη τιμή σε έναν επαναλήπτη. Χρησιμοποιεί αυστηρή σύγκριση (`===`) για να ελέγξει αν υπάρχει ταύτιση. Επιστρέφει `true` αν η τιμή βρέθηκε, διαφορετικά `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Αυτή η μέθοδος είναι χρήσιμη όταν πρέπει να προσδιορίσετε γρήγορα αν μια συγκεκριμένη τιμή υπάρχει σε έναν επαναλήπτη χωρίς να κάνετε χειροκίνητη επανάληψη σε όλα τα στοιχεία.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Ψάχνει για ένα δεδομένο κλειδί σε έναν επαναλήπτη. Χρησιμοποιεί αυστηρή σύγκριση (`===`) για να ελέγξει αν υπάρχει ταύτιση. Επιστρέφει `true` εάν το κλειδί βρέθηκε, διαφορετικά `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Ελέγχει αν όλα τα στοιχεία του επαναλήπτη ικανοποιούν τη συνθήκη που ορίζεται στο `$predicate`. Η συνάρτηση `$predicate` έχει την υπογραφή `function ($value, $key, iterable $iterable): bool` και πρέπει να επιστρέφει `true` για κάθε στοιχείο, ώστε η μέθοδος `every()` να επιστρέφει `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Αυτή η μέθοδος είναι χρήσιμη για τον έλεγχο ότι όλα τα στοιχεία μιας συλλογής πληρούν μια συγκεκριμένη συνθήκη, όπως για παράδειγμα αν όλοι οι αριθμοί είναι κάτω από μια συγκεκριμένη τιμή.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Δημιουργεί έναν νέο επαναλήπτη που περιέχει μόνο τα στοιχεία από τον αρχικό επαναλήπτη που ικανοποιούν τη συνθήκη που ορίζεται στο `$predicate`. Η συνάρτηση `$predicate` έχει την υπογραφή `function ($value, $key, iterable $iterable): bool` και πρέπει να επιστρέφει `true` για τα στοιχεία που πρέπει να διατηρηθούν.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Η μέθοδος χρησιμοποιεί γεννήτρια, πράγμα που σημαίνει ότι το φιλτράρισμα γίνεται σταδιακά κατά τη διάρκεια της επανάληψης. Αυτό είναι αποδοτικό στη μνήμη και επιτρέπει το χειρισμό πολύ μεγάλων συλλογών. Εάν δεν επαναλαμβάνετε όλα τα στοιχεία του επαναλήπτη που προκύπτει, εξοικονομείτε υπολογιστική προσπάθεια, καθώς δεν επεξεργάζονται όλα τα στοιχεία του αρχικού επαναλήπτη.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Επιστρέφει το πρώτο στοιχείο του επαναλήπτη. Εάν παρέχεται το `$predicate`, επιστρέφει το πρώτο στοιχείο που ικανοποιεί τη δεδομένη συνθήκη. Η συνάρτηση `$predicate` έχει την υπογραφή `function ($value, $key, iterable $iterable): bool`. Εάν δεν βρεθεί κανένα στοιχείο που να ταιριάζει, καλείται η συνάρτηση `$else` (εάν παρέχεται) και επιστρέφεται το αποτέλεσμά της. Εάν δεν παρέχεται η συνάρτηση `$else`, επιστρέφεται η συνάρτηση `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Αυτή η μέθοδος είναι χρήσιμη όταν πρέπει να ανακτήσετε γρήγορα το πρώτο στοιχείο μιας συλλογής ή το πρώτο στοιχείο που πληροί μια συγκεκριμένη συνθήκη χωρίς να επαναλάβετε χειροκίνητα ολόκληρη τη συλλογή.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Επιστρέφει το κλειδί του πρώτου στοιχείου του επαναλήπτη. Εάν παρέχεται το `$predicate`, επιστρέφει το κλειδί του πρώτου στοιχείου που ικανοποιεί τη δεδομένη συνθήκη. Η συνάρτηση `$predicate` έχει την υπογραφή `function ($value, $key, iterable $iterable): bool`. Εάν δεν βρεθεί κανένα στοιχείο που να ταιριάζει, καλείται η συνάρτηση `$else` (εάν παρέχεται) και επιστρέφεται το αποτέλεσμά της. Εάν δεν παρέχεται η συνάρτηση `$else`, επιστρέφεται η συνάρτηση `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Δημιουργεί έναν νέο επαναλήπτη εφαρμόζοντας τη συνάρτηση `$transformer` σε κάθε στοιχείο του αρχικού επαναλήπτη. Η συνάρτηση `$transformer` έχει την υπογραφή `function ($value, $key, iterable $iterable): mixed` και η τιμή επιστροφής της χρησιμοποιείται ως η νέα τιμή του στοιχείου.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Η μέθοδος χρησιμοποιεί γεννήτρια, πράγμα που σημαίνει ότι ο μετασχηματισμός γίνεται σταδιακά κατά τη διάρκεια της επανάληψης. Αυτό είναι αποδοτικό στη μνήμη και επιτρέπει το χειρισμό πολύ μεγάλων συλλογών. Εάν δεν επαναλαμβάνετε όλα τα στοιχεία του επαναλήπτη που προκύπτει, εξοικονομείτε υπολογιστική προσπάθεια, καθώς δεν επεξεργάζονται όλα τα στοιχεία του αρχικού επαναλήπτη.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Δημιουργεί έναν νέο επαναλήπτη μετασχηματίζοντας τις τιμές και τα κλειδιά του αρχικού επαναλήπτη. Η συνάρτηση `$transformer` έχει την υπογραφή `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Εάν η `$transformer` επιστρέφει `null`, το στοιχείο παραλείπεται. Για στοιχεία που διατηρούνται, το πρώτο στοιχείο του επιστρεφόμενου πίνακα χρησιμοποιείται ως νέο κλειδί και το δεύτερο στοιχείο ως νέα τιμή.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Όπως και η `map()`, αυτή η μέθοδος χρησιμοποιεί μια γεννήτρια για σταδιακή επεξεργασία και αποδοτικότητα μνήμης. Αυτό επιτρέπει την εργασία με μεγάλες συλλογές και την εξοικονόμηση υπολογιστικής προσπάθειας με την επεξεργασία μόνο μέρους του αποτελέσματος.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Δημιουργεί ένα περιτύλιγμα γύρω από έναν επαναλήπτη που αποθηκεύει τα κλειδιά και τις τιμές του κατά τη διάρκεια της επανάληψης. Αυτό επιτρέπει την επαναλαμβανόμενη επανάληψη των δεδομένων χωρίς να απαιτείται εκ νέου επεξεργασία της αρχικής πηγής δεδομένων.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Αυτή η μέθοδος είναι χρήσιμη σε περιπτώσεις όπου πρέπει να επαναλάβετε το ίδιο σύνολο δεδομένων πολλές φορές, αλλά ο αρχικός επαναλήπτης δεν υποστηρίζει επαναλαμβανόμενη επανάληψη ή η επαναλαμβανόμενη επανάληψη θα ήταν δαπανηρή (π.χ. ανάγνωση δεδομένων από μια βάση δεδομένων ή ένα αρχείο).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Ελέγχει αν τουλάχιστον ένα στοιχείο του επαναλήπτη ικανοποιεί τη συνθήκη που ορίζεται στο `$predicate`. Η συνάρτηση `$predicate` έχει την υπογραφή `function ($value, $key, iterable $iterable): bool` και πρέπει να επιστρέφει `true` για τουλάχιστον ένα στοιχείο, ώστε η μέθοδος `some()` να επιστρέφει `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Αυτή η μέθοδος είναι χρήσιμη για να ελέγξετε γρήγορα αν υπάρχει τουλάχιστον ένα στοιχείο σε μια συλλογή που πληροί μια συγκεκριμένη συνθήκη, όπως για παράδειγμα αν η συλλογή περιέχει τουλάχιστον έναν ζυγό αριθμό.
+
+Βλέπε [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Μετατρέπει οποιοδήποτε αντικείμενο επανάληψης (array, Traversable) σε Iterator. Εάν η είσοδος είναι ήδη ένας Iterator, επιστρέφεται αμετάβλητος.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Αυτή η μέθοδος είναι χρήσιμη όταν πρέπει να διασφαλίσετε ότι έχετε έναν Iterator, ανεξάρτητα από τον τύπο δεδομένων εισόδου. Αυτό μπορεί να είναι χρήσιμο κατά τη δημιουργία συναρτήσεων που λειτουργούν με διαφορετικούς τύπους επαναληπτικών δεδομένων.
diff --git a/utils/el/json.texy b/utils/el/json.texy
index c7679f3dc5..7c956ba4de 100644
--- a/utils/el/json.texy
+++ b/utils/el/json.texy
@@ -77,7 +77,7 @@ decode(string $json, bool $forceArray=false): mixed .[method]
 
 ```php
 Json::decode('{"variable": true}'); // επιστρέφει ένα αντικείμενο τύπου stdClass
-Json::decode('{"variable": true}', forceArray: true); // επιστρέφει έναν πίνακα
+Json::decode('{"variable": true}', forceArrays: true); // επιστρέφει έναν πίνακα
 ```
 
 Εκπέμπει μια εξαίρεση `Nette\Utils\JsonException` σε περίπτωση σφάλματος.
diff --git a/utils/el/smartobject.texy b/utils/el/smartobject.texy
index 229a82276f..e73cc73d15 100644
--- a/utils/el/smartobject.texy
+++ b/utils/el/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject και StaticClass
-***************************
+SmartObject
+***********
 
 .[perex]
-Το SmartObject προσθέτει υποστήριξη για *ιδιότητες* στις κλάσεις PHP. Το StaticClass χρησιμοποιείται για να δηλώσει στατικές κλάσεις.
+Το SmartObject διόρθωνε τη συμπεριφορά των αντικειμένων με πολλούς τρόπους, αλλά η σημερινή PHP περιλαμβάνει ήδη τις περισσότερες από αυτές τις βελτιώσεις εγγενώς. Ωστόσο, εξακολουθεί να προσθέτει υποστήριξη για *property*.
 
 
 Εγκατάσταση:
@@ -65,31 +65,16 @@ echo $circle->visible; // καλεί την isVisible()
 Οι ιδιότητες είναι κατά κύριο λόγο "συντακτική ζάχαρη"((syntactic sugar)), η οποία έχει σκοπό να κάνει τη ζωή του προγραμματιστή πιο γλυκιά απλοποιώντας τον κώδικα. Αν δεν τις θέλετε, δεν χρειάζεται να τις χρησιμοποιήσετε.
 
 
-Στατικές κλάσεις .[#toc-static-classes]
-=======================================
+Μια ματιά στην ιστορία .[#toc-a-glimpse-into-history]
+=====================================================
 
-Οι στατικές κλάσεις, δηλαδή οι κλάσεις που δεν προορίζονται για ενσάρκωση, μπορούν να επισημανθούν με το χαρακτηριστικό `Nette\StaticClass`:
+Το SmartObject χρησιμοποιείται για να βελτιώσει τη συμπεριφορά των αντικειμένων με πολλούς τρόπους, αλλά η σημερινή PHP ενσωματώνει ήδη τις περισσότερες από αυτές τις βελτιώσεις εγγενώς. Το κείμενο που ακολουθεί είναι μια νοσταλγική αναδρομή στην ιστορία, υπενθυμίζοντάς μας πώς εξελίχθηκαν τα πράγματα.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Όταν προσπαθείτε να δημιουργήσετε ένα instance, εκπέμπεται η εξαίρεση `Error`, υποδεικνύοντας ότι η κλάση είναι στατική.
-
-
-Μια ματιά στην ιστορία .[#toc-a-look-into-the-history]
-======================================================
-
-Το SmartObject βελτίωνε και διόρθωνε τη συμπεριφορά των κλάσεων με πολλούς τρόπους, αλλά η εξέλιξη της PHP έχει καταστήσει τα περισσότερα από τα αρχικά χαρακτηριστικά περιττά. Έτσι, το παρακάτω είναι μια ματιά στην ιστορία της εξέλιξης των πραγμάτων.
-
-Από την αρχή, το μοντέλο αντικειμένων της PHP υπέφερε από μια σειρά σοβαρών ελαττωμάτων και αναποτελεσματικότητας. Αυτός ήταν ο λόγος για τη δημιουργία της κλάσης `Nette\Object` (το 2007), η οποία προσπάθησε να τις διορθώσει και να βελτιώσει την εμπειρία χρήσης της PHP. Ήταν αρκετό για να κληρονομήσουν και άλλες κλάσεις από αυτήν και να αποκτήσουν τα οφέλη που έφερε. Όταν η PHP 5.4 ήρθε με υποστήριξη γνωρισμάτων, η κλάση `Nette\Object` αντικαταστάθηκε από την `Nette\SmartObject`. Έτσι, δεν ήταν πλέον απαραίτητη η κληρονομικότητα από έναν κοινό πρόγονο. Επιπλέον, το trait μπορούσε να χρησιμοποιηθεί σε κλάσεις που ήδη κληρονομούσαν από μια άλλη κλάση. Το οριστικό τέλος της `Nette\Object` ήρθε με την κυκλοφορία της PHP 7.2, η οποία απαγόρευσε στις κλάσεις να έχουν το όνομα `Object`.
+Από την αρχή της δημιουργίας του, το μοντέλο αντικειμένων της PHP υπέφερε από μυριάδες σοβαρές ελλείψεις και αδυναμίες. Αυτό οδήγησε στη δημιουργία της κλάσης `Nette\Object` (το 2007), η οποία είχε ως στόχο να διορθώσει αυτά τα προβλήματα και να βελτιώσει την άνεση της χρήσης της PHP. Το μόνο που χρειαζόταν ήταν άλλες κλάσεις να κληρονομήσουν από αυτήν και θα αποκτούσαν τα οφέλη που προσέφερε. Όταν η PHP 5.4 εισήγαγε την υποστήριξη για γνωρίσματα, η κλάση `Nette\Object` αντικαταστάθηκε από το γνώρισμα `Nette\SmartObject`. Αυτό εξάλειψε την ανάγκη να κληρονομήσετε από έναν κοινό πρόγονο. Επιπλέον, το γνώρισμα μπορούσε να χρησιμοποιηθεί σε κλάσεις που ήδη κληρονομούσαν από μια άλλη κλάση. Το οριστικό τέλος του `Nette\Object` ήρθε με την κυκλοφορία της PHP 7.2, η οποία απαγόρευσε στις κλάσεις να ονομάζονται `Object`.
 
-Καθώς η ανάπτυξη της PHP προχωρούσε, το μοντέλο αντικειμένων και οι δυνατότητες της γλώσσας βελτιώνονταν. Οι επιμέρους λειτουργίες της κλάσης `SmartObject` έγιναν περιττές. Από την έκδοση της PHP 8.2, το μόνο χαρακτηριστικό που παραμένει και δεν υποστηρίζεται ακόμη άμεσα από την PHP είναι η δυνατότητα χρήσης των λεγόμενων [ιδιοτήτων |#Properties, Getters and Setters].
+Καθώς η ανάπτυξη της PHP συνεχιζόταν, το μοντέλο αντικειμένων και οι δυνατότητες της γλώσσας βελτιώνονταν. Διάφορες λειτουργίες της κλάσης `SmartObject` έγιναν περιττές. Από την έκδοση της PHP 8.2, παραμένει μόνο ένα χαρακτηριστικό που δεν υποστηρίζεται άμεσα στην PHP: η δυνατότητα χρήσης των λεγόμενων [ιδιοτήτων |#Properties, getters, and setters].
 
-Ποια χαρακτηριστικά προσέφεραν κάποτε οι `Nette\Object` και `Nette\Object`; Ακολουθεί μια επισκόπηση. (Τα παραδείγματα χρησιμοποιούν την κλάση `Nette\Object`, αλλά οι περισσότερες από τις ιδιότητες ισχύουν και για την ιδιότητα `Nette\SmartObject` ).
+Ποια χαρακτηριστικά προσέφερε η `Nette\Object` και, κατ' επέκταση, η `Nette\SmartObject`; Ακολουθεί μια επισκόπηση. (Στα παραδείγματα χρησιμοποιείται η κλάση `Nette\Object`, αλλά τα περισσότερα χαρακτηριστικά ισχύουν και για την ιδιότητα `Nette\SmartObject` ).
 
 
 Ασυνεπή σφάλματα .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Η σημερινή PHP μπορεί να μην έχει καμία μορφή του "did you mean?", αλλά [η Tracy |tracy:] προσθέτει αυτή την προσθήκη στα σφάλματα. Και μπορεί ακόμη και να [διορθώσει |tracy:open-files-in-ide#toc-demos] η ίδια τέτοια σφάλματα.
+Αν και η σημερινή PHP δεν διαθέτει τη δυνατότητα "εννοούσατε;", αυτή η φράση μπορεί να προστεθεί στα σφάλματα από [την Tracy |tracy:]. Μπορεί ακόμη και να [διορθώσει αυτόματα τέτοια σφάλματα |tracy:open-files-in-ide#toc-demos].
 
 
 Μέθοδοι επέκτασης .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // returns 'John Doe
+$reflection->getAnnotation('author'); // returns 'John Doe'
 ```
 
 Από την PHP 8.0, είναι δυνατή η πρόσβαση σε μετα-πληροφορίες με τη μορφή χαρακτηριστικών:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/el/staticclass.texy b/utils/el/staticclass.texy
new file mode 100644
index 0000000000..0e7d4d0c58
--- /dev/null
+++ b/utils/el/staticclass.texy
@@ -0,0 +1,21 @@
+Στατικές κλάσεις
+****************
+
+.[perex]
+Το StaticClass χρησιμοποιείται για να δηλώσει στατικές κλάσεις.
+
+
+Εγκατάσταση:
+
+```shell
+composer require nette/utils
+```
+
+μπορούν να επισημανθούν με το χαρακτηριστικό [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/el/strings.texy b/utils/el/strings.texy
index f5afa11171..943e8ca617 100644
--- a/utils/el/strings.texy
+++ b/utils/el/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Τροποποιεί τη συμβολοσειρά UTF-8 στη μορφή που χρησιμοποιείται στη διεύθυνση URL, δηλαδή αφαιρεί τους διακριτικούς χαρακτήρες και αντικαθιστά όλους τους χαρακτήρες εκτός από τα γράμματα του αγγλικού αλφαβήτου και τους αριθμούς με μια παύλα.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Απαιτεί την επέκταση PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Αφαιρεί όλα τα αριστερά και δεξιά κενά (ή τους χαρακτήρες που περνούν ως δεύτερο όρισμα) από μια κωδικοποιημένη συμβολοσειρά UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Επιστρέφει ένα τμήμα της συμβολοσειράς UTF-8 που καθορίζεται από τη θέση έναρξης `$start` και το μήκος `$length`. Εάν το `$start` είναι αρνητικό, το επιστρεφόμενο αλφαριθμητικό θα ξεκινήσει από τον `$start`'οστό χαρακτήρα από το τέλος του αλφαριθμητικού.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Χρήση εγγενούς `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Συγκρίνει δύο συμβολοσειρές UTF-8 ή τα μέρη τους, χωρίς να λαμβάνει υπόψη την περίπτωση χαρακτήρων. Αν `$length` είναι null, συγκρίνονται ολόκληρες συμβολοσειρές, αν είναι αρνητικό, συγκρίνεται ο αντίστοιχος αριθμός χαρακτήρων από το τέλος των συμβολοσειρών, διαφορετικά συγκρίνεται ο αντίστοιχος αριθμός χαρακτήρων από την αρχή.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Ψάχνει τη συμβολοσειρά για όλες τις εμφανίσεις που ταιριάζουν με την κανονική έκφραση και επιστρέφει έναν πίνακα πινάκων που περιέχει την έκφραση που βρέθηκε και κάθε υποέκφραση.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Εάν το `$lazy` είναι `true`, η συνάρτηση επιστρέφει ένα `Generator` αντί για έναν πίνακα, γεγονός που παρέχει σημαντικά οφέλη στην απόδοση όταν εργάζεστε με μεγάλες συμβολοσειρές. Η γεννήτρια επιτρέπει τη σταδιακή εύρεση αντιστοιχιών, αντί να επεξεργάζεται ολόκληρη τη συμβολοσειρά με τη μία. Αυτό επιτρέπει τον αποτελεσματικό χειρισμό εξαιρετικά μεγάλων κειμένων εισόδου. Επιπλέον, μπορείτε να διακόψετε την επεξεργασία ανά πάσα στιγμή εάν βρείτε την επιθυμητή αντιστοιχία, εξοικονομώντας υπολογιστικό χρόνο.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/el/validators.texy b/utils/el/validators.texy
index 33bbfc2c76..5c111f74be 100644
--- a/utils/el/validators.texy
+++ b/utils/el/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Επαληθεύει ότι το στοιχείο `$key` στον πίνακα `$array` αποτελείται από τους [αναμενόμενους τύπους |#expected types] που χωρίζονται με pipe. Αν όχι, πετάει την εξαίρεση [api:Nette\Utils\AssertionException]. Η συμβολοσειρά `item '%' in array` στο μήνυμα εξαίρεσης μπορεί να αντικατασταθεί από την παράμετρο `$label`.
 
diff --git a/utils/en/@home.texy b/utils/en/@home.texy
index e2879920a3..bbd39a8616 100644
--- a/utils/en/@home.texy
+++ b/utils/en/@home.texy
@@ -13,13 +13,14 @@ In package `nette/utils` you will find a set of useful classes for everyday use:
 | [Helpers |helpers] | Nette\Utils\Helpers
 | [HTML Elements]    | Nette\Utils\Html
 | [Images]           | Nette\Utils\Image
+| [Iterables]        | Nette\Utils\Iterables
 | [JSON]             | Nette\Utils\Json
-| [Object model |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginator |paginator] | Nette\Utils\Paginator
 | [PHP Reflection |reflection] | Nette\Utils\Reflection
 | [PHP Types |type]  | Nette\Utils\Type
 | [Random Strings |random] | Nette\Utils\Random
 | [Strings]          | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validators |validators] | Nette\Utils\Validators
 
 
@@ -34,9 +35,12 @@ composer require nette/utils
 
 | version   | compatible with PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 – 8.2
-| Nette Utils 3.2 | PHP 7.2 – 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 – 3.1 | PHP 7.1 – 8.0
 | Nette Utils 2.5 | PHP 5.6 – 8.0
 
 Applies to the latest patch versions.
+
+
+If you are upgrading to a newer version, see the [upgrading] page.
diff --git a/utils/en/@left-menu.texy b/utils/en/@left-menu.texy
index 249f02c4f6..8a94eff2d9 100644
--- a/utils/en/@left-menu.texy
+++ b/utils/en/@left-menu.texy
@@ -8,12 +8,14 @@ Package nette/utils
 - [Helpers |helpers]
 - [HTML Elements]
 - [Images]
+- [Iterables]
 - [JSON]
 - [Paginator |paginator]
 - [Random Strings |random]
-- [SmartObject]
 - [PHP Reflection |reflection]
 - [Strings]
+- [SmartObject]
+- [StaticClass]
 - [Floats]
 - [PHP Types |type]
 - [Validators |validators]
diff --git a/utils/en/arrays.texy b/utils/en/arrays.texy
index 5e4e5f9718..0718e80acb 100644
--- a/utils/en/arrays.texy
+++ b/utils/en/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays
 ======
 
-[api:Nette\Utils\Arrays] is a static class, which contains a handful of handy array functions.
+[api:Nette\Utils\Arrays] is a static class, which contains a handful of handy array functions. Its equivalent for iterators is [Nette\Utils\Iterables|iterables].
 
 Following examples assume the following class alias is defined:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+The function flexibly transforms the `$array` into an associative array or objects according to the specified path `$path`. The path can be a string or an array. It consists of the names of keys in the input array and operators like '[]', '->', '=', and '|'. Throws `Nette\InvalidArgumentException` if the path is invalid.
+
+```php
+// converting to an associative array using a simple key
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    // ...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// assigning values from one key to another using the = operator
+$result = Arrays::associate($arr, 'name=age'); // or ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// creating an object using the -> operator
+$result = Arrays::associate($arr, '->name'); // or ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// combining keys using the | operator
+$result = Arrays::associate($arr, 'name|age'); // or ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// adding to an array using []
+$result = Arrays::associate($arr, 'name[]'); // or ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Tests whether all elements in the array pass the test implemented by the provided function, which has the signature `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 See [#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Returns a new array containing all key-value pairs matching the given `$predicate`. The callback has the signature `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Returns the first item from the array or null if array is empty. It does not change the internal pointer unlike `reset()`.
+Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking `$else` or null.
+The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`.
+
+It does not change the internal pointer unlike `reset()`. The `$predicate` and `$else` parameters exist since version 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+See [#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Returns the key of first item (matching the specified predicate if given) or null if there is no such item. The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+See [#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Returns `$array[$key]` item. If it does not exist, `Nette\InvalidArgumentException` is thrown, unless a default value is set as third argument.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Returns the last item (matching the specified predicate if given). If there is no such item, it returns result of invoking `$else` or null.
+The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`.
+
+It does not change the internal pointer unlike `end()`. The `$predicate` and `$else` parameters exist since version 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+See [#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Returns the last item from the array or null if array is empty. It does not change the internal pointer unlike `end()`.
+Returns the key of last item (matching the specified predicate if given) or null if there is no such item. The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+See [#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Calls `$callback` on all elements in the array and returns the array of return values. The callback has the signature `function ($value, $key, array $array): bool`.
+Calls `$transformer` on all elements in the array and returns the array of return values. The callback has the signature `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Creates a new array by transforming the values and keys of the original array. The function `$transformer` has the signature `function ($value, $key, array $array): ?array{$newValue, $newKey}`. If `$transformer` returns `null`, the element is skipped. For retained elements, the first element of the returned array is used as the new key and the second element as the new value.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+This method is useful in situations where you need to change the structure of an array (both keys and values simultaneously) or filter elements during transformation (by returning null for unwanted elements).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Values from the second array are always appended to the first. The disappearance of the value `10` from the second array may seem a bit confusing. It should be noted that this value as well as the value `5` in the first array have the same numeric key `0`, so in the resulting field there is only an element from the first array.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizes array to associative array. Replace numeric keys with their values, the new value will be `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Returns and removes the value of an item from an array. If it does not exist, it throws an exception, or returns `$default`, if provided.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Tests whether at least one element in the array passes the test implemented by the provided callback with signature `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 It casts each element of array to string and encloses it with `$prefix` and `$suffix`.
 
diff --git a/utils/en/datetime.texy b/utils/en/datetime.texy
index b2be48fba5..4ff258943f 100644
--- a/utils/en/datetime.texy
+++ b/utils/en/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Extends [DateTime::createFromFormat()|https://www.php.net/manual/en/datetime.createfromformat.php] with the ability to specify a timezone as a string.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create with custom timezone
diff --git a/utils/en/filesystem.texy b/utils/en/filesystem.texy
index d7fc8b600b..fab3feea01 100644
--- a/utils/en/filesystem.texy
+++ b/utils/en/filesystem.texy
@@ -2,9 +2,11 @@ Filesystem Functions
 ********************
 
 .[perex]
-[api:Nette\Utils\FileSystem] is a static class, which contains useful functions for working with a filesystem. One advantage over native PHP functions is that they throw exceptions in case of errors.
+[api:Nette\Utils\FileSystem] is a class, which contains useful functions for working with a filesystem. One advantage over native PHP functions is that they throw exceptions in case of errors.
 
 
+If you need to search for files on the disk, use the [Finder |finder].
+
 Installation:
 
 ```shell
@@ -174,3 +176,26 @@ Converts slashes to characters specific to the current platform, i.e. `\` on Win
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Static vs Non-static Approach
+=============================
+
+To easily replace the `FileSystem` class with another class for example for testing purposes, use it non-statically:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/en/finder.texy b/utils/en/finder.texy
index f9117246db..d10d88243a 100644
--- a/utils/en/finder.texy
+++ b/utils/en/finder.texy
@@ -61,6 +61,8 @@ An alternative to static methods is to create an instance using `new Finder` (th
 
 You can use [#wildcards] `*`, `**`, `?` and `[...]` in the mask. You can even specify in directories, for example `src/*.php` will search for all PHP files in the `src` directory.
 
+Symlinks are also considered directories or files.
+
 
 Where to Search?
 ----------------
diff --git a/utils/en/floats.texy b/utils/en/floats.texy
index 96bbe394e9..a186e97d5b 100644
--- a/utils/en/floats.texy
+++ b/utils/en/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 When trying to compare `NAN`, it throws an `\LogicException` exception.
 
+.[tip]
+The `Floats` class tolerates differences less than `1e-10`. If you need to work with more precision, use the BCMath library instead.
+
 
 Float Comparison
 ================
diff --git a/utils/en/html-elements.texy b/utils/en/html-elements.texy
index b9f7023e12..ae8aa3bd71 100644
--- a/utils/en/html-elements.texy
+++ b/utils/en/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Another way to create and insert a new `Html` node:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/en/images.texy b/utils/en/images.texy
index 8226cce7b6..aed221f6e9 100644
--- a/utils/en/images.texy
+++ b/utils/en/images.texy
@@ -17,6 +17,8 @@ Following examples assume the following class alias is defined:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Optionally, you can specify a background color (default is black):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Or we load the image from a file:
@@ -41,17 +43,6 @@ Or we load the image from a file:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Supported formats are JPEG, PNG, GIF, WebP, AVIF and BMP, but your version of PHP must also support them (check the `phpinfo()`, section GD). Animations are not supported.
-
-Need to detect the image format when loading? The method returns format in the second parameter:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type is Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF or Image::BMP
-```
-
-Only the detection without loading the image is done by `Image::detectTypeFromFile()`.
-
 
 Save the Image
 ==============
@@ -68,25 +59,45 @@ We can specify compression quality in the range 0..100 for JPEG (default 85), WE
 $image->save('resampled.jpg', 80); // JPEG, quality 80%
 ```
 
-If the format is not obvious from the file extension, it can be specified by one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, and `Image::BMP`:
+If the format is not obvious from the file extension, it can be specified by [constant|#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 The image can be written to a variable instead of to disk:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, quality 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, quality 80%
 ```
 
 or send directly to the browser with the appropriate HTTP header `Content-Type`:
 
 ```php
 // sends header Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formats
+=======
+
+Supported formats are JPEG, PNG, GIF, WebP, AVIF, and BMP. However, they must also be supported by your version of PHP, which can be verified using the [#isTypeSupported()] function. Animations are not supported.
+
+The formats are represented by constants `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, and `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Need to detect the format of an image upon loading? The method returns it in the second parameter:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+The actual detection without loading the image is performed by `Image::detectTypeFromFile()`.
+
 
 Image Resize
 ============
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Method `cropAuto()` is an object encapsulation of the `imagecropauto()` function, see [its documentation|https://www.php.net/manual/en/function.imagecropauto] for more information.
 
 
+Colors .{data-version:4.0.2}
+============================
+
+The `ImageColor::rgb()` method allows you to define a color using red, green, and blue (RGB) values. Optionally, you can also specify a transparency value ranging from 0 (completely transparent) to 1 (fully opaque), just like in CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+The `ImageColor::hex()` method allows you to define a color using the hexadecimal format, similar to CSS. It supports the formats `#rgb`, `#rrggbb`, `#rgba`, and `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Colors can be used in other methods, such as `ellipse()`, `fill()`, etc.
+
+
 Drawing and Editing
 ===================
 
-You can draw, you can write, you can use all PHP functions for working with images, such as [imagefilledellipse()|https://www.php.net/manual/en/function.imagefilledellipse.php], but using object style:
+You can draw, you can write, you can use all PHP functions for image manipulation, see [#Overview of methods], but in an object-oriented wrapper:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-See [#Overview of Methods].
+Since PHP functions for drawing rectangles are impractical due to specifying coordinates, the `Image` class offers their replacements in the form of functions [#rectangleWH()] and [#filledRectangleWH()].
 
 
 Merge Multiple Images
@@ -200,7 +231,7 @@ You can easily place another image into the image:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // coordinates can be set also in percentage
 $blank->place($logo, '80%', '80%'); // near the right bottom corner
@@ -219,53 +250,68 @@ Overview of Methods
 ===================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Creates a new true color image of the given dimensions. The default color is black.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Reads an image from a file and returns its type in `$detectedFormat`. The supported types are `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` and `Image::BMP`.
+Reads an image from a file and returns its [type|#Formats] in `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Reads an image from a string and returns its type in `$detectedFormat`. The supported types are `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, and `Image::BMP`.
+Reads an image from a string and returns its [type|#Formats] in `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Creates a color that can be used in other methods, such as `ellipse()`, `fill()`, and so on.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+This feature has been replaced by the `ImageColor` class , see [colors |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Returns the file extension for the given `Image::XXX` constant.
+Returns the file extension for the given [type|#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Returns the mime type for the given `Image::XXX` constant.
+Returns the mime type for the given [type|#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Returns the image type as a constant `Image::XXX` according to the file extension.
+Returns the image [type|#Formats] according to the file extension.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Returns the type of image file as `Image::XXX` constant and in the `$width` and `$height` parameters also its dimensions.
+Returns the [type|#Formats] of image file and in the `$width` and `$height` parameters also its dimensions.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Returns the type of image from string as `Image::XXX` constant and in the `$width` and `$height` parameters also its dimensions.
+Returns the [type|#Formats] of image from string and in the `$width` and `$height` parameters also its dimensions.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Determines if the given image [type|#Formats] is supported.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Returns an array of supported image [types|#Formats].
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Calculates the dimensions of the rectangle that encloses the text in a specified font and size. It returns an associative array containing the keys `left`, `top`, `width`, `height`. The left margin can be negative if the text starts with a left overhang.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Return an image containing the affine transformed src image, using an optional clipping area. ([more|https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Returns the concatenation of two affine transformation matrices, what is useful if multiple transformations should be applied to the same image in one go. ([more|https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Returns an affine transformation matrix. ([more|https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Activate the fast drawing antialiased methods for lines and wired polygons. It d
 Using antialiased primitives with transparent background color can end with some unexpected results. The blend method uses the background color as any other colors. The lack of alpha component support does not allow an alpha based antialiasing method. ([more|https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Draws an arc of circle centered at the given coordinates. ([more|https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Draws the first character of `$char` in the image with its upper-left at `$x`,`$y` (top left is 0, 0) with the color `$color`. ([more|https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Draws the character `$char` vertically at the specified coordinate on the given image. ([more|https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Returns a color identifier representing the color composed of the given RGB components. It must be called to create each color that is to be used in the image. ([more|https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Returns the number of colors in an image palette. ([more|https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Gets or sets the transparent color in the image. ([more|https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Crops an image to the given rectangular area. Dimensions can be passed as integers in pixels or strings in percent (i.e. `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Automatically crops an image according to the given `$mode`. ([more|https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Draws an ellipse centered at the specified coordinates. ([more|https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Performs a flood fill starting at the given coordinate (top left is 0, 0) with the given `$color` in the image. ([more|https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Draws a partial arc centered at the specified coordinate in the image. ([more|https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Draws an ellipse centered at the specified coordinate in the image. ([more|https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Creates a filled polygon in the $image. ([more|https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Creates a rectangle filled with `$color` in the image starting at point 1 and ending at point 2. 0, 0 is the top left corner of the image. ([more|https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Creates a rectangle filled with `$color` in the image starting at `$x1` & `$y1` and ending at `$x2` & `$y2`. Point 0, 0 is the top left corner of the image. ([more |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Creates a rectangle filled with `$color` in the image starting from point `$left` & `$top` with width `$width` and height `$height`. Point 0, 0 is the top left corner of the image.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Performs a flood fill whose border color is defined by `$border`. The starting point for the fill is `$x`, `$y` (top left is 0, 0) and the region is filled with color `$color`. ([more|https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Flips the image using the given `$mode`. ([more|https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Write text to the image using fonts using FreeType 2. ([more|https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Write the text in the picture. ([more |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Returns the width of the image.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Turns the interlace bit on or off. If the interlace bit is set and the image is used as a JPEG image, the image is created as a progressive JPEG. ([more|https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Set the alpha blending flag to use layering effects. ([more|https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Draws a line between the two given points. ([more|https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Draws an open polygon on the image. Contrary to `polygon()`, no line is drawn between the last and the first point. ([more|https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Copies `$image` to the image at the coordinates `$left` and `$top`. Coordinates can be passed as integers in pixels or strings in percent (i.e. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Creates a polygon in the image. ([more|https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Creates a rectangle starting at the specified coordinates. ([more|https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Creates a rectangle at the given coordinates.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Scales an image, see [more info|#Image Resize]. Dimensions can be passed as integers in pixels or strings in percent (i.e. `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Allows to set and get the resolution of an image in DPI (dots per inch). If none of the optional parameters is given, the current resolution is returned as indexed array. If only `$resX` is given, the horizontal and vertical resolution are set to this value. If both optional parameters are given, the horizontal and vertical resolution are set to these values, respectively.
 
 The resolution is only used as meta information when images are read from and written to formats supporting this kind of information (curently PNG and JPEG). It does not affect any drawing operations. The default resolution for new images is 96 DPI. ([more|https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Rotates the image using the given `$angle` in degrees. The center of rotation is
 Requires *Bundled GD extension*, so it is not sure it will work everywhere.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Saves an image to a file.
 
-The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). If the type is not obvious from the file extension, you can specify it using one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, and `Image::BMP`.
+The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). If the type is not obvious from the file extension, you can specify it using one of the `ImageType` constants.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Scales an image using the given interpolation algorithm. ([more|https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Outputs an image to the browser.
 
-The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). Type is one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` and `Image::BMP`.
+The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Sets the interpolation method which affects methods `rotate()` and `affine()`. ([more|https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Draws a pixel at the specified coordinate. ([more|https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Sharpens image a little bit.
 Requires *Bundled GD extension*, so it is not sure it will work everywhere.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Draws a string at the given coordinates. ([more|https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Draws a string vertically at the given coordinates. ([more|https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Outputs an image to string.
 
-The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). Type is one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` and `Image::BMP`.
+The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Converts a truecolor image to a palette image. ([more|https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Writes the given text into the image using TrueType fonts. ([more|https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Writes the given text into the image. ([more |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/en/iterables.texy b/utils/en/iterables.texy
new file mode 100644
index 0000000000..75378c2b87
--- /dev/null
+++ b/utils/en/iterables.texy
@@ -0,0 +1,170 @@
+Iterator Functions
+******************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] is a static class with functions for working with iterators. Its counterpart for arrays is [Nette\Utils\Arrays|arrays].
+
+
+Installation:
+
+```shell
+composer require nette/utils
+```
+
+All examples assume the following alias is created:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Searches for a given value in an iterator. Uses strict comparison (`===`) to check for a match. Returns `true` if the value is found, otherwise `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+This method is useful when you need to quickly determine if a specific value is present in an iterator without manually iterating through all elements.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Searches for a given key in an iterator. Uses strict comparison (`===`) to check for a match. Returns `true` if the key is found, otherwise `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Checks if all elements of the iterator satisfy the condition defined in `$predicate`. The function `$predicate` has the signature `function ($value, $key, iterable $iterable): bool` and must return `true` for every element for the `every()` method to return `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+This method is useful for verifying that all elements in a collection meet a certain condition, such as whether all numbers are below a specific value.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Creates a new iterator that contains only the elements from the original iterator that satisfy the condition defined in `$predicate`. The function `$predicate` has the signature `function ($value, $key, iterable $iterable): bool` and must return `true` for elements that should be retained.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+The method uses a generator, meaning that filtering occurs incrementally during iteration. This is memory efficient and allows for handling very large collections. If you do not iterate through all elements of the resulting iterator, you save computational effort since not all elements of the original iterator are processed.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Returns the first element of the iterator. If `$predicate` is provided, it returns the first element that satisfies the given condition. The function `$predicate` has the signature `function ($value, $key, iterable $iterable): bool`. If no matching element is found, the `$else` function (if provided) is called and its result is returned. If `$else` is not provided, `null` is returned.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+This method is useful when you need to quickly retrieve the first element of a collection or the first element that meets a certain condition without manually iterating through the entire collection.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Returns the key of the first element of the iterator. If `$predicate` is provided, it returns the key of the first element that satisfies the given condition. The function `$predicate` has the signature `function ($value, $key, iterable $iterable): bool`. If no matching element is found, the `$else` function (if provided) is called and its result is returned. If `$else` is not provided, `null` is returned.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Creates a new iterator by applying the `$transformer` function to each element of the original iterator. The function `$transformer` has the signature `function ($value, $key, iterable $iterable): mixed` and its return value is used as the new value of the element.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+The method uses a generator, meaning that the transformation occurs incrementally during iteration. This is memory efficient and allows for handling very large collections. If you do not iterate through all elements of the resulting iterator, you save computational effort since not all elements of the original iterator are processed.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Creates a new iterator by transforming the values and keys of the original iterator. The function `$transformer` has the signature `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. If `$transformer` returns `null`, the element is skipped. For retained elements, the first element of the returned array is used as the new key and the second element as the new value.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Like `map()`, this method uses a generator for incremental processing and memory efficiency. This allows working with large collections and saving computational effort by processing only part of the result.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Creates a wrapper around an iterator that caches its keys and values during iteration. This allows for repeated iteration over the data without having to reprocess the original data source.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+This method is useful in situations where you need to iterate over the same set of data multiple times, but the original iterator does not support repeated iteration or repeated iteration would be costly (e.g., reading data from a database or file).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Checks if at least one element of the iterator satisfies the condition defined in `$predicate`. The function `$predicate` has the signature `function ($value, $key, iterable $iterable): bool` and must return `true` for at least one element for the `some()` method to return `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+This method is useful for quickly verifying if there is at least one element in a collection that meets a certain condition, such as whether the collection contains at least one even number.
+
+See [#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Converts any iterable object (array, Traversable) to an Iterator. If the input is already an Iterator, it is returned unchanged.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+This method is useful when you need to ensure that you have an Iterator, regardless of the input data type. This can be useful when creating functions that work with different types of iterable data.
diff --git a/utils/en/json.texy b/utils/en/json.texy
index f29024378f..b806869757 100644
--- a/utils/en/json.texy
+++ b/utils/en/json.texy
@@ -77,7 +77,7 @@ Setting `$forceArray` forces the return of arrays instead of objects:
 
 ```php
 Json::decode('{"variable": true}'); // returns an object of type stdClass
-Json::decode('{"variable": true}', forceArray: true); // returns an array
+Json::decode('{"variable": true}', forceArrays: true); // returns an array
 ```
 
 It throws an `Nette\Utils\JsonException` exception on error.
diff --git a/utils/en/smartobject.texy b/utils/en/smartobject.texy
index f53fde130d..27ec6370bb 100644
--- a/utils/en/smartobject.texy
+++ b/utils/en/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject and StaticClass
-***************************
+SmartObject
+***********
 
 .[perex]
-SmartObject adds support for *property* to PHP classes. StaticClass is used to denote static classes.
+SmartObject used to fix objects behavior in many ways, but today's PHP already includes most of these improvements natively. However, it still adds support for *properties*.
 
 
 Installation:
@@ -65,31 +65,16 @@ echo $circle->visible; // calls isVisible()
 Properties are primarily "syntactic sugar"((syntactic sugar)), which is intended to make the programmer's life sweeter by simplifying the code. If you don't want them, you don't have to use them.
 
 
-Static Classes
-==============
+A Glimpse into History
+======================
 
-Static classes, i.e. classes that are not intended to be instantiated, can be marked with the trait `Nette\StaticClass`:
+SmartObject used to refine the behavior of objects in numerous ways, but today's PHP already incorporates most of these enhancements natively. The following text is a nostalgic look back at history, reminding us of how things evolved.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-When you try to create an instance, the `Error` exception is thrown, indicating that the class is static.
-
-
-A Look into the History
-=======================
-
-SmartObject used to improve and fix class behavior in many ways, but the evolution of PHP has made most of the original features redundant. So the following is a look into the history of how things have evolved.
-
-From the beginning, the PHP object model suffered from a number of serious flaws and inefficiencies. This was the reason for the creation of the `Nette\Object` class (in 2007), which attempted to remedy them and improve the experience of using PHP. It was enough for other classes to inherit from it, and gain the benefits it brought. When PHP 5.4 came with trait support, the `Nette\Object` class was replaced by `Nette\SmartObject`. Thus, it was no longer necessary to inherit from a common ancestor. In addition, trait could be used in classes that already inherited from another class. The final end of `Nette\Object` came with the release of PHP 7.2, which forbade classes to be named `Object`.
+From its inception, PHP's object model suffered from a myriad of serious shortcomings and deficiencies. This led to the creation of the `Nette\Object` class (in 2007), which aimed to rectify these issues and enhance the comfort of using PHP. All that was needed was for other classes to inherit from it, and they would gain the benefits it offered. When PHP 5.4 introduced support for traits, the `Nette\Object` class was replaced by the `Nette\SmartObject` trait. This eliminated the need to inherit from a common ancestor. Moreover, the trait could be used in classes that already inherited from another class. The definitive end of `Nette\Object` came with the release of PHP 7.2, which prohibited classes from being named `Object`.
 
-As PHP development went on, the object model and language capabilities were improved. The individual functions of the `SmartObject` class became redundant. Since the release of PHP 8.2, the only feature that remains that is not yet directly supported in PHP is the ability to use so-called [properties |#Properties, Getters and Setters].
+As PHP development continued, its object model and language capabilities improved. Various functions of the `SmartObject` class became redundant. Since the release of PHP 8.2, there remains only one feature not directly supported in PHP: the ability to use so-called [properties|#Properties, getters, and setters].
 
-What features did `Nette\Object` and `Nette\Object` once offer? Here is an overview. (The examples use the `Nette\Object` class, but most of the properties also apply to the `Nette\SmartObject` trait.)
+What features did `Nette\Object` and, by extension, `Nette\SmartObject` offer? Here's an overview. (In the examples, the `Nette\Object` class is used, but most features also apply to the `Nette\SmartObject` trait).
 
 
 Inconsistent Errors
@@ -102,14 +87,14 @@ $obj->undeclared = 1;  // passes silently without reporting
 $obj->unknownMethod(); // Fatal error (not catchable by try/catch)
 ```
 
-Fatal error terminated the application without any possibility to react. Silently writing to non-existent members without warning could lead to serious errors that were difficult to detect. `Nette\Object` All of these cases were caught and an exception `MemberAccessException` was thrown.
+A fatal error would terminate the application without any chance of response. Silently writing to non-existent members without warning could lead to serious errors that were hard to detect. `Nette\Object` caught all these cases and threw a `MemberAccessException` exception.
 
 ```php
-echo $obj->undeclared;   // throw Nette\MemberAccessException
-$obj->undeclared = 1;    // throw Nette\MemberAccessException
-$obj->unknownMethod();   // throw Nette\MemberAccessException
+echo $obj->undeclared;   // throws Nette\MemberAccessException
+$obj->undeclared = 1;    // throws Nette\MemberAccessException
+$obj->unknownMethod();   // throws Nette\MemberAccessException
 ```
-Since PHP 7.0, PHP no longer causes not catchable fatal errors, and accessing undeclared members has been a bug since PHP 8.2.
+From PHP version 7.0 onwards, uncatchable fatal errors no longer occur, and accessing undeclared members becomes an error from PHP 8.2.
 
 
 Did you mean?
@@ -125,16 +110,16 @@ class Foo extends Nette\Object
 }
 
 $foo = Foo::form($var);
-// throw Nette\MemberAccessException
+// throws Nette\MemberAccessException
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Today's PHP may not have any form of "did you mean?", but [Tracy |tracy:] adds this addendum to errors. And it can even [fix |tracy:open-files-in-ide#toc-demos] such errors itself.
+While today's PHP doesn't have a "did you mean?" feature, this phrase can be added to errors by [Tracy|tracy:]. It can even [auto-correct such errors|tracy:open-files-in-ide#toc-demos].
 
 
-Extension methods
+Extension Methods
 -----------------
-Inspired by extension methods from C#. They gave the possibility to add new methods to existing classes. For example, you could add the `addDateTime()` method to a form to add your own DateTimePicker.
+Inspired by the extension methods from the C# language, they provided the ability to add new methods to existing classes. For instance, you could add a `addDateTime()` method to a form, which would introduce a custom DateTimePicker.
 
 ```php
 Form::extensionMethod(
@@ -146,15 +131,15 @@ $form = new Form;
 $form->addDateTime('date');
 ```
 
-Extension methods proved to be impractical because their names was not autocompleted by editors, instead they reported that the method did not exist. Therefore, their support was discontinued.
+Extension methods turned out to be impractical because their names were not suggested by editors; on the contrary, they reported that the method did not exist. Therefore, their support was discontinued.
 
 
-Getting the Class Name
-----------------------
+Determining the Class Name
+--------------------------
 
 ```php
 $class = $obj->getClass(); // using Nette\Object
-$class = $obj::class;      // since PHP 8.0
+$class = $obj::class;      // from PHP 8.0
 ```
 
 
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // returns 'John Doe
+$reflection->getAnnotation('author'); // returns 'John Doe'
 ```
 
 As of PHP 8.0, it is possible to access meta-information in the form of attributes:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
@@ -244,7 +229,7 @@ foreach ($this->onChange as $callback) {
 }
 ```
 
-For the sake of clarity we recommend to avoid the magic method `$this->onChange()`. A practical substitute is the [Nette\Utils\Arrays::invoke |arrays#invoke] function:
+For clarity, we recommend avoiding the magic method `$this->onChange()`. A practical alternative is the [Nette\Utils\Arrays::invoke |arrays#invoke] function:
 
 ```php
 Nette\Utils\Arrays::invoke($this->onChange, $this, $radius);
diff --git a/utils/en/staticclass.texy b/utils/en/staticclass.texy
new file mode 100644
index 0000000000..73054c0420
--- /dev/null
+++ b/utils/en/staticclass.texy
@@ -0,0 +1,21 @@
+Static Classes
+**************
+
+.[perex]
+StaticClass is used to denote static classes.
+
+
+Installation:
+
+```shell
+composer require nette/utils
+```
+
+Static classes, i.e. classes that are not intended to be instantiated, can be marked with the trait [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/en/strings.texy b/utils/en/strings.texy
index cea37f2e31..56d87c6c3e 100644
--- a/utils/en/strings.texy
+++ b/utils/en/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modifies the UTF-8 string to the form used in the URL, ie removes diacritics and replaces all characters except letters of the English alphabet and numbers with a hyphens.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Requires PHP extension `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Removes all left and right side spaces (or the characters passed as second argument) from a UTF-8 encoded string.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Returns a part of UTF-8 string specified by starting position `$start` and length `$length`. If `$start` is negative, the returned string will start at the `$start`'th character from the end of string.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Use native `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Compares two UTF-8 strings or their parts, without taking character case into account. If `$length` is null, whole strings are compared, if it is negative, the corresponding number of characters from the end of the strings is compared, otherwise the appropriate number of characters from the beginning is compared.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Searches the string for all occurrences matching the regular expression and returns an array of arrays containing the found expression and each subexpression.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+If `$lazy` is `true`, the function returns a `Generator` instead of an array, which provides significant performance benefits when working with large strings. The generator allows for matches to be found incrementally, rather than processing the entire string at once. This enables efficient handling of extremely large input texts. Additionally, you can interrupt processing at any time if you find the desired match, saving computational time.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/en/upgrading.texy b/utils/en/upgrading.texy
new file mode 100644
index 0000000000..359a158261
--- /dev/null
+++ b/utils/en/upgrading.texy
@@ -0,0 +1,34 @@
+Upgrading
+*********
+
+
+Migrating from 3.x to 4.0
+=========================
+
+Minimum required PHP version is 8.0.
+
+The `Nette\Utils\Reflection` class provided methods `getParameterType()`, `getPropertyType()` and `getReturnType()` for working with the types. These methods were created when PHP didn't have union, intersection or the newest disjunctive normal form types, which they no longer work with and were replaced by the [Type class |utils:type]. As of version 4.0, these methods have been removed.
+
+The method `Nette\Utils\Reflection::getParameterDefaultValue()` is deprecated because the native `ReflectionParameter::getDefaultValue()` already works correctly.
+
+The `Nette\Utils\Html::$xhtml` variable is removed.
+
+
+Finder
+------
+
+Finder has moved to the `nette/utils` package, remove the original package:
+
+```shell
+composer remove nette/finder
+```
+
+On Linux, it now behaves in case-sensitive mode.
+
+In the previous version, the `exclude()` and `filter()` methods worked differently when called **before** `from()` and `in()` respectively, and **after** it. This is no longer the case, `exclude()` and `filter()` always work the same. The former `filter()` called *before* has been replaced by the new `descentFilter()` method.
+
+The Finder no longer implements the Countable interface.
+
+A string starting with a slash in `Finder::findFiles('/f*')` is now considered an absolute path, it should be replaced with e.g. `Finder::findFiles('./f*')`.
+
+When directory you are searching in does not exist, `Nette\InvalidStateException` is thrown (instead of `UnexpectedValueException`).
diff --git a/utils/en/validators.texy b/utils/en/validators.texy
index 937d9cec1f..570a4b0eac 100644
--- a/utils/en/validators.texy
+++ b/utils/en/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Verifies that element `$key` in array `$array` is of [#expected types] separated by pipe. If not, it throws exception [api:Nette\Utils\AssertionException]. The string `item '%' in array` in the exception message can be replaced by parameter `$label`.
 
diff --git a/utils/es/@home.texy b/utils/es/@home.texy
index f54df2b0d8..13358a81fd 100644
--- a/utils/es/@home.texy
+++ b/utils/es/@home.texy
@@ -13,13 +13,14 @@ En el paquete `nette/utils` encontrará un conjunto de clases útiles para el us
 | [Generación de cadenas aleatorias |random] | Nette\Utils\Random
 | [Generar código HTML |html-elements] | Nette\Utils\Html
 | [Generar PHP Reflection |reflection] | Nette\Utils\Reflection
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [Imágenes |Images] | Nette\Utils\Image
 | [JSON] | Nette\Utils\Json
 | [Matrices |Arrays] | Nette\Utils\Arrays
-| [Modelo de objeto |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginador |Paginator] | Nette\Utils\Paginator
 | [Sistema de archivos |filesystem] | Nette\Utils\FileSystem
 | [Tipos |type] | Nette\Utils\Type
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validadores |Validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | versión | compatible con PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/es/@left-menu.texy b/utils/es/@left-menu.texy
index 9948ca0769..efa56faafc 100644
--- a/utils/es/@left-menu.texy
+++ b/utils/es/@left-menu.texy
@@ -8,13 +8,15 @@ Paquete nette/utils
 - [Fecha y hora |datetime]
 - [Flotadores |Floats]
 - [Funciones auxiliares |helpers]
+- [Iterables |iterables]
 - [Imágenes |Images]
 - [JSON]
 - [Matrices |Arrays]
-- [Objeto inteligente |SmartObject]
 - [Paginador |paginator]
 - [Reflexión PHP |reflection]
 - [Sistema de archivos |filesystem]
+- [SmartObject]
+- [StaticClass]
 - [Tipos de PHP |type]
 - [Validadores |validators]
 
diff --git a/utils/es/arrays.texy b/utils/es/arrays.texy
index a393e4b351..3d5c85fc99 100644
--- a/utils/es/arrays.texy
+++ b/utils/es/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] es una clase estática que contiene un puñado de prácticas funciones de array.
+[api:Nette\Utils\Arrays] es una clase estática, que contiene un puñado de prácticas funciones de array. Su equivalente para iteradores es [Nette\Utils\Iterables |iterables].
 
 Los siguientes ejemplos asumen que el siguiente alias de clase está definido:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+La función transforma de forma flexible la `$array` en una matriz asociativa u objetos según la ruta especificada `$path`. La ruta puede ser una cadena o una matriz. Consiste en los nombres de las claves de la matriz de entrada y operadores como '[]', '->', '=' y '|'. Lanza `Nette\InvalidArgumentException` si la ruta no es válida.
+
+```php
+// conversión a array asociativo utilizando una clave simple
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// asignar valores de una clave a otra mediante el operador =
+$result = Arrays::associate($arr, 'name=age'); // o ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// crear un objeto utilizando el operador ->
+$result = Arrays::associate($arr, '->name'); // o ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// combinación de claves mediante el operador |
+$result = Arrays::associate($arr, 'name|age'); // o ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// añadir a un array usando []
+$result = Arrays::associate($arr, 'name[]'); // o ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Comprueba si todos los elementos de la matriz pasan la prueba implementada por la función proporcionada, que tiene la firma `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Véase [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Devuelve una nueva matriz que contiene todos los pares clave-valor que coinciden con la dirección `$predicate`. La llamada de retorno tiene la firma `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Devuelve el primer elemento del array o null si el array está vacío. No cambia el puntero interno a diferencia de `reset()`.
+Devuelve el primer elemento (que coincida con el predicado especificado si se da). Si no existe tal elemento, devuelve el resultado de invocar `$else` o null.
+El `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`.
+
+No modifica el puntero interno, a diferencia de `reset()`. Los parámetros `$predicate` y `$else` existen desde la versión 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Véase [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Devuelve la clave del primer elemento (que coincida con el predicado especificado si se da) o null si no existe tal elemento. `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Véase [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Devuelve `$array[$key]` item. Si no existe, se lanza `Nette\InvalidArgumentException`, a menos que se establezca un valor por defecto como tercer argumento.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Devuelve el último elemento (que coincida con el predicado especificado si se da). Si no existe tal elemento, devuelve el resultado de invocar `$else` o null.
+El `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`.
+
+No modifica el puntero interno, a diferencia de `end()`. Los parámetros `$predicate` y `$else` existen desde la versión 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Véase [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Devuelve el último elemento del array o null si el array está vacío. No cambia el puntero interno a diferencia de `end()`.
+Devuelve la clave del último elemento (que coincida con el predicado especificado si se da) o null si no existe tal elemento. `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Véase [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Llama a `$callback` en todos los elementos de la matriz y devuelve la matriz de valores de retorno. La llamada de retorno tiene la firma `function ($value, $key, array $array): bool`.
+Llama a `$transformer` en todos los elementos de la matriz y devuelve la matriz de valores de retorno. La llamada de retorno tiene la firma `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Crea un nuevo array transformando los valores y claves del array original. La función `$transformer` tiene la firma `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Si `$transformer` devuelve `null`, el elemento se omite. Para los elementos retenidos, el primer elemento de la matriz devuelta se utiliza como la nueva clave y el segundo elemento como el nuevo valor.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Este método es útil en situaciones en las que se necesita cambiar la estructura de una matriz (tanto claves como valores simultáneamente) o filtrar elementos durante la transformación (devolviendo null para los elementos no deseados).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Los valores de la segunda matriz se añaden siempre a la primera. La desaparición del valor `10` de la segunda matriz puede parecer un poco confusa. Debe tenerse en cuenta que este valor, así como el valor `5` in the first array have the same numeric key `0`, por lo que en el campo resultante sólo hay un elemento de la primera matriz.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normaliza array a array asociativo. Sustituye las claves numéricas por sus valores, el nuevo valor será `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Devuelve y elimina el valor de un elemento de un array. Si no existe, lanza una excepción, o devuelve `$default`, si se proporciona.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Comprueba si al menos un elemento de la matriz supera la prueba implementada por la llamada de retorno proporcionada con la firma `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Convierte cada elemento del array en cadena y lo encierra con `$prefix` y `$suffix`.
 
diff --git a/utils/es/datetime.texy b/utils/es/datetime.texy
index d3d11dd8bf..ea40b4fbc3 100644
--- a/utils/es/datetime.texy
+++ b/utils/es/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Amplía [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] con la posibilidad de especificar una zona horaria como cadena.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create with custom timezone
diff --git a/utils/es/filesystem.texy b/utils/es/filesystem.texy
index f7f914d42b..e3cd23b683 100644
--- a/utils/es/filesystem.texy
+++ b/utils/es/filesystem.texy
@@ -2,9 +2,11 @@ Funciones del sistema de archivos
 *********************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] es una clase estática, que contiene funciones útiles para trabajar con un sistema de archivos. Una ventaja sobre las funciones nativas de PHP es que lanzan excepciones en caso de errores.
+[api:Nette\Utils\FileSystem] es una clase que contiene funciones útiles para trabajar con un sistema de archivos. Una ventaja sobre las funciones nativas de PHP es que lanzan excepciones en caso de errores.
 
 
+Si necesitas buscar archivos en el disco, utiliza el [Finder |finder].
+
 Instalación:
 
 ```shell
@@ -174,3 +176,26 @@ Convierte las barras inclinadas en caracteres específicos de la plataforma actu
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Enfoque estático frente a no estático .[#toc-static-vs-non-static-approach]
+===========================================================================
+
+Para reemplazar fácilmente la clase `FileSystem` por otra clase, por ejemplo para realizar pruebas, utilícela de forma no estática:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/es/finder.texy b/utils/es/finder.texy
index 04afe3c631..88d9e64cdb 100644
--- a/utils/es/finder.texy
+++ b/utils/es/finder.texy
@@ -61,6 +61,8 @@ Una alternativa a los métodos estáticos es crear una instancia utilizando `new
 
 Puede utilizar [comodines |#wildcards] `*`, `**`, `?` and `[...]` en la máscara. Incluso puede especificar en directorios, por ejemplo `src/*.php` buscará todos los archivos PHP en el directorio `src`.
 
+Los enlaces simbólicos también se consideran directorios o archivos.
+
 
 ¿Dónde buscar? .[#toc-where-to-search]
 --------------------------------------
diff --git a/utils/es/floats.texy b/utils/es/floats.texy
index 71989a6346..bfdf458cfa 100644
--- a/utils/es/floats.texy
+++ b/utils/es/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Al intentar comparar `NAN`, lanza una excepción `\LogicException`.
 
+.[tip]
+La clase `Floats` tolera diferencias inferiores a `1e-10`. Si necesita trabajar con más precisión, utilice en su lugar la biblioteca BCMath.
+
 
 Comparación de flotadores .[#toc-float-comparison]
 ==================================================
diff --git a/utils/es/html-elements.texy b/utils/es/html-elements.texy
index 553f1c2cdf..b035a402fd 100644
--- a/utils/es/html-elements.texy
+++ b/utils/es/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Otra forma de crear e insertar un nuevo nodo `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/es/images.texy b/utils/es/images.texy
index 2f9f140d87..6ea7247313 100644
--- a/utils/es/images.texy
+++ b/utils/es/images.texy
@@ -17,6 +17,8 @@ Los siguientes ejemplos suponen que se ha definido el siguiente alias de clase:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Opcionalmente, puede especificar un color de fondo (por defecto es negro):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 O cargamos la imagen desde un archivo:
@@ -41,17 +43,6 @@ O cargamos la imagen desde un archivo:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Los formatos soportados son JPEG, PNG, GIF, WebP, AVIF y BMP, pero su versión de PHP también debe soportarlos (compruebe la `phpinfo()`, sección GD). No se admiten animaciones.
-
-¿Necesita detectar el formato de la imagen al cargarla? El método devuelve el formato en el segundo parámetro:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type es Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF o Image::BMP
-```
-
-Sólo la detección sin carga de la imagen se realiza mediante `Image::detectTypeFromFile()`.
-
 
 Guardar la imagen .[#toc-save-the-image]
 ========================================
@@ -68,25 +59,45 @@ Podemos especificar la calidad de compresión en el rango 0..100 para JPEG (por
 $image->save('resampled.jpg', 80); // JPEG, quality 80%
 ```
 
-Si el formato no resulta obvio a partir de la extensión del archivo, puede especificarse mediante una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`:
+Si el formato no es obvio a partir de la extensión del archivo, puede especificarse mediante [una constante |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 La imagen puede escribirse en una variable en lugar de en el disco:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, quality 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, quality 80%
 ```
 
 o enviar directamente al navegador con el encabezado HTTP apropiado `Content-Type`:
 
 ```php
 // sends header Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formatos .[#toc-formats]
+========================
+
+Los formatos soportados son JPEG, PNG, GIF, WebP, AVIF y BMP. Sin embargo, también deben ser soportados por su versión de PHP, lo cual puede ser verificado usando la función [isTypeSupported() |#isTypeSupported()]. Las animaciones no están soportadas.
+
+Los formatos están representados por las constantes `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, y `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+¿Necesita detectar el formato de una imagen al cargarla? El método lo devuelve en el segundo parámetro:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+La detección real sin cargar la imagen la realiza `Image::detectTypeFromFile()`.
+
 
 Redimensionar imagen .[#toc-image-resize]
 =========================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 El método `cropAuto()` es una encapsulación de objeto de la función `imagecropauto()`, consulte [su documentación |https://www.php.net/manual/en/function.imagecropauto] para obtener más información.
 
 
+Colores .[#toc-colors]
+======================
+
+El método `ImageColor::rgb()` le permite definir un color utilizando los valores rojo, verde y azul (RGB). Opcionalmente, también puede especificar un valor de transparencia que va de 0 (completamente transparente) a 1 (completamente opaco), igual que en CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+El método `ImageColor::hex()` permite definir un color utilizando el formato hexadecimal, de forma similar a CSS. Admite los formatos `#rgb`, `#rrggbb`, `#rgba`, y `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Los colores pueden utilizarse en otros métodos, como `ellipse()`, `fill()`, etc.
+
+
 Dibujo y edición .[#toc-drawing-and-editing]
 ============================================
 
-Puedes dibujar, puedes escribir, puedes usar todas las funciones PHP para trabajar con imágenes, como [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], pero usando el estilo objeto:
+Puedes dibujar, puedes escribir, puedes usar todas las funciones PHP para la manipulación de imágenes, ver [Resumen de métodos |#Overview of methods], pero en una envoltura orientada a objetos:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Véase el [resumen de métodos |#Overview of Methods].
+Dado que las funciones PHP para dibujar rectángulos son poco prácticas debido a la especificación de coordenadas, la clase `Image` ofrece sus sustitutos en forma de funciones [rectangleWH() |#rectangleWH()] y [filledRectangleWH() |#filledRectangleWH()].
 
 
 Fusionar varias imágenes .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Puedes colocar fácilmente otra imagen dentro de la imagen:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // coordinates can be set also in percentage
 $blank->place($logo, '80%', '80%'); // near the right bottom corner
@@ -219,53 +250,68 @@ Métodos .[#toc-overview-of-methods]
 ===================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Crea una nueva imagen en color verdadero de las dimensiones dadas. El color por defecto es el negro.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Lee una imagen de un archivo y devuelve su tipo en `$detectedFormat`. Los tipos admitidos son `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`.
+Lee una imagen de un archivo y devuelve su [tipo |#Formats] en `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Lee una imagen de una cadena y devuelve su tipo en `$detectedFormat`. Los tipos admitidos son `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`.
+Lee una imagen de una cadena y devuelve su [tipo |#Formats] en `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Crea un color que puede utilizarse en otros métodos, como `ellipse()`, `fill()`, etc.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Esta función ha sido sustituida por la clase `ImageColor`, ver [colores |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Devuelve la extensión de archivo para la constante `Image::XXX` dada.
+Devuelve la extensión de archivo para el [tipo |#Formats] dado.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Devuelve el tipo mime para la constante `Image::XXX` dada.
+Devuelve el tipo mime para el [tipo |#Formats] dado.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Devuelve el tipo de imagen como una constante `Image::XXX` según la extensión del archivo.
+Devuelve el [tipo de |#Formats] imagen según la extensión del archivo.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Devuelve el tipo de archivo de imagen como constante `Image::XXX` y en los parámetros `$width` y `$height` también sus dimensiones.
+Devuelve el [tipo |#Formats] de archivo de imagen y en los parámetros `$width` y `$height` también sus dimensiones.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Devuelve el tipo de imagen a partir de la cadena como constante `Image::XXX` y en los parámetros `$width` y `$height` también sus dimensiones.
+Devuelve el [tipo |#Formats] de imagen a partir de la cadena y en los parámetros `$width` y `$height` también sus dimensiones.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Determina si el [tipo de |#Formats] imagen dado es compatible.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Devuelve un array de tipos de imagen soportados (constantes `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Calcula las dimensiones del rectángulo que encierra el texto en una fuente y tamaño especificados. Devuelve una matriz asociativa que contiene las claves `left`, `top`, `width`, `height`. El margen izquierdo puede ser negativo si el texto comienza con un saliente a la izquierda.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Devuelve una imagen que contiene la imagen src transformada afinadamente, utilizando un área de recorte opcional. ([más |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Devuelve la concatenación de dos matrices de transformación afín, lo que resulta útil si deben aplicarse múltiples transformaciones a la misma imagen de una sola vez. ([más |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Devuelve una matriz de transformación afín. ([más |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Activa los métodos de dibujo rápido antialiasing para líneas y polígonos al
 El uso de primitivas con antialiasing y color de fondo transparente puede dar lugar a resultados inesperados. El método de mezcla utiliza el color de fondo como cualquier otro color. La falta de soporte de componentes alfa no permite un método de antialiasing basado en alfa. ([más |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Dibuja un arco de círculo centrado en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Dibuja el primer carácter de `$char` en la imagen con su parte superior izquierda en `$x`,`$y` (la parte superior izquierda es 0, 0) con el color `$color`. ([más |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Dibuja el carácter `$char` verticalmente en la coordenada especificada en la imagen dada. ([más |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Devuelve un identificador de color que representa el color compuesto por los componentes RGB dados. Debe llamarse para crear cada color que se vaya a utilizar en la imagen. ([más |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Devuelve el número de colores de una paleta de imágenes ([más |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Obtiene o establece el color transparente de la imagen. ([más |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Recorta una imagen en el área rectangular dada. Las dimensiones pueden pasarse como números enteros en píxeles o cadenas en porcentaje (es decir, `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Recorta automáticamente una imagen según la dirección `$mode`. ([más |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Dibuja una elipse centrada en las coordenadas especificadas. ([más |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Realiza un relleno de inundación comenzando en la coordenada dada (arriba a la izquierda es 0, 0) con el `$color` dado en la imagen. ([más |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Dibuja un arco parcial centrado en la coordenada especificada en la imagen. ([más |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Dibuja una elipse centrada en la coordenada especificada en la imagen. ([más |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Crea un polígono relleno en la $imagen. ([más |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Crea un rectángulo relleno con `$color` en la imagen comenzando en el punto 1 y terminando en el punto 2. 0, 0 es la esquina superior izquierda de la imagen. ([más |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Crea un rectángulo relleno con `$color` en la imagen comenzando en `$x1` & `$y1` y terminando en `$x2` & `$y2`. El punto 0, 0 es la esquina superior izquierda de la imagen. ([más |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Crea un rectángulo relleno de `$color` en la imagen a partir del punto `$left` & `$top` con anchura `$width` y altura `$height`. El punto 0, 0 es la esquina superior izquierda de la imagen.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Realiza un relleno de inundación cuyo color de borde está definido por `$border`. El punto de partida del relleno es `$x`, `$y` (arriba a la izquierda es 0, 0) y la región se rellena con el color `$color`. ([más |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Voltea la imagen utilizando la dirección `$mode`. ([más |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Escribe texto en la imagen utilizando fuentes con FreeType 2. ([más |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Escribe el texto de la imagen. ([más |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Devuelve la anchura de la imagen.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Activa o desactiva el bit de entrelazado. Si el bit de entrelazado está activado y la imagen se utiliza como imagen JPEG, la imagen se crea como JPEG progresivo. ([más |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Establezca la bandera de mezcla alfa para utilizar efectos de estratificación. ([más |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Dibuja una línea entre los dos puntos dados. ([más |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Dibuja un polígono abierto en la imagen. Contrariamente a `polygon()`, no se traza ninguna línea entre el último y el primer punto. ([más |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Copia `$image` en la imagen en las coordenadas `$left` y `$top`. Las coordenadas pueden pasarse como números enteros en píxeles o cadenas en porcentaje (es decir, `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Crea un polígono en la imagen. ([más |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Crea un rectángulo que comienza en las coordenadas especificadas. ([más |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Crea un rectángulo en las coordenadas dadas.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Escala una imagen, ver [más info |#Image Resize]. Las dimensiones pueden pasarse como números enteros en píxeles o cadenas en porcentaje (es decir, `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Permite establecer y obtener la resolución de una imagen en PPP (puntos por pulgada). Si no se proporciona ninguno de los parámetros opcionales, se devuelve la resolución actual como matriz indexada. Si sólo se indica `$resX`, la resolución horizontal y vertical se ajustan a este valor. Si se dan ambos parámetros opcionales, la resolución horizontal y vertical se fijan en estos valores, respectivamente.
 
 La resolución sólo se utiliza como metainformación cuando las imágenes se leen y escriben en formatos que admiten este tipo de información (actualmente PNG y JPEG). No afecta a ninguna operación de dibujo. La resolución por defecto para las nuevas imágenes es de 96 PPP. ([más |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Rota la imagen utilizando la dirección `$angle` en grados. El centro de rotaci
 Requiere la extensión *Bundled GD*, por lo que no es seguro que funcione en todas partes.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Guarda una imagen en un archivo.
 
-La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). Si el tipo no es obvio a partir de la extensión del archivo, puede especificarlo utilizando una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, y `Image::BMP`.
+La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). Si el tipo no es obvio a partir de la extensión del archivo, puede especificarlo utilizando una de las constantes de `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Escala una imagen utilizando el algoritmo de interpolación dado. ([más |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Envía una imagen al navegador.
 
-La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). El tipo es una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`.
+La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Establece el método de interpolación que afecta a los métodos `rotate()` y `affine()`. ([más |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Dibuja un píxel en la coordenada especificada. ([más |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Enfoca un poco la imagen.
 Requiere la extensión *Bundled GD*, por lo que no es seguro que funcione en todas partes.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Dibuja una cadena en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Dibuja una cadena verticalmente en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Muestra una imagen en una cadena.
 
-La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). El tipo es una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`.
+La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Convierte una imagen truecolor en una imagen de paleta. ([más |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Escribe el texto dado en la imagen utilizando fuentes TrueType. ([más |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Escribe el texto dado en la imagen. ([más |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/es/iterables.texy b/utils/es/iterables.texy
new file mode 100644
index 0000000000..8307fa4871
--- /dev/null
+++ b/utils/es/iterables.texy
@@ -0,0 +1,170 @@
+Funciones de iteración
+**********************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] es una clase estática con funciones para trabajar con iteradores. Su contrapartida para arrays es [Nette\Utils\Arrays |arrays].
+
+
+Instalación:
+
+```shell
+composer require nette/utils
+```
+
+Todos los ejemplos suponen que se ha creado el siguiente alias:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Busca un valor dado en un iterador. Utiliza la comparación estricta (`===`) para buscar una coincidencia. Devuelve `true` si se encuentra el valor, en caso contrario `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Este método es útil cuando se necesita determinar rápidamente si un valor específico está presente en un iterador sin iterar manualmente a través de todos los elementos.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Busca una clave dada en un iterador. Utiliza la comparación estricta (`===`) para buscar una coincidencia. Devuelve `true` si se encuentra la clave, en caso contrario `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Comprueba si todos los elementos del iterador cumplen la condición definida en `$predicate`. La función `$predicate` tiene la firma `function ($value, $key, iterable $iterable): bool` y debe devolver `true` para cada elemento para que el método `every()` devuelva `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Este método es útil para verificar que todos los elementos de una colección cumplen una determinada condición, como por ejemplo si todos los números están por debajo de un valor específico.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Crea un nuevo iterador que contiene sólo los elementos del iterador original que satisfacen la condición definida en `$predicate`. La función `$predicate` tiene la firma `function ($value, $key, iterable $iterable): bool` y debe devolver `true` para los elementos que deben conservarse.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+El método utiliza un generador, lo que significa que el filtrado se produce de forma incremental durante la iteración. Esto es eficiente en memoria y permite manejar colecciones muy grandes. Si no se itera por todos los elementos del iterador resultante, se ahorra esfuerzo computacional, ya que no se procesan todos los elementos del iterador original.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Devuelve el primer elemento del iterador. Si se proporciona `$predicate`, devuelve el primer elemento que satisface la condición dada. La función `$predicate` tiene la firma `function ($value, $key, iterable $iterable): bool`. Si no se encuentra ningún elemento coincidente, se llama a la función `$else` (si se proporciona) y se devuelve su resultado. Si no se proporciona `$else`, se devuelve `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Este método es útil cuando se necesita recuperar rápidamente el primer elemento de una colección o el primer elemento que cumple una determinada condición sin iterar manualmente por toda la colección.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Devuelve la clave del primer elemento del iterador. Si se proporciona `$predicate`, devuelve la clave del primer elemento que satisface la condición dada. La función `$predicate` tiene la firma `function ($value, $key, iterable $iterable): bool`. Si no se encuentra ningún elemento coincidente, se llama a la función `$else` (si se proporciona) y se devuelve su resultado. Si no se proporciona `$else`, se devuelve `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Crea un nuevo iterador aplicando la función `$transformer` a cada elemento del iterador original. La función `$transformer` tiene la firma `function ($value, $key, iterable $iterable): mixed` y su valor de retorno se utiliza como el nuevo valor del elemento.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+El método utiliza un generador, lo que significa que la transformación se produce de forma incremental durante la iteración. Esto es eficiente en memoria y permite manejar colecciones muy grandes. Si no se itera por todos los elementos del iterador resultante, se ahorra esfuerzo computacional, ya que no se procesan todos los elementos del iterador original.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Crea un nuevo iterador transformando los valores y claves del iterador original. La función `$transformer` tiene la firma `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Si `$transformer` devuelve `null`, el elemento se omite. Para los elementos retenidos, el primer elemento del array devuelto se utiliza como la nueva clave y el segundo elemento como el nuevo valor.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Al igual que `map()`, este método utiliza un generador para el procesamiento incremental y la eficiencia de memoria. Esto permite trabajar con grandes colecciones y ahorrar esfuerzo computacional procesando sólo una parte del resultado.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Crea una envoltura alrededor de un iterador que almacena en caché sus claves y valores durante la iteración. Esto permite repetir la iteración sobre los datos sin tener que reprocesar la fuente de datos original.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Este método es útil en situaciones en las que se necesita iterar sobre el mismo conjunto de datos varias veces, pero el iterador original no soporta la iteración repetida o la iteración repetida sería costosa (por ejemplo, la lectura de datos de una base de datos o archivo).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Comprueba si al menos un elemento del iterador cumple la condición definida en `$predicate`. La función `$predicate` tiene la firma `function ($value, $key, iterable $iterable): bool` y debe devolver `true` para al menos un elemento para que el método `some()` devuelva `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Este método es útil para verificar rápidamente si hay al menos un elemento en una colección que cumpla una determinada condición, como por ejemplo si la colección contiene al menos un número par.
+
+Véase [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Convierte cualquier objeto iterable (array, Traversable) en un Iterator. Si la entrada ya es un Iterador, se devuelve sin cambios.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Este método es útil cuando necesitas asegurarte de que tienes un Iterator, independientemente del tipo de datos de entrada. Esto puede ser útil cuando se crean funciones que trabajan con diferentes tipos de datos iterables.
diff --git a/utils/es/json.texy b/utils/es/json.texy
index 1b4cd3ee45..d431de77f1 100644
--- a/utils/es/json.texy
+++ b/utils/es/json.texy
@@ -77,7 +77,7 @@ Establecer `$forceArray` fuerza la devolución de arrays en lugar de objetos:
 
 ```php
 Json::decode('{"variable": true}'); // devuelve un objeto de tipo stdClass
-Json::decode('{"variable": true}', forceArray: true); // devuelve un array
+Json::decode('{"variable": true}', forceArrays: true); // devuelve un array
 ```
 
 Lanza una excepción `Nette\Utils\JsonException` en caso de error.
diff --git a/utils/es/smartobject.texy b/utils/es/smartobject.texy
index b8824ec24d..b3b4cbc5b3 100644
--- a/utils/es/smartobject.texy
+++ b/utils/es/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject y StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject añade soporte para *propiedades* a las clases PHP. StaticClass se utiliza para denotar clases estáticas.
+SmartObject solía arreglar el comportamiento de los objetos de muchas maneras, pero el PHP actual ya incluye la mayoría de estas mejoras de forma nativa. Sin embargo, aún añade soporte para *property*.
 
 
 Instalación:
@@ -65,31 +65,16 @@ echo $circle->visible; // calls isVisible()
 Las propiedades son principalmente "azúcar sintáctico"((syntactic sugar)), que pretende hacer la vida del programador más dulce simplificando el código. Si no las quieres, no tienes por qué usarlas.
 
 
-Clases estáticas .[#toc-static-classes]
-=======================================
+Un vistazo a la Historia .[#toc-a-glimpse-into-history]
+=======================================================
 
-Las clases estáticas, es decir, las clases que no están destinadas a ser instanciadas, pueden marcarse con el rasgo `Nette\StaticClass`:
+SmartObject solía refinar el comportamiento de los objetos de numerosas maneras, pero el PHP actual ya incorpora la mayoría de estas mejoras de forma nativa. El siguiente texto es una mirada nostálgica a la historia, recordándonos como evolucionaron las cosas.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Cuando se intenta crear una instancia, se lanza la excepción `Error`, indicando que la clase es estática.
-
-
-Un vistazo a la historia .[#toc-a-look-into-the-history]
-========================================================
-
-SmartObject solía mejorar y arreglar el comportamiento de las clases de muchas maneras, pero la evolución de PHP ha hecho que la mayoría de las características originales sean redundantes. Así que lo siguiente es una mirada a la historia de cómo han evolucionado las cosas.
-
-Desde el principio, el modelo de objetos de PHP sufrió de un número de serios defectos e ineficiencias. Este fue el motivo de la creación de la clase `Nette\Object` (en 2007), que intentaba remediarlos y mejorar la experiencia de uso de PHP. Fue suficiente para que otras clases heredaran de ella y obtuvieran los beneficios que aportaba. Cuando PHP 5.4 llegó con soporte para traits, la clase `Nette\Object` fue reemplazada por `Nette\SmartObject`. Así, ya no era necesario heredar de un ancestro común. Además, trait podía usarse en clases que ya heredaban de otra clase. El fin definitivo de `Nette\Object` llegó con el lanzamiento de PHP 7.2, que prohibió que las clases se llamaran `Object`.
+Desde sus inicios, el modelo de objetos de PHP sufrió de una miríada de serios defectos y deficiencias. Esto llevó a la creación de la clase `Nette\Object` (en 2007), que pretendía rectificar estos problemas y mejorar la comodidad de uso de PHP. Todo lo que se necesitaba era que otras clases heredaran de ella, y obtendrían los beneficios que ofrecía. Cuando PHP 5.4 introdujo el soporte para traits, la clase `Nette\Object` fue reemplazada por el trait `Nette\SmartObject`. Esto eliminó la necesidad de heredar de un ancestro común. Además, el trait podía ser usado en clases que ya heredaban de otra clase. El fin definitivo de `Nette\Object` llegó con el lanzamiento de PHP 7.2, que prohibió que las clases se llamaran `Object`.
 
-A medida que avanzaba el desarrollo de PHP, el modelo de objetos y las capacidades del lenguaje fueron mejorando. Las funciones individuales de la clase `SmartObject` se volvieron redundantes. Desde el lanzamiento de PHP 8.2, la única característica que aún no está soportada directamente en PHP es la capacidad de usar las llamadas [propiedades |#Properties, getters and setters].
+A medida que el desarrollo de PHP continuaba, su modelo de objetos y las capacidades del lenguaje mejoraron. Varias funciones de la clase `SmartObject` se volvieron redundantes. Desde el lanzamiento de PHP 8.2, sólo queda una característica no soportada directamente en PHP: la capacidad de usar las llamadas [propiedades |#Properties, getters, and setters].
 
-¿Qué características ofrecían `Nette\Object` y `Nette\Object`? He aquí un resumen. (Los ejemplos usan la clase `Nette\Object`, pero la mayoría de las propiedades también se aplican al rasgo `Nette\SmartObject` ).
+¿Qué características ofrecían `Nette\Object` y, por extensión, `Nette\SmartObject`? He aquí un resumen. (En los ejemplos, se usa la clase `Nette\Object`, pero la mayoría de las características también se aplican al rasgo `Nette\SmartObject` ).
 
 
 Errores incoherentes .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Puede que el PHP actual no tenga ninguna forma de "¿querías decir?", pero [Tracy |tracy:] añade este apéndice a los errores. E incluso puede [corregir |tracy:open-files-in-ide#toc-demos] esos errores por sí mismo.
+Aunque el PHP actual no tiene la función "¿Querías decir?", esta frase puede ser añadida a los errores por [Tracy |tracy:]. Incluso puede [autocorregir dichos errores |tracy:open-files-in-ide#toc-demos].
 
 
 Métodos de extensión .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // returns 'John Doe
+$reflection->getAnnotation('author'); // returns 'John Doe'
 ```
 
 A partir de PHP 8.0, es posible acceder a meta-información en forma de atributos:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/es/staticclass.texy b/utils/es/staticclass.texy
new file mode 100644
index 0000000000..c2f7bc35fc
--- /dev/null
+++ b/utils/es/staticclass.texy
@@ -0,0 +1,21 @@
+Clases estáticas
+****************
+
+.[perex]
+StaticClass se utiliza para denotar clases estáticas.
+
+
+Instalación:
+
+```shell
+composer require nette/utils
+```
+
+Las clases estáticas, es decir, las clases que no están destinadas a ser instanciadas, pueden marcarse con el rasgo [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/es/strings.texy b/utils/es/strings.texy
index 97a3af980b..e850cea5fa 100644
--- a/utils/es/strings.texy
+++ b/utils/es/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modifica la cadena UTF-8 a la forma utilizada en la URL, es decir, elimina los diacríticos y sustituye todos los caracteres excepto las letras del alfabeto inglés y los números por un guión.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Requiere la extensión PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Elimina todos los espacios a la izquierda y a la derecha (o los caracteres pasados como segundo argumento) de una cadena codificada en UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Devuelve una parte de la cadena UTF-8 especificada por la posición inicial `$start` y la longitud `$length`. Si `$start` es negativo, la cadena devuelta comenzará en el carácter `$start`'th desde el final de la cadena.
 
@@ -266,8 +266,8 @@ Strings::length('red');   // 3
 \--
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Compara dos cadenas UTF-8 o sus partes, sin tener en cuenta las mayúsculas y minúsculas. Si `$length` es nulo, se comparan cadenas enteras; si es negativo, se compara el número correspondiente de caracteres desde el final de las cadenas; en caso contrario, se compara el número correspondiente de caracteres desde el principio.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Busca en la cadena todas las ocurrencias que coincidan con la expresión regular y devuelve una matriz de matrices que contiene la expresión encontrada y cada subexpresión.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Si `$lazy` es `true`, la función devuelve un `Generator` en lugar de una matriz, lo que proporciona importantes ventajas de rendimiento cuando se trabaja con cadenas de gran tamaño. El generador permite encontrar coincidencias de forma incremental, en lugar de procesar toda la cadena a la vez. Esto permite trabajar con textos de entrada de gran tamaño. Además, puede interrumpir el procesamiento en cualquier momento si encuentra la coincidencia deseada, lo que ahorra tiempo de cálculo.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/es/validators.texy b/utils/es/validators.texy
index a01a9ce39c..b45e6fa841 100644
--- a/utils/es/validators.texy
+++ b/utils/es/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Verifica que el elemento `$key` en el array `$array` es de los [tipos esperados |#expected types] separados por una tubería. Si no es así, lanza la excepción [api:Nette\Utils\AssertionException]. La cadena `item '%' in array` del mensaje de excepción puede sustituirse por el parámetro `$label`.
 
diff --git a/utils/fr/@home.texy b/utils/fr/@home.texy
index f96f963d94..7d16be9d5d 100644
--- a/utils/fr/@home.texy
+++ b/utils/fr/@home.texy
@@ -13,13 +13,14 @@ Dans le paquetage `nette/utils`, vous trouverez un ensemble de classes utiles po
 | [Chaînes de caractères |Strings] | Nette\Utils\Strings
 | [Images] | Nette\Utils\Image
 | [JSON] | Nette\Utils\Json
-| [Modèle d'objet |smartobject] | Nette\SmartObject & Nette\StaticClass
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [Finder] | Nette\Utils\Finder
 | [Paginateur |Paginator] | Nette\Utils\Paginator
 | [PHP Reflection |reflection] | Nette\Utils\Reflection
 | [Système de fichiers |filesystem] | Nette\Utils\FileSystem
 | [Tableaux |Arrays] | Nette\Utils\Arrays
 | [Types |type] | Nette\Utils\Type
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validateurs |Validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | version | compatible avec PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/fr/@left-menu.texy b/utils/fr/@left-menu.texy
index 8b9a577cae..93efe1a2b7 100644
--- a/utils/fr/@left-menu.texy
+++ b/utils/fr/@left-menu.texy
@@ -8,13 +8,15 @@ Paquet net/utils
 - [Chaînes aléatoires |random]
 - [Chaînes de caractères |Strings]
 - [Images]
+- [Itérables |iterables]
 - [JSON]
 - [Paginateur |paginator]
 - [PHP Reflection |reflection]
 - [Retour d'appel |Callback]
-- [SmartObject]
 - [Système de fichiers |filesystem]
 - [Tableaux |Arrays]
+- [SmartObject]
+- [StaticClass]
 - [Types PHP |type]
 - [Validateurs |validators]
 
diff --git a/utils/fr/arrays.texy b/utils/fr/arrays.texy
index 7d94514953..4c47586166 100644
--- a/utils/fr/arrays.texy
+++ b/utils/fr/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Matrices .[#toc-arrays]
 =======================
 
-[api:Nette\Utils\Arrays] est une classe statique, qui contient une poignée de fonctions pratiques pour les tableaux.
+[api:Nette\Utils\Arrays] est une classe statique qui contient une poignée de fonctions pratiques pour les tableaux. Son équivalent pour les itérateurs est [Nette\Utils\Iterables |iterables].
 
 Les exemples suivants supposent que l'alias de classe suivant est défini :
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+La fonction transforme de manière flexible le fichier `$array` en un tableau associatif ou en objets selon le chemin spécifié `$path`. Le chemin peut être une chaîne ou un tableau. Il se compose des noms des clés du tableau d'entrée et d'opérateurs tels que "[]", "->", "=" et "|". Lance `Nette\InvalidArgumentException` si le chemin n'est pas valide.
+
+```php
+// conversion en tableau associatif à l'aide d'une simple clé
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// l'affectation de valeurs d'une clé à une autre à l'aide de l'opérateur =.
+$result = Arrays::associate($arr, 'name=age'); // ou ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// création d'un objet à l'aide de l'opérateur ->
+$result = Arrays::associate($arr, '->name'); // ou ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// combiner des clés à l'aide de l'opérateur |
+$result = Arrays::associate($arr, 'name|age'); // ou ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// ajouter à un tableau en utilisant []
+$result = Arrays::associate($arr, 'name[]'); // ou ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Teste si tous les éléments du tableau passent le test implémenté par la fonction fournie, qui a la signature `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Voir [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Renvoie un nouveau tableau contenant toutes les paires clé-valeur correspondant à l'adresse `$predicate`. Le rappel a la signature `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Retourne le premier élément du tableau ou null si le tableau est vide. Elle ne modifie pas le pointeur interne contrairement à `reset()`.
+Renvoie le premier élément (correspondant au prédicat spécifié s'il est donné). S'il n'y a pas d'élément de ce type, il renvoie le résultat de l'invocation de `$else` ou null.
+Le site `$predicate` a la signature `function ($value, int|string $key, array $array): bool`.
+
+Il ne modifie pas le pointeur interne, contrairement à `reset()`. Les paramètres `$predicate` et `$else` existent depuis la version 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Voir [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Renvoie la clé du premier élément (correspondant au prédicat spécifié s'il est donné) ou null s'il n'y a pas d'élément de ce type. La signature de `$predicate` est `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Voir [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Retourne `$array[$key]` item. S'il n'existe pas, `Nette\InvalidArgumentException` est lancé, sauf si une valeur par défaut est définie comme troisième argument.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Renvoie le dernier élément (correspondant au prédicat spécifié, le cas échéant). S'il n'existe pas d'élément de ce type, il renvoie le résultat de l'invocation de `$else` ou null.
+Le site `$predicate` a la signature `function ($value, int|string $key, array $array): bool`.
+
+Il ne modifie pas le pointeur interne, contrairement à `end()`. Les paramètres `$predicate` et `$else` existent depuis la version 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Voir [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Retourne le dernier élément du tableau ou null si le tableau est vide. Elle ne modifie pas le pointeur interne contrairement à `end()`.
+Renvoie la clé du dernier élément (correspondant au prédicat spécifié s'il est donné) ou null s'il n'y a pas d'élément de ce type. La signature de `$predicate` est `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Voir [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Appelle `$callback` sur tous les éléments du tableau et renvoie le tableau des valeurs de retour. Le callback a la signature `function ($value, $key, array $array): bool`.
+Appelle `$transformer` sur tous les éléments du tableau et renvoie le tableau des valeurs de retour. Le callback a la signature `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Crée un nouveau tableau en transformant les valeurs et les clés du tableau original. La fonction `$transformer` a pour signature `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Si `$transformer` renvoie `null`, l'élément est ignoré. Pour les éléments conservés, le premier élément du tableau retourné est utilisé comme nouvelle clé et le deuxième élément comme nouvelle valeur.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Cette méthode est utile dans les situations où vous devez modifier la structure d'un tableau (à la fois les clés et les valeurs) ou filtrer les éléments au cours de la transformation (en renvoyant null pour les éléments non souhaités).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Les valeurs du deuxième tableau sont toujours ajoutées au premier. La disparition de la valeur `10` du deuxième tableau peut sembler un peu déroutante. Il convient de noter que cette valeur, ainsi que la valeur `5` in the first array have the same numeric key `0`, font que dans le champ résultant, il n'y a qu'un élément du premier tableau.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalise le tableau en tableau associatif. Remplacez les clés numériques par leurs valeurs, la nouvelle valeur sera `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Renvoie et supprime la valeur d'un élément d'un tableau. S'il n'existe pas, il lève une exception, ou renvoie `$default`, s'il est fourni.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Teste si au moins un élément du tableau passe le test implémenté par la callback fournie avec la signature `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Il transforme chaque élément du tableau en chaîne de caractères et l'entoure de `$prefix` et `$suffix`.
 
diff --git a/utils/fr/datetime.texy b/utils/fr/datetime.texy
index 912c12aa0a..19f6c6811f 100644
--- a/utils/fr/datetime.texy
+++ b/utils/fr/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Extends [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] avec la possibilité de spécifier un fuseau horaire comme une chaîne de caractères.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // créer avec un fuseau horaire personnalisé
diff --git a/utils/fr/filesystem.texy b/utils/fr/filesystem.texy
index a8aceb487f..19a148c11f 100644
--- a/utils/fr/filesystem.texy
+++ b/utils/fr/filesystem.texy
@@ -2,9 +2,11 @@ Fonctions du système de fichiers
 ********************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] est une classe statique, qui contient des fonctions utiles pour travailler avec un système de fichiers. Un avantage par rapport aux fonctions natives de PHP est qu'elles lèvent des exceptions en cas d'erreurs.
+[api:Nette\Utils\FileSystem] est une classe qui contient des fonctions utiles pour travailler avec un système de fichiers. Un avantage par rapport aux fonctions natives de PHP est qu'elles lèvent des exceptions en cas d'erreur.
 
 
+Si vous devez rechercher des fichiers sur le disque, utilisez le [Finder |finder].
+
 Installation :
 
 ```shell
@@ -174,3 +176,26 @@ Convertit les barres obliques en caractères spécifiques à la plate-forme actu
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Approche statique ou non statique .[#toc-static-vs-non-static-approach]
+=======================================================================
+
+Pour remplacer facilement la classe `FileSystem` par une autre classe, par exemple à des fins de test, utilisez-la de manière non statique :
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/fr/finder.texy b/utils/fr/finder.texy
index c846adf89c..c4b7682126 100644
--- a/utils/fr/finder.texy
+++ b/utils/fr/finder.texy
@@ -61,6 +61,8 @@ Une alternative aux méthodes statiques est de créer une instance à l'aide de
 
 Vous pouvez utiliser des [caractères génériques |#wildcards] `*`, `**`, `?` and `[...]` dans le masque. Vous pouvez même spécifier des répertoires, par exemple `src/*.php` recherchera tous les fichiers PHP dans le répertoire `src`.
 
+Les liens symboliques sont également considérés comme des répertoires ou des fichiers.
+
 
 Où chercher ? .[#toc-where-to-search]
 -------------------------------------
diff --git a/utils/fr/floats.texy b/utils/fr/floats.texy
index 0ae4e0fd11..60824eb5d3 100644
--- a/utils/fr/floats.texy
+++ b/utils/fr/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Lorsque l'on essaie de comparer `NAN`, une exception `\LogicException` est levée.
 
+.[tip]
+La classe `Floats` tolère des différences inférieures à `1e-10`. Si vous devez travailler avec plus de précision, utilisez plutôt la bibliothèque BCMath.
+
 
 Comparaison de flottants .[#toc-float-comparison]
 =================================================
diff --git a/utils/fr/html-elements.texy b/utils/fr/html-elements.texy
index fa92fa6979..5518ed6434 100644
--- a/utils/fr/html-elements.texy
+++ b/utils/fr/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Une autre façon de créer et d'insérer un nouveau nœud `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/fr/images.texy b/utils/fr/images.texy
index 94e3677f74..92610af862 100644
--- a/utils/fr/images.texy
+++ b/utils/fr/images.texy
@@ -17,6 +17,8 @@ Les exemples suivants supposent que l'alias de classe suivant est défini :
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 En option, vous pouvez spécifier une couleur de fond (noir par défaut) :
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Ou nous chargeons l'image depuis un fichier :
@@ -41,17 +43,6 @@ Ou nous chargeons l'image depuis un fichier :
 $image = Image::fromFile('nette.jpg');
 ```
 
-Les formats pris en charge sont JPEG, PNG, GIF, WebP, AVIF et BMP, mais votre version de PHP doit également les prendre en charge (consultez le site `phpinfo()`, section GD). Les animations ne sont pas prises en charge.
-
-Vous avez besoin de détecter le format de l'image lors du chargement ? La méthode renvoie le format dans le deuxième paramètre :
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type est Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ou Image::BMP
-```
-
-Seule la détection sans chargement de l'image est effectuée par `Image::detectTypeFromFile()`.
-
 
 Sauvegarder l'image .[#toc-save-the-image]
 ==========================================
@@ -68,25 +59,45 @@ Nous pouvons spécifier une qualité de compression comprise entre 0 et 100 pour
 $image->save('resampled.jpg', 80); // JPEG, qualité 80
 ```
 
-Si le format ne ressort pas clairement de l'extension du fichier, il peut être spécifié par l'une des constantes suivantes : `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, et `Image::BMP`:
+Si le format ne ressort pas clairement de l'extension du fichier, il peut être spécifié par une [constante |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 L'image peut être écrite dans une variable plutôt que sur le disque :
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, qualité 80%.
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, qualité 80%.
 ```
 
 ou envoyer directement au navigateur avec l'en-tête HTTP approprié `Content-Type`:
 
 ```php
 // envoie l'en-tête Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formats .[#toc-formats]
+=======================
+
+Les formats supportés sont JPEG, PNG, GIF, WebP, AVIF et BMP. Cependant, ils doivent également être supportés par votre version de PHP, ce qui peut être vérifié à l'aide de la fonction [isTypeSupported() |#isTypeSupported()]. Les animations ne sont pas prises en charge.
+
+Les formats sont représentés par les constantes `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, et `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Besoin de détecter le format d'une image au chargement ? La méthode le renvoie dans le second paramètre :
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+La détection proprement dite, sans chargement de l'image, est effectuée par `Image::detectTypeFromFile()`.
+
 
 Redimensionnement de l'image .[#toc-image-resize]
 =================================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 La méthode `cropAuto()` est une encapsulation objet de la fonction `imagecropauto()`, voir [sa documentation |https://www.php.net/manual/en/function.imagecropauto] pour plus d'informations.
 
 
+Couleurs .[#toc-colors]
+=======================
+
+La méthode `ImageColor::rgb()` permet de définir une couleur à l'aide des valeurs rouge, vert et bleu (RVB). En option, vous pouvez également spécifier une valeur de transparence allant de 0 (complètement transparent) à 1 (complètement opaque), comme dans les CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+La méthode `ImageColor::hex()` vous permet de définir une couleur en utilisant le format hexadécimal, comme dans CSS. Elle prend en charge les formats `#rgb`, `#rrggbb`, `#rgba`, et `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Les couleurs peuvent être utilisées dans d'autres méthodes, telles que `ellipse()`, `fill()`, etc.
+
+
 Dessin et édition .[#toc-drawing-and-editing]
 =============================================
 
-Vous pouvez dessiner, vous pouvez écrire, vous pouvez utiliser toutes les fonctions PHP pour travailler avec des images, comme [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], mais en utilisant le style objet :
+Vous pouvez dessiner, vous pouvez écrire, vous pouvez utiliser toutes les fonctions PHP pour la manipulation d'images, voir [Aperçu des méthodes |#Overview of methods], mais dans une enveloppe orientée objet :
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Voir l'[aperçu des méthodes |#Overview of Methods].
+Puisque les fonctions PHP pour dessiner des rectangles ne sont pas pratiques en raison de la spécification des coordonnées, la classe `Image` offre leurs remplacements sous la forme de fonctions [rectangleWH() |#rectangleWH()] et [filledRectangleWH() |#filledRectangleWH()].
 
 
 Fusionner plusieurs images .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Vous pouvez facilement placer une autre image dans l'image :
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // les coordonnées peuvent également être définies en pourcentage
 $blank->place($logo, '80%', '80%'); // près du coin inférieur droit de l'image
@@ -219,53 +250,68 @@ Aperçu des méthodes .[#toc-overview-of-methods]
 ===============================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Crée une nouvelle image en couleurs réelles avec les dimensions données. La couleur par défaut est le noir.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Lit une image à partir d'un fichier et renvoie son type à `$detectedFormat`. Les types supportés sont `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` et `Image::BMP`.
+Lit une image à partir d'un fichier et renvoie son [type |#Formats] à `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Lit une image à partir d'une chaîne de caractères et renvoie son type à `$detectedFormat`. Les types supportés sont `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, et `Image::BMP`.
+Lit une image à partir d'une chaîne de caractères et renvoie son [type |#Formats] à `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Crée une couleur qui peut être utilisée dans d'autres méthodes, telles que `ellipse()`, `fill()`, etc.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Cette fonctionnalité a été remplacée par la classe `ImageColor`, voir les [couleurs |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Renvoie l'extension de fichier pour la constante `Image::XXX` donnée.
+Renvoie l'extension du fichier pour le [type |#Formats] donné.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Renvoie le type de mime pour la constante `Image::XXX` donnée.
+Renvoie le type de mime pour le [type |#Formats] donné.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Renvoie le type d'image sous la forme d'une constante `Image::XXX` en fonction de l'extension du fichier.
+Renvoie le [type d' |#Formats] image en fonction de l'extension du fichier.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Renvoie le type de fichier image comme constante `Image::XXX` et dans les paramètres `$width` et `$height` également ses dimensions.
+Renvoie le [type de |#Formats] fichier image et, dans les paramètres `$width` et `$height`, ses dimensions.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Renvoie le type d'image de la chaîne de caractères comme constante `Image::XXX` et dans les paramètres `$width` et `$height` également ses dimensions.
+Renvoie le [type d' |#Formats] image à partir d'une chaîne de caractères et, dans les paramètres `$width` et `$height`, ses dimensions.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Détermine si le [type d' |#Formats] image donné est pris en charge.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Renvoie un tableau des types d'images pris en charge (constantes `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Calcule les dimensions du rectangle qui entoure le texte d'une police et d'une taille spécifiées. Il renvoie un tableau associatif contenant les clés `left`, `top`, `width`, `height`. La marge de gauche peut être négative si le texte commence avec un débordement à gauche.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Renvoie une image contenant l'image src transformée affine, en utilisant une zone de découpage optionnelle. ([plus |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Renvoie la concaténation de deux matrices de transformation affine, ce qui est utile si plusieurs transformations doivent être appliquées à la même image en une seule fois. ([plus |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Retourne une matrice de transformation affine. ([plus |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Activez les méthodes de dessin rapide avec anticrénelage pour les lignes et le
 L'utilisation de primitives anticrénelées avec une couleur de fond transparente peut donner des résultats inattendus. La méthode de fusion utilise la couleur de fond comme n'importe quelle autre couleur. L'absence de prise en charge de la composante alpha ne permet pas d'utiliser une méthode d'anticrénelage basée sur l'alpha. ([plus |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Dessine un arc de cercle centré sur les coordonnées données. ([plus |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Dessine le premier caractère de `$char` dans l'image avec son haut gauche à `$x`,`$y` (haut gauche est 0, 0) avec la couleur `$color`. ([plus |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Dessine le caractère `$char` verticalement à la coordonnée spécifiée sur l'image donnée. ([plus |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Renvoie un identifiant de couleur représentant la couleur composée des composantes RVB données. Elle doit être appelée pour créer chaque couleur qui doit être utilisée dans l'image. ([plus |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Renvoie le nombre de couleurs dans une palette d'images. ([plus |https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Obtient ou définit la couleur transparente de l'image. ([plus |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Recadrer une image dans une zone rectangulaire donnée. Les dimensions peuvent être transmises sous forme d'entiers en pixels ou de chaînes de caractères en pourcentage (par exemple, `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Recadrage automatique d'une image en fonction de l'adresse `$mode`. ([plus |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Dessine une ellipse centrée sur les coordonnées spécifiées. ([plus |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Effectue un remplissage par inondation à partir de la coordonnée donnée (en haut à gauche, c'est 0, 0) avec le `$color` donné dans l'image. ([plus |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Dessine un arc partiel centré sur la coordonnée spécifiée dans l'image. ([plus |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Dessine une ellipse centrée sur la coordonnée spécifiée dans l'image. ([plus |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Crée un polygone rempli dans l'image $. ([plus |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Crée un rectangle rempli de `$color` dans l'image en commençant au point 1 et en terminant au point 2. 0, 0 est le coin supérieur gauche de l'image. ([plus |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Crée un rectangle rempli de `$color` dans l'image commençant à `$x1` & `$y1` et se terminant à `$x2` & `$y2`. Le point 0, 0 est le coin supérieur gauche de l'image. ([plus |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Crée un rectangle rempli de `$color` dans l'image à partir des points `$left` & `$top` avec la largeur `$width` et la hauteur `$height`. Le point 0, 0 est le coin supérieur gauche de l'image.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Effectue un remplissage par inondation dont la couleur de la bordure est définie par `$border`. Le point de départ du remplissage est `$x`, `$y` (en haut à gauche, 0, 0) et la région est remplie de la couleur `$color`. ([plus |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Retourne l'image en utilisant l'adresse `$mode`. ([plus |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Écrivez du texte sur l'image à l'aide de polices de caractères utilisant FreeType 2. ([plus |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Écrivez le texte dans l'image. ([plus |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Renvoie la largeur de l'image.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Active ou désactive le bit d'entrelacement. Si le bit d'entrelacement est activé et que l'image est utilisée comme une image JPEG, l'image est créée comme un JPEG progressif. ([plus |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Définissez le drapeau de mélange alpha pour utiliser les effets de superposition. ([plus |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Trace une ligne entre les deux points donnés. ([plus |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Dessine un polygone ouvert sur l'image. Contrairement à `polygon()`, aucune ligne n'est tracée entre le dernier et le premier point. ([plus |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Copie `$image` sur l'image aux coordonnées `$left` et `$top`. Les coordonnées peuvent être transmises sous forme d'entiers en pixels ou de chaînes de caractères en pourcentage (par exemple `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Crée un polygone dans l'image. ([plus |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Crée un rectangle à partir des coordonnées spécifiées. ([plus |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Crée un rectangle aux coordonnées données.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Mise à l'échelle d'une image, voir [plus d'infos |#Image Resize]. Les dimensions peuvent être transmises sous forme d'entiers en pixels ou de chaînes de caractères en pourcentage (par exemple, `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Permet de définir et d'obtenir la résolution d'une image en DPI (points par pouce). Si aucun des paramètres optionnels n'est donné, la résolution courante est retournée sous forme de tableau indexé. Si seule la valeur `$resX` est donnée, la résolution horizontale et verticale est fixée à cette valeur. Si les deux paramètres facultatifs sont donnés, les résolutions horizontale et verticale sont respectivement définies à ces valeurs.
 
 La résolution est uniquement utilisée comme méta-information lorsque les images sont lues et écrites dans des formats supportant ce type d'information (actuellement PNG et JPEG). Elle n'affecte pas les opérations de dessin. La résolution par défaut des nouvelles images est de 96 DPI. ([plus |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Fait pivoter l'image en utilisant l'adresse `$angle` donnée en degrés. Le cent
 Nécessite *l'extension GD groupée*, il n'est donc pas sûr qu'elle fonctionne partout.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Enregistre une image dans un fichier.
 
-La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Si le type n'est pas évident à partir de l'extension du fichier, vous pouvez le spécifier en utilisant l'une des constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, et `Image::BMP`.
+La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Si le type n'est pas évident à partir de l'extension du fichier, vous pouvez le spécifier en utilisant l'une des constantes `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Met à l'échelle une image en utilisant l'algorithme d'interpolation donné. ([plus |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Affiche une image dans le navigateur.
 
-La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Type est l'une des constantes suivantes : `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` et `Image::BMP`.
+La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Définit la méthode d'interpolation qui affecte les méthodes `rotate()` et `affine()`. ([plus |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Dessine un pixel à la coordonnée spécifiée. ([plus |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Affine un peu l'image.
 Nécessite l'extension *Bundled GD*, il n'est donc pas sûr que cela fonctionne partout.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Dessine une chaîne aux coordonnées données. ([plus |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Dessine une chaîne verticalement aux coordonnées données. ([plus |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Produit une image sous forme de chaîne.
 
-La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Type est l'une des constantes suivantes : `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` et `Image::BMP`.
+La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Convertit une image truecolor en une image palette. ([plus |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Écrit le texte donné dans l'image en utilisant les polices TrueType. ([plus |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Écrit le texte donné dans l'image. ([plus |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/fr/iterables.texy b/utils/fr/iterables.texy
new file mode 100644
index 0000000000..ece43bc2db
--- /dev/null
+++ b/utils/fr/iterables.texy
@@ -0,0 +1,170 @@
+Fonctions de l'itérateur
+************************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] est une classe statique contenant des fonctions permettant de travailler avec des itérateurs. Son équivalent pour les tableaux est [Nette\Utils\Arrays |arrays].
+
+
+L'installation :
+
+```shell
+composer require nette/utils
+```
+
+Tous les exemples supposent que l'alias suivant a été créé :
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Recherche une valeur donnée dans un itérateur. Utilise une comparaison stricte (`===`) pour vérifier la correspondance. Retourne `true` si la valeur est trouvée, sinon `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Cette méthode est utile pour déterminer rapidement si une valeur spécifique est présente dans un itérateur sans avoir à parcourir manuellement tous les éléments.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Recherche une clé donnée dans un itérateur. Utilise une comparaison stricte (`===`) pour vérifier s'il y a une correspondance. Retourne `true` si la clé est trouvée, sinon `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Vérifie si tous les éléments de l'itérateur satisfont à la condition définie dans `$predicate`. La fonction `$predicate` a pour signature `function ($value, $key, iterable $iterable): bool` et doit renvoyer `true` pour chaque élément pour que la méthode `every()` renvoie `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Cette méthode est utile pour vérifier que tous les éléments d'une collection remplissent une certaine condition, par exemple si tous les nombres sont inférieurs à une valeur spécifique.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Crée un nouvel itérateur qui ne contient que les éléments de l'itérateur original qui satisfont à la condition définie dans `$predicate`. La fonction `$predicate` a pour signature `function ($value, $key, iterable $iterable): bool` et doit renvoyer `true` pour les éléments qui doivent être conservés.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+La méthode utilise un générateur, ce qui signifie que le filtrage s'effectue de manière incrémentielle au cours de l'itération. Cette méthode est économe en mémoire et permet de traiter de très grandes collections. Si vous n'itérez pas sur tous les éléments de l'itérateur résultant, vous économisez des efforts de calcul puisque tous les éléments de l'itérateur d'origine ne sont pas traités.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Renvoie le premier élément de l'itérateur. Si `$predicate` est fourni, il renvoie le premier élément qui satisfait à la condition donnée. La fonction `$predicate` a pour signature `function ($value, $key, iterable $iterable): bool`. Si aucun élément correspondant n'est trouvé, la fonction `$else` (si elle est fournie) est appelée et son résultat est renvoyé. Si `$else` n'est pas fourni, `null` est renvoyé.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Cette méthode est utile pour récupérer rapidement le premier élément d'une collection ou le premier élément qui répond à une certaine condition sans avoir à parcourir manuellement l'ensemble de la collection.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Renvoie la clé du premier élément de l'itérateur. Si `$predicate` est fourni, il renvoie la clé du premier élément qui satisfait à la condition donnée. La fonction `$predicate` a pour signature `function ($value, $key, iterable $iterable): bool`. Si aucun élément correspondant n'est trouvé, la fonction `$else` (si elle est fournie) est appelée et son résultat est renvoyé. Si `$else` n'est pas fourni, `null` est renvoyé.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Crée un nouvel itérateur en appliquant la fonction `$transformer` à chaque élément de l'itérateur original. La fonction `$transformer` a pour signature `function ($value, $key, iterable $iterable): mixed` et sa valeur de retour est utilisée comme nouvelle valeur de l'élément.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+La méthode utilise un générateur, ce qui signifie que la transformation se produit de manière incrémentielle au cours de l'itération. Cela permet d'économiser de la mémoire et de traiter de très grandes collections. Si vous n'itérez pas sur tous les éléments de l'itérateur résultant, vous économisez des efforts de calcul puisque tous les éléments de l'itérateur d'origine ne sont pas traités.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Crée un nouvel itérateur en transformant les valeurs et les clés de l'itérateur original. La fonction `$transformer` a pour signature `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Si `$transformer` renvoie `null`, l'élément est ignoré. Pour les éléments conservés, le premier élément du tableau retourné est utilisé comme nouvelle clé et le deuxième élément comme nouvelle valeur.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Comme `map()`, cette méthode utilise un générateur pour le traitement incrémental et l'efficacité de la mémoire. Cela permet de travailler avec de grandes collections et d'économiser l'effort de calcul en ne traitant qu'une partie du résultat.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Crée une enveloppe autour d'un itérateur qui met en cache ses clés et ses valeurs pendant l'itération. Cela permet de répéter l'itération sur les données sans avoir à retraiter la source de données d'origine.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Cette méthode est utile dans les situations où vous devez itérer plusieurs fois sur le même ensemble de données, mais où l'itérateur original ne supporte pas l'itération répétée ou l'itération répétée serait coûteuse (par exemple, la lecture de données à partir d'une base de données ou d'un fichier).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Vérifie si au moins un élément de l'itérateur satisfait à la condition définie dans `$predicate`. La fonction `$predicate` a pour signature `function ($value, $key, iterable $iterable): bool` et doit retourner `true` pour au moins un élément pour que la méthode `some()` retourne `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Cette méthode est utile pour vérifier rapidement si au moins un élément d'une collection remplit une certaine condition, par exemple si la collection contient au moins un nombre pair.
+
+Voir [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Convertit n'importe quel objet itérable (tableau, Traversable) en un Iterator. Si l'entrée est déjà un Iterator, elle est retournée inchangée.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Cette méthode est utile lorsque vous devez vous assurer que vous disposez d'un itérateur, quel que soit le type de données en entrée. Cela peut être utile lors de la création de fonctions qui fonctionnent avec différents types de données itérables.
diff --git a/utils/fr/json.texy b/utils/fr/json.texy
index a01a7e23d9..bbc766dda6 100644
--- a/utils/fr/json.texy
+++ b/utils/fr/json.texy
@@ -77,7 +77,7 @@ Le paramètre `$forceArray` force le retour des tableaux au lieu des objets :
 
 ```php
 Json::decode('{"variable": true}'); // renvoie un objet de type stdClass
-Json::decode('{"variable": true}', forceArray: true); // renvoie un tableau
+Json::decode('{"variable": true}', forceArrays: true); // renvoie un tableau
 ```
 
 Il lance une exception `Nette\Utils\JsonException` en cas d'erreur.
diff --git a/utils/fr/smartobject.texy b/utils/fr/smartobject.texy
index 70d1024e3c..9458d913bb 100644
--- a/utils/fr/smartobject.texy
+++ b/utils/fr/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject et StaticClass
-**************************
+SmartObject
+***********
 
 .[perex]
-SmartObject ajoute le support des *propriétés* aux classes PHP. StaticClass est utilisé pour désigner les classes statiques.
+SmartObject corrigeait le comportement des objets de plusieurs façons, mais le PHP d'aujourd'hui inclut déjà la plupart de ces améliorations de façon native. Cependant, il ajoute encore le support des *propriétés*.
 
 
 Installation :
@@ -65,31 +65,16 @@ echo $circle->visible; // calls isVisible()
 Les propriétés sont principalement du "sucre syntaxique" ((sucre syntaxique)), destiné à rendre la vie du programmeur plus douce en simplifiant le code. Si vous n'en voulez pas, vous n'êtes pas obligé de les utiliser.
 
 
-Classes statiques .[#toc-static-classes]
-========================================
+Un aperçu de l'histoire .[#toc-a-glimpse-into-history]
+======================================================
 
-Les classes statiques, c'est-à-dire les classes qui ne sont pas destinées à être instanciées, peuvent être marquées par le trait `Nette\StaticClass`:
+SmartObject permettait d'affiner le comportement des objets de nombreuses manières, mais le PHP d'aujourd'hui incorpore déjà la plupart de ces améliorations de manière native. Le texte suivant est un regard nostalgique sur l'histoire, nous rappelant comment les choses ont évolué.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Lorsque vous essayez de créer une instance, l'exception `Error` est levée, indiquant que la classe est statique.
-
-
-Un regard sur l'histoire .[#toc-a-look-into-the-history]
-========================================================
-
-SmartObject améliorait et corrigeait le comportement des classes de plusieurs façons, mais l'évolution de PHP a rendu la plupart des fonctionnalités originales superflues. Ce qui suit est donc un regard sur l'histoire de l'évolution des choses.
-
-Dès le début, le modèle objet de PHP a souffert d'un certain nombre de défauts sérieux et d'inefficacités. C'est la raison de la création de la classe `Nette\Object` (en 2007), qui a tenté d'y remédier et d'améliorer l'expérience d'utilisation de PHP. Il a suffi que d'autres classes héritent d'elle pour bénéficier de ses avantages. Lorsque PHP 5.4 a intégré le support des traits, la classe `Nette\Object` a été remplacée par `Nette\SmartObject`. Ainsi, il n'était plus nécessaire d'hériter d'un ancêtre commun. De plus, les traits pouvaient être utilisés dans des classes qui héritaient déjà d'une autre classe. La fin définitive de `Nette\Object` est intervenue avec la sortie de PHP 7.2, qui interdisait aux classes d'être nommées `Object`.
+Dès le début, le modèle objet de PHP a souffert d'une myriade de lacunes et de déficiences. Cela a conduit à la création de la classe `Nette\Object` (en 2007), qui visait à corriger ces problèmes et à améliorer le confort d'utilisation de PHP. Il suffisait que d'autres classes héritent de cette classe pour bénéficier des avantages qu'elle offrait. Lorsque PHP 5.4 a introduit le support des traits, la classe `Nette\Object` a été remplacée par le trait `Nette\SmartObject`. Cela a éliminé le besoin d'hériter d'un ancêtre commun. De plus, le trait pouvait être utilisé dans des classes qui héritaient déjà d'une autre classe. La fin définitive de `Nette\Object` est intervenue avec la publication de PHP 7.2, qui a interdit aux classes d'être nommées `Object`.
 
-Au fur et à mesure du développement de PHP, le modèle objet et les capacités du langage ont été améliorés. Les fonctions individuelles de la classe `SmartObject` sont devenues redondantes. Depuis la version 8.2 de PHP, la seule fonctionnalité qui n'est pas encore directement supportée par PHP est la possibilité d'utiliser des [propriétés |#Properties, getters and setters].
+Au fur et à mesure du développement de PHP, le modèle d'objet et les capacités du langage se sont améliorés. Plusieurs fonctions de la classe `SmartObject` sont devenues redondantes. Depuis la sortie de PHP 8.2, il ne reste plus qu'une seule fonctionnalité non directement supportée par PHP : la possibilité d'utiliser ce que l'on appelle des [propriétés |#Properties, getters, and setters].
 
-Quelles fonctionnalités offraient autrefois `Nette\Object` et `Nette\Object`? En voici un aperçu. (Les exemples utilisent la classe `Nette\Object`, mais la plupart des propriétés s'appliquent également au trait `Nette\SmartObject` ).
+Quelles sont les fonctionnalités offertes par `Nette\Object` et, par extension, par `Nette\SmartObject`? En voici un aperçu. (Dans les exemples, la classe `Nette\Object` est utilisée, mais la plupart des fonctionnalités s'appliquent également au trait `Nette\SmartObject` ).
 
 
 Erreurs de cohérence .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Le PHP d'aujourd'hui n'a peut-être pas de forme de "did you mean ?", mais [Tracy |tracy:] ajoute cet addendum aux erreurs. Et il peut même [corriger |tracy:open-files-in-ide#toc-demos] ces erreurs lui-même.
+Bien que le PHP d'aujourd'hui n'ait pas de fonction "did you mean ?", cette phrase peut être ajoutée aux erreurs par [Tracy |tracy:]. Il peut même [corriger automatiquement ces erreurs |tracy:open-files-in-ide#toc-demos].
 
 
 Méthodes d'extension .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // returns 'John Doe
+$reflection->getAnnotation('author'); // returns 'John Doe'
 ```
 
 Depuis PHP 8.0, il est possible d'accéder aux méta-informations sous forme d'attributs :
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/fr/staticclass.texy b/utils/fr/staticclass.texy
new file mode 100644
index 0000000000..20d426d804
--- /dev/null
+++ b/utils/fr/staticclass.texy
@@ -0,0 +1,21 @@
+Classes statiques
+*****************
+
+.[perex]
+StaticClass est utilisé pour désigner les classes statiques.
+
+
+L'installation :
+
+```shell
+composer require nette/utils
+```
+
+Les classes statiques, c'est-à-dire les classes qui ne sont pas destinées à être instanciées, peuvent être marquées par le trait [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/fr/strings.texy b/utils/fr/strings.texy
index 57fb7eaf41..d10e9c609e 100644
--- a/utils/fr/strings.texy
+++ b/utils/fr/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modifie la chaîne UTF-8 à la forme utilisée dans l'URL, c'est-à-dire supprime les diacritiques et remplace tous les caractères sauf les lettres de l'alphabet anglais et les chiffres par un trait d'union.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Nécessite l'extension PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Supprime tous les espaces à gauche et à droite (ou les caractères passés en second argument) d'une chaîne de caractères encodée en UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Renvoie une partie de la chaîne UTF-8 spécifiée par la position de départ `$start` et la longueur `$length`. Si `$start` est négatif, la chaîne retournée commencera au `$start`'ème caractère à partir de la fin de la chaîne.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Utilise le natif `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Compare deux chaînes de caractères UTF-8 ou leurs parties, sans tenir compte de la casse des caractères. Si `$length` est nul, les chaînes entières sont comparées, s'il est négatif, le nombre correspondant de caractères depuis la fin des chaînes est comparé, sinon le nombre approprié de caractères depuis le début est comparé.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Recherche dans la chaîne toutes les occurrences correspondant à l'expression régulière et renvoie un tableau de tableaux contenant l'expression trouvée et chaque sous-expression.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Si `$lazy` est `true`, la fonction renvoie un `Generator` au lieu d'un tableau, ce qui offre des avantages considérables en termes de performances lorsque l'on travaille avec des chaînes de grande taille. Le générateur permet de trouver les correspondances de manière incrémentielle, plutôt que de traiter l'ensemble de la chaîne en une seule fois. Cela permet de traiter efficacement des textes d'entrée extrêmement volumineux. En outre, vous pouvez interrompre le traitement à tout moment si vous trouvez la correspondance souhaitée, ce qui permet d'économiser du temps de calcul.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/fr/validators.texy b/utils/fr/validators.texy
index 54073869c0..23dfa3ce8a 100644
--- a/utils/fr/validators.texy
+++ b/utils/fr/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Vérifie que l'élément `$key` dans le tableau `$array` est constitué des [types attendus |#expected types] séparés par un pipe. Si ce n'est pas le cas, il lève l'exception [api:Nette\Utils\AssertionException]. La chaîne `item '%' in array` dans le message d'exception peut être remplacée par le paramètre `$label`.
 
diff --git a/utils/hu/@home.texy b/utils/hu/@home.texy
index 9a33f01d4c..739b6393f4 100644
--- a/utils/hu/@home.texy
+++ b/utils/hu/@home.texy
@@ -13,13 +13,14 @@ A `nette/utils` csomagban a mindennapi használatra hasznos osztályok találhat
 | [Segédprogramok |helpers] | Nette\Utils\Helpers
 | [HTML elemek |HTML Elements] | Nette\Utils\Html
 | [Képek |Images] | Nette\Utils\Image
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [JSON |JSON] | Nette\Utils\Json
-| [Objektum modell |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginátor |paginator] | Nette\Utils\Paginátor
 | [PHP Reflection |reflection] | Nette\Utils\Reflection
 | [PHP típusok |type] | Nette\Utils\Type
 | [Véletlenszerű karakterláncok |random] | Nette\Utils\Random
 | [Sztringek |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Érvényesítők |validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | verzió | kompatibilis a PHP-vel
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/hu/@left-menu.texy b/utils/hu/@left-menu.texy
index 7c674c589e..8068605260 100644
--- a/utils/hu/@left-menu.texy
+++ b/utils/hu/@left-menu.texy
@@ -8,13 +8,15 @@ Csomag nette/utils
 - [Segédprogramok |helpers]
 - [HTML elemek |HTML Elements]
 - [Képek |Images]
+- [Iterábilisok |iterables]
 - [JSON |JSON]
 - [Paginátor |paginator]
 - [Véletlenszerű karakterláncok |random]
-- [SmartObject |SmartObject]
 - [PHP reflexió |reflection]
 - [Strings |Strings]
 - [Lebegők |Floats]
+- [SmartObject]
+- [StaticClass]
 - [PHP típusok |type]
 - [Validátorok |validators]
 
diff --git a/utils/hu/arrays.texy b/utils/hu/arrays.texy
index b2efecd091..2a32067acc 100644
--- a/utils/hu/arrays.texy
+++ b/utils/hu/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] egy statikus osztály, amely egy maroknyi praktikus tömbfüggvényt tartalmaz.
+[api:Nette\Utils\Arrays] egy statikus osztály, amely egy maroknyi hasznos tömbfüggvényt tartalmaz. Ennek megfelelője az iterátorok esetében a [Nette\Utils\Iterables |iterables].
 
 A következő példák feltételezik, hogy a következő osztály alias definiálva van:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+A függvény rugalmasan átalakítja a `$array` címet egy asszociatív tömbre vagy objektumokra a megadott útvonalnak megfelelően `$path`. Az útvonal lehet egy karakterlánc vagy egy tömb. A bemeneti tömb kulcsainak nevéből és olyan operátorokból áll, mint a '[]', '->', '=' és '|'. A `Nette\InvalidArgumentException` értéket dobja, ha az elérési útvonal érvénytelen.
+
+```php
+// egyszerű kulcs segítségével asszociatív tömbté alakítás
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// értékek hozzárendelése egyik kulcsról a másikhoz az = operátorral
+$result = Arrays::associate($arr, 'name=age'); // vagy ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// objektum létrehozása a -> operátor használatával
+$result = Arrays::associate($arr, '->name'); // vagy ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// kulcsok kombinálása a | operátorral
+$result = Arrays::associate($arr, 'name|age'); // vagy ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// hozzáadás egy tömbhöz a []
+$result = Arrays::associate($arr, 'name[]'); // vagy ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Megvizsgálja, hogy a tömb minden eleme megfelel-e a megadott függvény által végrehajtott tesztnek, amelynek aláírása `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Lásd [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Visszaad egy új tömböt, amely tartalmazza az összes kulcs-érték párt, amely megfelel a megadott `$predicate`. A visszahívás aláírása `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Visszaadja a tömb első elemét, vagy null, ha a tömb üres. Nem változtatja meg a belső mutatót, ellentétben a `reset()`.
+Visszaadja az első elemet (amely megfelel a megadott predikátumnak, ha megadva van). Ha nincs ilyen elem, akkor a `$else` meghívásának eredményét vagy nullát adja vissza.
+A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`.
+
+Nem változtatja meg a belső mutatót, ellentétben a `reset()`. A `$predicate` és `$else` paraméterek a 4.0.4-es verzió óta léteznek.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Lásd [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Visszaadja az első elem kulcsát (amely megfelel a megadott predikátumnak, ha megadva van), vagy null, ha nincs ilyen elem. A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Lásd [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Visszaadja `$array[$key]` item. Ha nem létezik, akkor a `Nette\InvalidArgumentException` dob, kivéve, ha harmadik argumentumként egy alapértelmezett érték van megadva.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Visszaadja az utolsó elemet (amely megfelel a megadott predikátumnak, ha megadva van). Ha nincs ilyen elem, akkor a `$else` meghívásának eredményét vagy nullát adja vissza.
+A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`.
+
+Nem változtatja meg a belső mutatót, ellentétben a `end()`. A `$predicate` és `$else` paraméterek a 4.0.4-es verzió óta léteznek.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Lásd [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Visszaadja a tömb utolsó elemét vagy nullát, ha a tömb üres. Nem változtatja meg a belső mutatót, ellentétben a `end()`.
+Visszaadja az utolsó elem kulcsát (amely megfelel a megadott predikátumnak, ha meg van adva), vagy null, ha nincs ilyen elem. A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Lásd [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-A `$callback` meghívja a tömb összes elemét, és visszaadja a visszatérési értékek tömbjét. A visszahívás aláírása `function ($value, $key, array $array): bool`.
+A `$transformer` meghívja a tömb összes elemét, és visszaadja a visszatérési értékek tömbjét. A visszahívás aláírása `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Új tömböt hoz létre az eredeti tömb értékeinek és kulcsainak átalakításával. A `$transformer` függvény aláírása: `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Ha a `$transformer` visszatér `null`, az elemet kihagyja. A megtartott elemek esetében a visszaadott tömb első eleme az új kulcs, a második elem pedig az új érték.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Ez a módszer olyan helyzetekben hasznos, amikor egy tömb szerkezetét kell megváltoztatni (egyszerre a kulcsokat és az értékeket), vagy az elemeket kell szűrni az átalakítás során (a nem kívánt elemek nullának visszaadásával).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 A második tömb értékei mindig hozzá lesznek csatolva az elsőhöz. A `10` érték eltűnése a második tömbből kissé zavarónak tűnhet. Meg kell jegyezni, hogy ez az érték, valamint a `5` in the first array have the same numeric key `0`, tehát a kapott mezőben csak egy elem van az első tömbből.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizálja a tömböt asszociatív tömbre. A numerikus kulcsokat kicseréli az értékeikkel, az új érték `$filling` lesz.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Visszaadja és eltávolítja egy elem értékét egy tömbből. Ha nem létezik, akkor kivételt dob, vagy visszaadja a `$default`, ha megadva van.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // nullát ad vissza
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Megvizsgálja, hogy a tömb legalább egy eleme átmegy-e a `function ($value, $key, array $array): bool` aláírással ellátott callback által végrehajtott teszten.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // beállítja $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 A tömb minden egyes elemét karakterlánccá alakítja, és a `$prefix` és a `$suffix` objektummal körülveszi.
 
diff --git a/utils/hu/datetime.texy b/utils/hu/datetime.texy
index 3dea476b42..ce47083537 100644
--- a/utils/hu/datetime.texy
+++ b/utils/hu/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Kiterjeszti a [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] funkciót az időzóna stringként történő megadásának lehetőségével.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create with custom timezone
diff --git a/utils/hu/filesystem.texy b/utils/hu/filesystem.texy
index 83e5836ceb..36f0687c1b 100644
--- a/utils/hu/filesystem.texy
+++ b/utils/hu/filesystem.texy
@@ -2,9 +2,11 @@ Fájlrendszer funkciók
 *********************
 
 .[perex]
-[api:Nette\Utils\FileSystem] egy statikus osztály, amely hasznos függvényeket tartalmaz a fájlrendszerrel való munkához. Egyik előnye a natív PHP függvényekkel szemben, hogy hiba esetén kivételeket dobnak.
+[api:Nette\Utils\FileSystem] egy osztály, amely hasznos funkciókat tartalmaz a fájlrendszerrel való munkához. Egyik előnye a natív PHP függvényekkel szemben, hogy hiba esetén kivételeket dobnak.
 
 
+Ha fájlokat kell keresnie a lemezen, használja a [Finder |finder] programot.
+
 Telepítés:
 
 ```shell
@@ -174,3 +176,26 @@ A slashes karaktereket az aktuális platformra jellemző karakterekre konvertál
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Statikus vs. nem statikus megközelítés .[#toc-static-vs-non-static-approach]
+============================================================================
+
+A `FileSystem` osztályt könnyen lecserélhetjük egy másik osztályra, például tesztelési célokra, ha nem-statikusan használjuk:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/hu/finder.texy b/utils/hu/finder.texy
index 81131ce5a4..10cd3f3b02 100644
--- a/utils/hu/finder.texy
+++ b/utils/hu/finder.texy
@@ -61,6 +61,8 @@ A statikus módszerek alternatívája, hogy létrehozunk egy példányt a `new F
 
 Használhat [vadkártyákat |#wildcards] `*`, `**`, `?` and `[...]` a maszkban. Megadhat könyvtárakat is, például a `src/*.php` a `src` könyvtárban található összes PHP-fájlt megkeresi.
 
+A szimbolikus hivatkozások szintén könyvtáraknak vagy fájloknak minősülnek.
+
 
 Hol keressünk? .[#toc-where-to-search]
 --------------------------------------
diff --git a/utils/hu/floats.texy b/utils/hu/floats.texy
index 64f72c88b3..6eb4523785 100644
--- a/utils/hu/floats.texy
+++ b/utils/hu/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Amikor megpróbálja összehasonlítani a `NAN`, akkor a `\LogicException` kivételt dob.
 
+.[tip]
+A `Floats` osztály tolerálja a `1e-10`-nél kisebb különbségeket. Ha nagyobb pontossággal kell dolgoznia, használja helyette a BCMath könyvtárat.
+
 
 Lebegő összehasonlítás .[#toc-float-comparison]
 ===============================================
diff --git a/utils/hu/html-elements.texy b/utils/hu/html-elements.texy
index 4b8eeb1770..f157b90006 100644
--- a/utils/hu/html-elements.texy
+++ b/utils/hu/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Egy másik módja egy új `Html` csomópont létrehozásának és beszúrásának:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/hu/images.texy b/utils/hu/images.texy
index f267d98de0..d4595022eb 100644
--- a/utils/hu/images.texy
+++ b/utils/hu/images.texy
@@ -17,6 +17,8 @@ A következő példák feltételezik, hogy a következő osztály alias van defi
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Opcionálisan megadhat egy háttérszínt (alapértelmezett a fekete):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Vagy betöltjük a képet egy fájlból:
@@ -41,17 +43,6 @@ Vagy betöltjük a képet egy fájlból:
 $image = Image::fromFile('nette.jpg');
 ```
 
-A támogatott formátumok a JPEG, PNG, GIF, WebP, AVIF és BMP, de a PHP verziójának támogatnia kell ezeket (ellenőrizze a `phpinfo()`, GD szakaszban). Az animációk nem támogatottak.
-
-Fel kell ismernie a képformátumot betöltéskor? A módszer a formátumot adja vissza a második paraméterben:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type az Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF vagy Image::BMP.
-```
-
-Csak a kép betöltése nélküli felismerést végzi a `Image::detectTypeFromFile()`.
-
 
 A kép mentése .[#toc-save-the-image]
 ====================================
@@ -68,25 +59,45 @@ A tömörítési minőséget a JPEG (alapértelmezett 85), WEBP (alapértelmezet
 $image->save('resampled.jpg', 80); // JPEG, minőség 80%
 ```
 
-Ha a formátum nem egyértelmű a fájlkiterjesztésből, akkor a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok valamelyikével adható meg:
+Ha a formátum nem egyértelmű a fájlkiterjesztésből, akkor [konstanssal |#Formats] is megadható:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 A képet lemez helyett egy változóba is ki lehet írni:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, minőség 80%.
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, minőség 80%.
 ```
 
 vagy közvetlenül a böngészőnek a megfelelő HTTP fejléccel `Content-Type`:
 
 ```php
 // fejlécet küld Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formátumok .[#toc-formats]
+==========================
+
+Támogatott formátumok: JPEG, PNG, GIF, WebP, AVIF és BMP. Ezeket azonban a PHP verziójának is támogatnia kell, amit az [isTypeSupported() |#isTypeSupported()] függvény segítségével ellenőrizhet. Az animációk nem támogatottak.
+
+A formátumokat a `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` és `ImageType::BMP` konstansok jelölik.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Fel kell ismernie egy kép formátumát betöltéskor? A módszer ezt a második paraméterben adja vissza:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+A tényleges felismerést a kép betöltése nélkül a `Image::detectTypeFromFile()` végzi.
+
 
 Kép átméretezése .[#toc-image-resize]
 =====================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 A `cropAuto()` metódus a `imagecropauto()` függvény objektumkapszulázása, további információkért lásd [a dokumentációját |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Színek .[#toc-colors]
+=====================
+
+A `ImageColor::rgb()` módszer lehetővé teszi a színek meghatározását a vörös, zöld és kék (RGB) értékek segítségével. Opcionálisan egy átlátszósági értéket is megadhat 0 (teljesen átlátszó) és 1 (teljesen átlátszatlan) között, akárcsak a CSS-ben.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+A `ImageColor::hex()` módszerrel a CSS-hez hasonlóan hexadecimális formátumban adhat meg egy színt. Támogatja a `#rgb`, `#rrggbb`, `#rgba` és `#rrggbbaa` formátumokat:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+A színeket más módszerekben is lehet használni, mint például a `ellipse()`, `fill()`, stb.
+
+
 Rajzolás és szerkesztés .[#toc-drawing-and-editing]
 ===================================================
 
-Rajzolhatsz, írhatsz, használhatod az összes PHP függvényt a képekkel való munkához, mint például az [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], de objektum stílusban:
+Rajzolhatsz, írhatsz, használhatod az összes PHP függvényt a képmanipulációhoz, lásd: [A módszerek áttekintése |#Overview of methods], de egy objektumorientált burkolatban:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Lásd [a módszerek áttekintését |#Overview of Methods].
+Mivel a téglalapok rajzolására szolgáló PHP függvények a koordináták megadása miatt nem praktikusak, a `Image` osztály a [rectangleWH() |#rectangleWH()] és a [filledRectangleWH() |#filledRectangleWH()] függvények formájában helyettesíti őket.
 
 
 Több kép egyesítése .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Könnyedén elhelyezhet egy másik képet a képbe:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // a koordináták százalékban is megadhatók
 $blank->place($logo, '80%', '80%'); // közel a jobb alsó sarokhoz
@@ -219,53 +250,68 @@ A módszerek áttekintése .[#toc-overview-of-methods]
 ===================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Új, valós színű képet hoz létre a megadott méretekkel. Az alapértelmezett szín a fekete.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Beolvas egy képet egy fájlból, és visszaadja a típusát a `$detectedFormat` címen. A támogatott típusok: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP`.
+Beolvas egy képet egy fájlból, és visszaadja a [típusát |#Formats] a `$detectedFormat` címen.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Beolvas egy képet egy karakterláncból, és visszaadja a típusát a `$detectedFormat` címen. A támogatott típusok: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP`.
+Beolvas egy képet egy karakterláncból, és visszaadja [a típusát |#Formats] a `$detectedFormat` címen.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Létrehoz egy színt, amely más módszerekben, például a `ellipse()`, `fill()`, stb. használható.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Ezt a funkciót a `ImageColor` osztály váltotta fel, lásd a [színeket |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Visszaadja az adott `Image::XXX` konstans fájlkiterjesztését.
+Visszaadja az adott [típushoz |#Formats] tartozó fájlkiterjesztést.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Visszaadja a megadott `Image::XXX` konstans mime típusát.
+Visszaadja az adott [típus |#Formats] mime típusát.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Visszaadja a kép típusát a `Image::XXX` konstansként a fájlkiterjesztésnek megfelelően.
+Visszaadja a kép [típusát |#Formats] a fájlkiterjesztésnek megfelelően.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Visszaadja a képfájl típusát a `Image::XXX` konstansként, valamint a `$width` és `$height` paraméterekben a méreteit is.
+Visszaadja a képfájl [típusát |#Formats] és a `$width` és `$height` paraméterekben a méreteit is.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Visszaadja a kép típusát a stringből a `Image::XXX` konstansként, és a `$width` és `$height` paraméterekben a méreteit is.
+Visszaadja a kép [típusát |#Formats] a stringből és a `$width` és `$height` paraméterekben a méreteit is.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Megállapítja, hogy az adott [képtípus |#Formats] támogatott-e.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Visszaadja a támogatott képtípusok tömbjét (konstansok `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Kiszámítja a megadott betűtípusú és méretű szöveget körülvevő téglalap méreteit. Egy asszociatív tömböt ad vissza, amely a `left`, `top`, `width`, `height` kulcsokat tartalmazza. A bal oldali margó negatív lehet, ha a szöveg bal oldali túlnyúlással kezdődik.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Visszaad egy képet, amely az affin transzformált src képet tartalmazza, egy opcionális vágási terület használatával. ([tovább |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Két affin transzformációs mátrix összekapcsolását adja vissza, ami akkor hasznos, ha több transzformációt kell alkalmazni ugyanarra a képre egy menetben. ([tovább |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Visszaad egy affin transzformációs mátrixot. ([tovább |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Aktiválja a gyors rajzolás antializált módszereit a vonalak és a vezetékes
 Az antialiased primitívek átlátszó háttérszínnel történő használata nem várt eredményekkel járhat. A keverési módszer a háttérszínt ugyanúgy használja, mint bármely más színt. Az alfa komponens támogatás hiánya nem teszi lehetővé az alfa alapú antialiasing módszert. ([tovább |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 A megadott koordináták középpontjában lévő körív rajzolása. ([tovább |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-A `$char` első karakterét a képen a `$x`,`$y` (a bal felső rész 0, 0) színnel rajzolja meg a `$color` színnel a első karakterét. ([tovább |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-A `$char` karaktert függőlegesen rajzolja a megadott koordinátán a megadott képen. ([tovább |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Visszaad egy színazonosítót, amely a megadott RGB-komponensekből álló színt reprezentálja. Minden egyes, a képen használni kívánt szín létrehozásához meg kell hívni. ([tovább |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Visszaadja a színek számát egy képpalettán ([more |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 A kép átlátszó színének lekérdezése vagy beállítása. ([tovább |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 A képet a megadott téglalap alakú területre vágja. A méretek átadhatók egész számokként pixelben vagy karakterláncokként százalékban (pl. `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Automatikusan levágja a képet a megadott `$mode` címnek megfelelően. ([tovább |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Egy ellipszist rajzol a megadott koordináták középpontjába. ([tovább |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 A megadott koordinátánál (balra fent 0, 0) kezdődő áradásos kitöltést hajt végre a megadott `$color` címen a képen. ([tovább |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Egy részleges ívet rajzol, amelynek középpontja a kép megadott koordinátája. ([tovább |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Egy ellipszist rajzol, amelynek középpontja a kép megadott koordinátája. ([tovább |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Egy kitöltött sokszöget hoz létre a $image-ben. ([tovább |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Egy téglalapot hoz létre a képen a `$color` címmel, amely az 1. pontban kezdődik és a 2. pontban végződik. 0, 0 a kép bal felső sarka. ([tovább |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Egy téglalapot hoz létre a képen a `$color` címmel, amely a `$x1` és a `$y1` címen kezdődik és a `$x2` és a `$y2` címen végződik. 0, 0 pont a kép bal felső sarka. ([tovább |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Létrehoz egy téglalapot, amely a `$color` képen a `$left` és a `$top` pontból kiindulva `$width` szélességű és `$height` magasságú téglalapot hoz létre. A 0,0 pont a kép bal felső sarka.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Olyan áradásos kitöltést végez, amelynek határszínét a `$border` határozza meg. A kitöltés kezdőpontja a `$x`, `$y` (balra fent 0, 0), és a régiót a `$color` színnel töltjük ki. ([tovább |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Megfordítja a képet a megadott `$mode` segítségével. ([tovább |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Írjon szöveget a képre a FreeType 2 betűtípusok segítségével. ([tovább |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Írja a képen látható szöveget. ([tovább |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Visszaadja a kép szélességét.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Be- vagy kikapcsolja az interlace bitet. Ha az interlace bit be van állítva, és a képet JPEG-ként használják, a kép progresszív JPEG-ként jön létre. ([tovább |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Állítsa be az alpha blending flaget a réteghatások használatához. ([tovább |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Vonalat húz a két megadott pont közé. ([tovább |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Egy nyitott sokszöget rajzol a képre. A `polygon()` címmel ellentétben az utolsó és az első pont között nem húzódik vonal. ([tovább |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Másolja a `$image` címet a képre a `$left` és a `$top` koordinátáknál. A koordináták átadhatók egész számokként pixelben vagy karakterláncokként százalékban (pl. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Egy sokszöget hoz létre a képen. ([tovább |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 A megadott koordinátáknál kezdődő téglalapot hoz létre. ([tovább |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Egy téglalapot hoz létre a megadott koordinátákon.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Méretezi a képet, [további információk |#Image Resize]. A méretek átadhatók egész számokként pixelben vagy karakterláncokként százalékban (pl. `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Lehetővé teszi a kép felbontásának beállítását és lekérdezését DPI-ben (dots per inch). Ha az opcionális paraméterek egyike sincs megadva, az aktuális felbontás indexelt tömbként kerül visszaadásra. Ha csak a `$resX` értéket adja meg, a vízszintes és függőleges felbontás erre az értékre kerül beállításra. Ha mindkét opcionális paramétert megadjuk, a vízszintes és függőleges felbontás ezekre az értékekre kerül beállításra.
 
 A felbontást csak akkor használjuk meta információként, amikor a képeket az ilyen információt támogató formátumokból olvassuk be és írjuk ki (jelenleg PNG és JPEG). Ez nem befolyásolja a rajzolási műveleteket. Az új képek alapértelmezett felbontása 96 DPI. ([tovább |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Elforgatja a képet a megadott `$angle` értékkel fokban. Az elforgatás közé
 Igényli a *Bundled GD kiterjesztést*, így nem biztos, hogy mindenhol működik.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Kép mentése egy fájlba.
 
-A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében pedig 0..9 tartományban van. Ha a típus nem egyértelmű a fájlkiterjesztésből, akkor a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok valamelyikével adhatja meg.
+A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. Ha a típus nem egyértelmű a fájlkiterjesztésből, akkor a `ImageType` konstansok egyikével adhatja meg.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 A megadott interpolációs algoritmus segítségével méretezi a képet. ([tovább |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Kimeneti egy képet a böngészőbe.
 
-A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. A típus a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok egyike.
+A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van.
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Beállítja az interpolációs módszert, amely hatással van a `rotate()` és a `affine()` módszerekre. ([tovább |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Egy pixelt rajzol a megadott koordinátára. ([tovább |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Egy kicsit élesíti a képet.
 Igényli a *Bundled GD kiterjesztést*, így nem biztos, hogy mindenhol működik.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Egy karakterláncot rajzol a megadott koordinátákhoz. ([tovább |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Egy sztringet rajzol függőlegesen a megadott koordinátákhoz. ([tovább |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Kimeneti képet ad ki stringként.
 
-A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. A típus a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok egyike.
+A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van.
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Egy valódi színű képet palettaképpé alakít át. ([tovább |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-A megadott szöveget TrueType betűtípusok használatával írja a képbe. ([tovább |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+A megadott szöveget írja a képbe. ([tovább |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/hu/iterables.texy b/utils/hu/iterables.texy
new file mode 100644
index 0000000000..6133ff8ff2
--- /dev/null
+++ b/utils/hu/iterables.texy
@@ -0,0 +1,170 @@
+Iterátor funkciók
+*****************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] egy statikus osztály az iterátorokkal való munkához szükséges függvényekkel. A tömbökre vonatkozó megfelelője a [Nette\Utils\Arrays |arrays].
+
+
+Telepítés:
+
+```shell
+composer require nette/utils
+```
+
+Minden példa feltételezi a következő alias létrehozását:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Egy adott értéket keres egy iterátorban. Szigorú összehasonlítást (`===`) használ az egyezés ellenőrzésére. Visszaadja a `true` értéket, ha az értéket megtalálta, egyébként `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Ez a módszer akkor hasznos, ha gyorsan meg kell állapítani, hogy egy adott érték jelen van-e egy iterátorban anélkül, hogy manuálisan végig kellene iterálni az összes elemet.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Egy adott kulcs keresése egy iterátorban. Szigorú összehasonlítást (`===`) használ az egyezés keresésére. Visszaadja `true` ha a kulcsot megtalálta, egyébként `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Ellenőrzi, hogy az iterátor minden eleme megfelel-e a `$predicate` pontban meghatározott feltételnek. A `$predicate` függvénynek a `function ($value, $key, iterable $iterable): bool` aláírása van, és minden elemre vissza kell adnia a `true` értéket ahhoz, hogy a `every()` módszer a `true` értéket adja vissza.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Ez a módszer hasznos annak ellenőrzésére, hogy egy gyűjtemény minden eleme megfelel-e egy bizonyos feltételnek, például annak, hogy az összes szám egy adott érték alatt van-e.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Létrehoz egy új iterátort, amely csak azokat az elemeket tartalmazza az eredeti iterátorból, amelyek megfelelnek a `$predicate` pontban meghatározott feltételnek. A `$predicate` függvény aláírása `function ($value, $key, iterable $iterable): bool`, és a megtartandó elemek esetében a `true` függvényt kell visszaadnia.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+A módszer generátort használ, ami azt jelenti, hogy a szűrés az iteráció során inkrementálisan történik. Ez memóriahatékony és lehetővé teszi a nagyon nagy gyűjtemények kezelését. Ha nem iteráljuk végig az eredményül kapott iterátor minden elemét, akkor számítási energiát takarítunk meg, mivel az eredeti iterátor nem minden elemét dolgozzuk fel.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Visszaadja az iterátor első elemét. Ha a `$predicate` megadva van, akkor az első olyan elemet adja vissza, amely megfelel a megadott feltételnek. A `$predicate` függvény aláírása `function ($value, $key, iterable $iterable): bool`. Ha nem talál megfelelő elemet, akkor a `$else` függvényt (ha megadva van) hívja meg, és annak eredményét adja vissza. Ha a `$else` nincs megadva, akkor a `null` függvényt adja vissza.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Ez a módszer akkor hasznos, ha gyorsan ki kell kérni egy gyűjtemény első elemét vagy az első olyan elemet, amely megfelel egy bizonyos feltételnek, anélkül, hogy manuálisan végig kellene iterálni a teljes gyűjteményt.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Visszaadja az iterátor első elemének kulcsát. Ha `$predicate` van megadva, akkor a megadott feltételnek megfelelő első elem kulcsát adja vissza. A `$predicate` függvény aláírása `function ($value, $key, iterable $iterable): bool`. Ha nem találunk megfelelő elemet, akkor a `$else` függvényt (ha megadva van) hívja meg, és annak eredményét adja vissza. Ha a `$else` nincs megadva, akkor a `null` függvényt adja vissza.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Új iterátort hoz létre a `$transformer` függvénynek az eredeti iterátor minden elemére történő alkalmazásával. A `$transformer` függvény aláírása `function ($value, $key, iterable $iterable): mixed`, és visszatérési értéke az elem új értékeként kerül felhasználásra.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+A módszer generátort használ, ami azt jelenti, hogy az átalakítás az iteráció során inkrementálisan történik. Ez memóriahatékony és lehetővé teszi a nagyon nagy gyűjtemények kezelését. Ha nem iteráljuk végig az eredményül kapott iterátor minden elemét, akkor számítási erőfeszítést takarítunk meg, mivel az eredeti iterátor nem minden elemét dolgozzuk fel.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Új iterátort hoz létre az eredeti iterátor értékeinek és kulcsainak átalakításával. A `$transformer` függvény aláírása: `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Ha a `$transformer` visszatér `null`, akkor az elemet kihagyja. A megtartott elemek esetében a visszaadott tömb első elemét használja új kulcsként, a második elemet pedig új értékként.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+A `map()` módszerhez hasonlóan ez a módszer is generátort használ a növekményes feldolgozás és a memóriahatékonyság érdekében. Ez lehetővé teszi a nagy gyűjteményekkel való munkát és a számítási erőfeszítés megtakarítását azáltal, hogy az eredménynek csak egy részét dolgozza fel.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Létrehoz egy burkolatot egy iterátor körül, amely az iteráció során a kulcsokat és az értékeket gyorsítótárba helyezi. Ez lehetővé teszi az adatok ismételt iterálását anélkül, hogy az eredeti adatforrást újra fel kellene dolgozni.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Ez a módszer olyan helyzetekben hasznos, amikor többször kell ugyanazon az adathalmazon iterálni, de az eredeti iterátor nem támogatja az ismételt iterációt, vagy az ismételt iteráció költséges lenne (pl. adatok olvasása adatbázisból vagy fájlból).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Ellenőrzi, hogy az iterátor legalább egy eleme megfelel-e a `$predicate` pontban meghatározott feltételnek. A `$predicate` függvénynek a `function ($value, $key, iterable $iterable): bool` aláírása van, és legalább egy elemre vonatkozóan vissza kell adnia a `true` értéket, hogy a `some()` módszer a `true` értéket adja vissza.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Ez a módszer hasznos annak gyors ellenőrzésére, hogy van-e legalább egy olyan elem egy gyűjteményben, amely megfelel egy bizonyos feltételnek, például, hogy a gyűjtemény tartalmaz-e legalább egy páros számot.
+
+Lásd [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Bármilyen iterálható objektumot (tömb, Traversable) Iterátorrá alakít. Ha a bemenet már egy Iterator, akkor azt változatlanul adja vissza.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Ez a metódus akkor hasznos, ha a bemeneti adattípustól függetlenül biztosítani kell, hogy egy Iterátorral rendelkezzünk. Ez hasznos lehet olyan függvények létrehozásakor, amelyek különböző típusú iterálható adatokkal dolgoznak.
diff --git a/utils/hu/json.texy b/utils/hu/json.texy
index dd74607580..fbad6d09fb 100644
--- a/utils/hu/json.texy
+++ b/utils/hu/json.texy
@@ -77,7 +77,7 @@ A `$forceArray` beállítása objektumok helyett tömbök visszaküldését kén
 
 ```php
 Json::decode('{"variable": true}'); // egy stdClass típusú objektumot ad vissza.
-Json::decode('{"variable": true}', forceArray: true); // egy tömböt ad vissza.
+Json::decode('{"variable": true}', forceArrays: true); // egy tömböt ad vissza.
 ```
 
 `Nette\Utils\JsonException` kivételt dob hiba esetén.
diff --git a/utils/hu/smartobject.texy b/utils/hu/smartobject.texy
index a158b2858b..eb81664c98 100644
--- a/utils/hu/smartobject.texy
+++ b/utils/hu/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject és StaticClass
-**************************
+SmartObject
+***********
 
 .[perex]
-A SmartObject a PHP osztályok *tulajdonságok* támogatását adja hozzá. A StaticClass a statikus osztályok jelölésére szolgál.
+A SmartObject korábban sokféleképpen javította az objektumok viselkedését, de a mai PHP már natívan tartalmazza ezen fejlesztések nagy részét. Azonban még mindig hozzáadja a *tulajdonságok* támogatását.
 
 
 Telepítés:
@@ -65,31 +65,16 @@ echo $circle->visible; // hívja az isVisible() függvényt
 A tulajdonságok elsősorban "szintaktikai cukor"((syntactic sugar)), amelynek célja, hogy a kód egyszerűsítésével megédesítse a programozó életét. Ha nem akarod őket, nem kell használni őket.
 
 
-Statikus osztályok .[#toc-static-classes]
-=========================================
+Pillantás a történelembe .[#toc-a-glimpse-into-history]
+=======================================================
 
-A statikus osztályokat, azaz azokat az osztályokat, amelyeket nem szándékoznak példányosítani, a `Nette\StaticClass` tulajdonsággal lehet jelölni:
+A SmartObject korábban számos módon finomította az objektumok viselkedését, de a mai PHP már natívan tartalmazza ezen fejlesztések nagy részét. A következő szöveg egy nosztalgikus visszatekintés a történelembe, emlékeztetve minket a dolgok fejlődésére.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Amikor megpróbál egy példányt létrehozni, a `Error` kivétel dobódik, jelezve, hogy az osztály statikus.
-
-
-Egy pillantás a történelembe .[#toc-a-look-into-the-history]
-============================================================
-
-A SmartObject korábban sokféleképpen javította és javította az osztályok viselkedését, de a PHP fejlődése az eredeti funkciók nagy részét feleslegessé tette. A következőkben tehát a dolgok fejlődésének történetébe pillantunk bele.
-
-A PHP objektummodellje a kezdetektől fogva számos komoly hibától és hiányosságtól szenvedett. Ez volt az oka a `Nette\Object` osztály létrehozásának (2007-ben), amely megpróbálta ezeket orvosolni és javítani a PHP használatának élményét. Ez elég volt ahhoz, hogy más osztályok is örököljenek belőle, és elnyerjék az általa nyújtott előnyöket. Amikor a PHP 5.4-ben megjelent a trait-támogatás, a `Nette\Object` osztályt a `Nette\SmartObject` osztály váltotta fel. Így már nem volt szükség arra, hogy egy közös őstől örököljenek. Ráadásul a trait olyan osztályokban is használható volt, amelyek már egy másik osztálytól örököltek. A `Nette\Object` végleges végét a PHP 7.2 kiadása jelentette, amely megtiltotta az osztályok `Object` nevének használatát.
+A PHP objektummodellje a kezdetektől fogva számtalan komoly hiányosságtól és hiányosságtól szenvedett. Ez vezetett a `Nette\Object` osztály létrehozásához (2007-ben), amelynek célja ezen problémák orvoslása és a PHP használatának kényelmesebbé tétele volt. Mindössze arra volt szükség, hogy más osztályok is örököljenek belőle, és máris élvezhették az általa kínált előnyöket. Amikor a PHP 5.4 bevezette a tulajdonságok támogatását, a `Nette\Object` osztály helyébe a `Nette\SmartObject` tulajdonság lépett. Ezzel megszűnt a közös őstől való öröklés szükségessége. Sőt, a tulajdonságot olyan osztályokban is lehetett használni, amelyek már örököltek egy másik osztálytól. A `Nette\Object` végleges megszűnését a PHP 7.2 kiadása jelentette, amely megtiltotta, hogy az osztályok neve `Object` legyen.
 
-A PHP fejlesztésének előrehaladtával az objektummodell és a nyelvi képességek tovább fejlődtek. A `SmartObject` osztály egyes függvényei feleslegessé váltak. A PHP 8.2 kiadása óta az egyetlen olyan funkció, amely megmaradt, és amelyet a PHP még nem támogat közvetlenül, az úgynevezett [tulajdonságok |#Properties, Getters and Setters] használatának lehetősége.
+A PHP fejlesztésének előrehaladtával az objektummodell és a nyelvi képességek tovább fejlődtek. A `SmartObject` osztály különböző funkciói feleslegessé váltak. A PHP 8.2 kiadása óta csak egyetlen olyan funkció maradt, amelyet a PHP közvetlenül nem támogat: az úgynevezett [tulajdonságok |#Properties, getters, and setters] használatának lehetősége.
 
-Milyen funkciókat kínált egykor a `Nette\Object` és a `Nette\Object`? Íme egy áttekintés. (A példák a `Nette\Object` osztályt használják, de a tulajdonságok többsége a `Nette\SmartObject` tulajdonságra is vonatkozik).
+Milyen funkciókat kínált a `Nette\Object` és ennek folytán a `Nette\SmartObject`? Íme egy áttekintés. (A példákban a `Nette\Object` osztályt használjuk, de a legtöbb funkció a `Nette\SmartObject` tulajdonságra is vonatkozik).
 
 
 Inkonzisztens hibák .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-A mai PHP-ben talán nincs a "did you mean?" semmilyen formája, de [Tracy |tracy:] ezt a kiegészítést hozzáadja a hibákhoz. És még maga is képes [kijavítani |tracy:open-files-in-ide#toc-demos] az ilyen hibákat.
+Bár a mai PHP nem rendelkezik "úgy értetted?" funkcióval, ez a mondat hozzáadható a hibákhoz a [Tracy |tracy:] által. Még az [ilyen hibákat |tracy:open-files-in-ide#toc-demos] is képes [automatikusan kijavítani |tracy:open-files-in-ide#toc-demos].
 
 
 Bővítési módszerek .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // visszaadja 'John Doe'.
+$reflection->getAnnotation('author'); // visszaadja 'John Doe'
 ```
 
 A PHP 8.0-tól kezdve a metainformációkat attribútumok formájában is elérhetjük:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/hu/staticclass.texy b/utils/hu/staticclass.texy
new file mode 100644
index 0000000000..aff0d36925
--- /dev/null
+++ b/utils/hu/staticclass.texy
@@ -0,0 +1,21 @@
+Statikus osztályok
+******************
+
+.[perex]
+A StaticClass a statikus osztályok jelölésére szolgál.
+
+
+Telepítés:
+
+```shell
+composer require nette/utils
+```
+
+Statikus osztályok, azaz olyan osztályok, amelyeket nem szándékoznak példányosítani, a [api:Nette\StaticClass] tulajdonsággal jelölhetők:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/hu/strings.texy b/utils/hu/strings.texy
index e81a276a8b..1853022d9c 100644
--- a/utils/hu/strings.texy
+++ b/utils/hu/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Az UTF-8 karakterláncot az URL-ben használt formára módosítja, azaz eltávolítja a diakritikus jeleket, és az angol ábécé betűinek és a számoknak a kivételével minden karaktert kötőjellel helyettesít.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Szükséges a `intl` PHP kiterjesztés.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Eltávolítja a bal és jobb oldali szóközöket (vagy a második argumentumként átadott karaktereket) egy UTF-8 kódolt karakterláncból.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Visszaadja az UTF-8 karakterlánc egy részét, amelyet a `$start` kezdőpozíció és a `$length` hossza határoz meg. Ha a `$start` negatív, akkor a visszaadott karakterlánc a karakterlánc végétől számított `$start`'th karaktertől kezdődik.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Használja a natív `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Összehasonlít két UTF-8 karakterláncot vagy azok részeit, a karakterek esetének figyelembevétele nélkül. Ha a `$length` értéke nulla, akkor egész karakterláncokat hasonlít össze, ha negatív, akkor a karakterláncok végétől számított megfelelő számú karaktert, ellenkező esetben az elejétől számított megfelelő számú karaktert hasonlít össze.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Megkeresi a karakterlánc minden olyan előfordulását, amely megfelel a reguláris kifejezésnek, és egy olyan tömböt ad vissza, amely tartalmazza a talált kifejezést és az egyes részkifejezéseket.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Ha a `$lazy` értéke `true`, a függvény egy tömb helyett egy `Generator` értéket ad vissza, ami jelentős teljesítményelőnyt jelent a nagy karakterláncokkal való munka során. A generátor lehetővé teszi, hogy az egyezéseket fokozatosan találjuk meg, ahelyett, hogy a teljes karakterláncot egyszerre feldolgoznánk. Ez lehetővé teszi a rendkívül nagy bemeneti szövegek hatékony kezelését. Ezenkívül bármikor megszakíthatja a feldolgozást, ha megtalálja a kívánt egyezést, így számítási időt takaríthat meg.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/hu/validators.texy b/utils/hu/validators.texy
index 29d5510af8..01fd4d162e 100644
--- a/utils/hu/validators.texy
+++ b/utils/hu/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Ellenőrzi, hogy a `$array` tömb `$key` eleme a tömbben csővel elválasztott, [elvárt típusokból |#expected types] áll. Ha nem, akkor kivételt dob [api:Nette\Utils\AssertionException]. A kivételüzenetben szereplő `item '%' in array` karakterláncot a `$label` paraméterrel lehet helyettesíteni.
 
diff --git a/utils/it/@home.texy b/utils/it/@home.texy
index d7eac70856..43e6e34c48 100644
--- a/utils/it/@home.texy
+++ b/utils/it/@home.texy
@@ -13,13 +13,14 @@ Il pacchetto `nette/utils` contiene un insieme di classi utili per l'uso quotidi
 | [Helpers |helpers] | Nette\Utils\Helpers
 | [Elementi HTML |HTML Elements] | Nette\Utils\Html
 | [Immagini |Images] | Nette\Utils\Image
+| [Iterabili |iterables] | Nette\Utils\Iterables
 | [JSON |JSON] | Nette\Utils\Json
-| [Modello a oggetti |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginatore |paginator] | Nette\Utils\Paginatore
 | [Riflessione PHP |reflection] | Nette\Utils\Reflection
 | [Tipi PHP |type] | Nette\Utils\Type
 | [Stringhe casuali |random] | Nette\Utils\Random
 | [Stringhe |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validatori |validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | versione | compatibile con PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/it/@left-menu.texy b/utils/it/@left-menu.texy
index c856685e85..d7407854fc 100644
--- a/utils/it/@left-menu.texy
+++ b/utils/it/@left-menu.texy
@@ -8,13 +8,15 @@ Pacchetto nette/utils
 - [Aiutanti |helpers]
 - [Elementi HTML |HTML Elements]
 - [Immagini |Images]
+- [Iterabili |iterables]
 - [JSON |JSON]
 - [Paginatore |paginator]
 - [Stringhe casuali |random]
-- [Oggetto intelligente |SmartObject]
 - [Riflessione PHP |reflection]
 - [Stringhe |Strings]
 - [Galleggianti |Floats]
+- [SmartObject]
+- [StaticClass]
 - [Tipi PHP |type]
 - [Validatori |validators]
 
diff --git a/utils/it/arrays.texy b/utils/it/arrays.texy
index a4394bde90..c4aa521e6c 100644
--- a/utils/it/arrays.texy
+++ b/utils/it/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Array .[#toc-arrays]
 ====================
 
-[api:Nette\Utils\Arrays] è una classe statica che contiene una serie di pratiche funzioni per gli array.
+[api:Nette\Utils\Arrays] è una classe statica che contiene una manciata di pratiche funzioni per gli array. Il suo equivalente per gli iteratori è [Nette\Utils\Iterables |iterables].
 
 Gli esempi seguenti presuppongono che sia definito il seguente alias di classe:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+La funzione trasforma in modo flessibile l'oggetto `$array` in un array associativo o in oggetti secondo il percorso specificato `$path`. Il percorso può essere una stringa o un array. È costituito dai nomi delle chiavi dell'array di input e da operatori come '[]', '->', '=' e '|'. Lancia `Nette\InvalidArgumentException` se il percorso non è valido.
+
+```php
+// Conversione in un array associativo con una chiave semplice
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// assegnare valori da una chiave a un'altra utilizzando l'operatore =
+$result = Arrays::associate($arr, 'name=age'); // o ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// creare un oggetto utilizzando l'operatore ->
+$result = Arrays::associate($arr, '->name'); // o ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// combinando le chiavi con l'operatore |
+$result = Arrays::associate($arr, 'name|age'); // oppure ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// aggiungere a un array usando []
+$result = Arrays::associate($arr, 'name[]'); // oppure ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Verifica se tutti gli elementi dell'array superano il test implementato dalla funzione fornita, che ha la firma `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Vedere [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Restituisce un nuovo array contenente tutte le coppie chiave-valore corrispondenti al dato `$predicate`. Il callback ha la firma `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Restituisce il primo elemento dell'array o null se l'array è vuoto. Non modifica il puntatore interno, a differenza di `reset()`.
+Restituisce il primo elemento (che corrisponde al predicato specificato, se dato). Se non esiste un elemento, restituisce il risultato dell'invocazione di `$else` o null.
+ `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`.
+
+Non modifica il puntatore interno, a differenza di `reset()`. I parametri `$predicate` e `$else` esistono dalla versione 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Vedere [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Restituisce la chiave del primo elemento (che corrisponde al predicato specificato, se dato) o null se non esiste un elemento. `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Vedere [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Restituisce `$array[$key]` item. Se non esiste, viene lanciato `Nette\InvalidArgumentException`, a meno che non venga impostato un valore predefinito come terzo parametro.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Restituisce l'ultimo elemento (che corrisponde al predicato specificato, se dato). Se non esiste un elemento, restituisce il risultato dell'invocazione di `$else` o null.
+ `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`.
+
+Non modifica il puntatore interno, a differenza di `end()`. I parametri `$predicate` e `$else` esistono dalla versione 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Vedere [prima() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Restituisce l'ultimo elemento dell'array o null se l'array è vuoto. Non modifica il puntatore interno, a differenza di `end()`.
+Restituisce la chiave dell'ultimo elemento (che corrisponde al predicato specificato, se dato) o null se non esiste un elemento. `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Vedere [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Richiama `$callback` su tutti gli elementi dell'array e restituisce l'array dei valori di ritorno. Il callback ha la firma `function ($value, $key, array $array): bool`.
+Richiama `$transformer` su tutti gli elementi dell'array e restituisce l'array dei valori di ritorno. Il callback ha la firma `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Crea un nuovo array trasformando i valori e le chiavi dell'array originale. La funzione `$transformer` ha la firma `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Se `$transformer` restituisce `null`, l'elemento viene saltato. Per gli elementi mantenuti, il primo elemento dell'array restituito viene utilizzato come nuova chiave e il secondo elemento come nuovo valore.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Questo metodo è utile nelle situazioni in cui è necessario modificare la struttura di un array (sia le chiavi che i valori contemporaneamente) o filtrare gli elementi durante la trasformazione (restituendo null per gli elementi indesiderati).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 I valori del secondo array vengono sempre aggiunti al primo. La scomparsa del valore `10` dal secondo array può sembrare un po' confusa. Va notato che questo valore, così come il valore `5` in the first array have the same numeric key `0`, quindi nel campo risultante c'è solo un elemento del primo array.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizza l'array in un array associativo. Sostituisce le chiavi numeriche con i loro valori, il nuovo valore sarà `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Restituisce e rimuove il valore di un elemento da un array. Se non esiste, lancia un'eccezione o restituisce `$default`, se fornito.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // restituisce null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Verifica se almeno un elemento dell'array supera il test implementato dal callback fornito con la firma `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // imposta $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Lancia ogni elemento dell'array come stringa e lo racchiude con `$prefix` e `$suffix`.
 
diff --git a/utils/it/datetime.texy b/utils/it/datetime.texy
index 02fd389dc4..a7825b1ce0 100644
--- a/utils/it/datetime.texy
+++ b/utils/it/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Estende [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] con la possibilità di specificare un fuso orario come stringa.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create with custom timezone
diff --git a/utils/it/filesystem.texy b/utils/it/filesystem.texy
index 695312636c..3fa2a45128 100644
--- a/utils/it/filesystem.texy
+++ b/utils/it/filesystem.texy
@@ -2,9 +2,11 @@ Funzioni del filesystem
 ***********************
 
 .[perex]
-[api:Nette\Utils\FileSystem] è una classe statica che contiene funzioni utili per lavorare con il filesystem. Un vantaggio rispetto alle funzioni native di PHP è che lanciano eccezioni in caso di errori.
+[api:Nette\Utils\FileSystem] è una classe che contiene funzioni utili per lavorare con il filesystem. Un vantaggio rispetto alle funzioni native di PHP è che lanciano eccezioni in caso di errori.
 
 
+Per cercare i file sul disco, utilizzare il [Finder |finder].
+
 Installazione:
 
 ```shell
@@ -174,3 +176,26 @@ Converte gli slash in caratteri specifici della piattaforma corrente, ad esempio
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Approccio statico e non statico .[#toc-static-vs-non-static-approach]
+=====================================================================
+
+Per sostituire facilmente la classe `FileSystem` con un'altra classe, ad esempio a scopo di test, utilizzarla in modo non statico:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/it/finder.texy b/utils/it/finder.texy
index fd44122a2a..e365191e57 100644
--- a/utils/it/finder.texy
+++ b/utils/it/finder.texy
@@ -61,6 +61,8 @@ Un'alternativa ai metodi statici è creare un'istanza con `new Finder` (l'oggett
 
 Si possono usare [i caratteri jolly |#wildcards] `*`, `**`, `?` and `[...]` nella maschera. Si possono anche specificare le directory, ad esempio `src/*.php` cercherà tutti i file PHP nella directory `src`.
 
+Anche i collegamenti simbolici sono considerati directory o file.
+
 
 Dove cercare? .[#toc-where-to-search]
 -------------------------------------
diff --git a/utils/it/floats.texy b/utils/it/floats.texy
index 87d310788f..efd473b289 100644
--- a/utils/it/floats.texy
+++ b/utils/it/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Quando si tenta di confrontare `NAN`, viene lanciata un'eccezione `\LogicException`.
 
+.[tip]
+La classe `Floats` tollera differenze inferiori a `1e-10`. Se è necessario lavorare con maggiore precisione, utilizzare la libreria BCMath.
+
 
 Confronto tra i galleggianti .[#toc-float-comparison]
 =====================================================
diff --git a/utils/it/html-elements.texy b/utils/it/html-elements.texy
index b58fae2b14..e29f8eb927 100644
--- a/utils/it/html-elements.texy
+++ b/utils/it/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Un altro modo per creare e inserire un nuovo nodo `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/it/images.texy b/utils/it/images.texy
index f8888325f6..323386b224 100644
--- a/utils/it/images.texy
+++ b/utils/it/images.texy
@@ -17,6 +17,8 @@ Gli esempi seguenti presuppongono che sia stato definito il seguente alias di cl
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Opzionalmente, è possibile specificare un colore di sfondo (l'impostazione predefinita è il nero):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Oppure si carica l'immagine da un file:
@@ -41,17 +43,6 @@ Oppure si carica l'immagine da un file:
 $image = Image::fromFile('nette.jpg');
 ```
 
-I formati supportati sono JPEG, PNG, GIF, WebP, AVIF e BMP, ma è necessario che anche la vostra versione di PHP li supporti (controllate `phpinfo()`, sezione GD). Le animazioni non sono supportate.
-
-È necessario rilevare il formato dell'immagine durante il caricamento? Il metodo restituisce il formato nel secondo parametro:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $tipo è Immagine::JPEG, Immagine::PNG, Immagine::GIF, Immagine::WEBP, Immagine::AVIF o Immagine::BMP
-```
-
-Solo il rilevamento senza caricamento dell'immagine viene effettuato da `Image::detectTypeFromFile()`.
-
 
 Salvare l'immagine .[#toc-save-the-image]
 =========================================
@@ -68,25 +59,45 @@ $image->save('resampled.jpg');
 $image->save('resampled.jpg', 80); // JPEG, qualità 80%
 ```
 
-Se il formato non è evidente dall'estensione del file, può essere specificato da una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`:
+Se il formato non è evidente dall'estensione del file, può essere specificato con una [costante |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 L'immagine può essere scritta in una variabile invece che su disco:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, quality 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, quality 80%
 ```
 
 o inviare direttamente al browser con l'intestazione HTTP appropriata `Content-Type`:
 
 ```php
 // invia l'intestazione Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formati .[#toc-formats]
+=======================
+
+I formati supportati sono JPEG, PNG, GIF, WebP, AVIF e BMP. Tuttavia, devono essere supportati anche dalla versione di PHP in uso, il che può essere verificato con la funzione [isTypeSupported() |#isTypeSupported()]. Le animazioni non sono supportate.
+
+I formati sono rappresentati dalle costanti `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` e `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+È necessario rilevare il formato di un'immagine al momento del caricamento? Il metodo lo restituisce nel secondo parametro:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Il rilevamento effettivo senza caricare l'immagine viene eseguito da `Image::detectTypeFromFile()`.
+
 
 Ridimensionamento dell'immagine .[#toc-image-resize]
 ====================================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Il metodo `cropAuto()` è un oggetto che incapsula la funzione `imagecropauto()`; per ulteriori informazioni, consultare la [relativa documentazione |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Colori .[#toc-colors]
+=====================
+
+Il metodo `ImageColor::rgb()` consente di definire un colore utilizzando i valori rosso, verde e blu (RGB). Opzionalmente, si può anche specificare un valore di trasparenza che va da 0 (completamente trasparente) a 1 (completamente opaco), proprio come nei CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Il metodo `ImageColor::hex()` consente di definire un colore utilizzando il formato esadecimale, come nei CSS. Supporta i formati `#rgb`, `#rrggbb`, `#rgba` e `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+I colori possono essere utilizzati in altri metodi, come `ellipse()`, `fill()`, ecc.
+
+
 Disegno e modifica .[#toc-drawing-and-editing]
 ==============================================
 
-Si può disegnare, si può scrivere, si possono usare tutte le funzioni PHP per lavorare con le immagini, come [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], ma utilizzando lo stile a oggetti:
+Si può disegnare, si può scrivere, si possono usare tutte le funzioni PHP per la manipolazione delle immagini, vedi [Panoramica dei metodi |#Overview of methods], ma in un involucro orientato agli oggetti:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Vedere [Panoramica dei metodi |#Overview of Methods].
+Poiché le funzioni PHP per disegnare i rettangoli sono poco pratiche a causa della necessità di specificare le coordinate, la classe `Image` le sostituisce con le funzioni [rectangleWH() |#rectangleWH()] e [filledRectangleWH() |#filledRectangleWH()].
 
 
 Unire più immagini .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Unire più immagini .[#toc-merge-multiple-images]
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // le coordinate possono essere impostate anche in percentuale
 $blank->place($logo, '80%', '80%'); // vicino all'angolo destro in basso
@@ -219,53 +250,68 @@ Panoramica dei metodi .[#toc-overview-of-methods]
 =================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Crea una nuova immagine a colori reali delle dimensioni indicate. Il colore predefinito è il nero.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Legge un'immagine da un file e ne restituisce il tipo in `$detectedFormat`. I tipi supportati sono `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`.
+Legge un'immagine da un file e ne restituisce il [tipo |#Formats] in `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Legge un'immagine da una stringa e ne restituisce il tipo in `$detectedFormat`. I tipi supportati sono `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`.
+Legge un'immagine da una stringa e ne restituisce il [tipo |#Formats] in `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Crea un colore che può essere utilizzato in altri metodi, come `ellipse()`, `fill()`, e così via.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Questa funzione è stata sostituita dalla classe `ImageColor`, vedi [colori |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Restituisce l'estensione del file per la costante `Image::XXX` data.
+Restituisce l'estensione del file per il [tipo |#Formats] dato.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Restituisce il tipo di mime per la costante `Image::XXX`.
+Restituisce il tipo di mime per il [tipo |#Formats] dato.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Restituisce il tipo di immagine come costante `Image::XXX` in base all'estensione del file.
+Restituisce il [tipo di |#Formats] immagine in base all'estensione del file.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Restituisce il tipo di file immagine come costante `Image::XXX` e nei parametri `$width` e `$height` anche le sue dimensioni.
+Restituisce il [tipo di |#Formats] file immagine e nei parametri `$width` e `$height` anche le sue dimensioni.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Restituisce il tipo di immagine dalla stringa come costante `Image::XXX` e nei parametri `$width` e `$height` anche le sue dimensioni.
+Restituisce il [tipo |#Formats] di immagine dalla stringa e nei parametri `$width` e `$height` anche le sue dimensioni.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Determina se il [tipo di |#Formats] immagine dato è supportato.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Restituisce un array di tipi di immagine supportati (costanti `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Calcola le dimensioni del rettangolo che racchiude il testo in un font e in una dimensione specificati. Restituisce un array associativo contenente le chiavi `left`, `top`, `width`, `height`. Il margine sinistro può essere negativo se il testo inizia con una sporgenza a sinistra.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Restituisce un'immagine contenente l'immagine src trasformata affine, utilizzando un'area di ritaglio opzionale. ([altro |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Restituisce la concatenazione di due matrici di trasformazione affine, utile se si vogliono applicare più trasformazioni alla stessa immagine in una sola volta. ([altro |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Restituisce una matrice di trasformazione affine. ([altro |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Attivare i metodi di disegno rapido antialias per linee e poligoni cablati. Non
 L'uso di primitive con antialias e colore di sfondo trasparente può portare a risultati inaspettati. Il metodo blend utilizza il colore di sfondo come qualsiasi altro colore. La mancanza del supporto per i componenti alfa non consente un metodo di antialiasing basato su alfa. ([altro |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Disegna un arco di cerchio centrato sulle coordinate date. ([altro |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Disegna il primo carattere di `$char` nell'immagine con la parte superiore sinistra a `$x`,`$y` (in alto a sinistra è 0, 0) con il colore `$color`. ([altro |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Disegna il carattere `$char` verticalmente alla coordinata specificata sull'immagine data. ([altro |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Restituisce un identificatore di colore che rappresenta il colore composto dalle componenti RGB indicate. Deve essere richiamato per creare ogni colore da utilizzare nell'immagine. ([altro |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Restituisce il numero di colori in una tavolozza di immagini ([more |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Ottiene o imposta il colore trasparente dell'immagine. ([altro |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Ritaglia un'immagine nell'area rettangolare indicata. Le dimensioni possono essere passate come numeri interi in pixel o come stringhe in percentuale (ad esempio `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Ritaglia automaticamente un'immagine in base all'indirizzo `$mode`. ([altro |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Disegna un'ellisse centrata sulle coordinate specificate. ([altro |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Esegue un riempimento a tappeto a partire dalla coordinata data (in alto a sinistra è 0, 0) con il dato `$color` nell'immagine. ([altro |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Disegna un arco parziale centrato nella coordinata specificata dell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Disegna un'ellisse centrata sulla coordinata specificata nell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Crea un poligono riempito nell'immagine $. ([altro |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Crea un rettangolo riempito con `$color` nell'immagine a partire dal punto 1 e fino al punto 2. 0, 0 è l'angolo superiore sinistro dell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Crea un rettangolo riempito con `$color` nell'immagine che inizia con `$x1` e `$y1` e termina con `$x2` e `$y2`. Il punto 0, 0 è l'angolo superiore sinistro dell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Crea un rettangolo riempito con `$color` nell'immagine a partire dai punti `$left` e `$top` con larghezza `$width` e altezza `$height`. Il punto 0, 0 è l'angolo superiore sinistro dell'immagine.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Esegue un riempimento a tappeto il cui colore del bordo è definito da `$border`. Il punto di partenza per il riempimento è `$x`, `$y` (in alto a sinistra 0, 0) e la regione viene riempita con il colore `$color`. ([altro |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Capovolge l'immagine utilizzando l'indirizzo `$mode`. ([altro |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Scrivere il testo sull'immagine usando i font di FreeType 2. ([altro |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Scrivere il testo nell'immagine. ([altro |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Restituisce la larghezza dell'immagine.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Attiva o disattiva il bit di interlacciamento. Se il bit di interlacciamento è impostato e l'immagine viene utilizzata come immagine JPEG, l'immagine viene creata come JPEG progressivo. ([altro |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Impostare il flag di fusione alfa per utilizzare gli effetti di stratificazione. ([altro |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Disegna una linea tra i due punti dati. ([altro |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Disegna un poligono aperto sull'immagine. Contrariamente a `polygon()`, non viene tracciata una linea tra l'ultimo e il primo punto. ([altro |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Copia `$image` nell'immagine alle coordinate `$left` e `$top`. Le coordinate possono essere passate come numeri interi in pixel o come stringhe in percentuale (ad esempio `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Crea un poligono nell'immagine. ([altro |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Crea un rettangolo a partire dalle coordinate specificate. ([altro |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Crea un rettangolo alle coordinate date.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Scala un'immagine, vedi [maggiori informazioni |#Image Resize]. Le dimensioni possono essere passate come numeri interi in pixel o come stringhe in percentuale (ad esempio `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Permette di impostare e ottenere la risoluzione di un'immagine in DPI (punti per pollice). Se non viene fornito nessuno dei parametri opzionali, la risoluzione corrente viene restituita come array indicizzato. Se viene indicato solo `$resX`, la risoluzione orizzontale e verticale viene impostata su questo valore. Se vengono forniti entrambi i parametri opzionali, la risoluzione orizzontale e verticale viene impostata rispettivamente su questi valori.
 
 La risoluzione viene utilizzata come meta-informazione solo quando le immagini vengono lette e scritte in formati che supportano questo tipo di informazioni (attualmente PNG e JPEG). Non influisce su nessuna operazione di disegno. La risoluzione predefinita per le nuove immagini è 96 DPI. ([altro |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Ruota l'immagine utilizzando l'indirizzo `$angle` in gradi. Il centro di rotazio
 Richiede l'estensione *Bundled GD*, quindi non è sicuro che funzioni ovunque.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Salva un'immagine in un file.
 
-La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Se il tipo non è evidente dall'estensione del file, è possibile specificarlo utilizzando una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`.
+La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Se il tipo non è evidente dall'estensione del file, è possibile specificarlo utilizzando una delle costanti `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Ridimensiona un'immagine utilizzando l'algoritmo di interpolazione indicato. ([altro |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Invia un'immagine al browser.
 
-La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Il tipo è una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`.
+La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Imposta il metodo di interpolazione che influisce sui metodi `rotate()` e `affine()`. ([altro |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Disegna un pixel alla coordinata specificata. ([altro |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Rende l'immagine un po' più nitida.
 Richiede l'estensione *Bundled GD*, quindi non è sicuro che funzioni ovunque.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Disegna una stringa alle coordinate date. ([altro |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Disegna una stringa in verticale alle coordinate date. ([altro |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Emette un'immagine in stringa.
 
-La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Il tipo è una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`.
+La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Converte un'immagine truecolor in un'immagine palette. ([altro |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Scrive il testo dato nell'immagine usando i font TrueType. ([altro |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Scrive il testo dato nell'immagine. ([altro |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/it/iterables.texy b/utils/it/iterables.texy
new file mode 100644
index 0000000000..5d98ac0ca9
--- /dev/null
+++ b/utils/it/iterables.texy
@@ -0,0 +1,170 @@
+Funzioni di iteratore
+*********************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] è una classe statica con funzioni per lavorare con gli iteratori. La sua controparte per gli array è [NetteUtilsArrays |arrays].
+
+
+Installazione:
+
+```shell
+composer require nette/utils
+```
+
+Tutti gli esempi presuppongono la creazione del seguente alias:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Cerca un valore dato in un iteratore. Utilizza un confronto rigoroso (`===`) per verificare la corrispondenza. Restituisce `true` se il valore viene trovato, altrimenti `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Questo metodo è utile quando è necessario determinare rapidamente se un valore specifico è presente in un iteratore, senza iterare manualmente tutti gli elementi.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Cerca una determinata chiave in un iteratore. Utilizza un confronto rigoroso (`===`) per verificare la corrispondenza. Restituisce `true` se la chiave viene trovata, altrimenti `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Verifica se tutti gli elementi dell'iteratore soddisfano la condizione definita in `$predicate`. La funzione `$predicate` ha la firma `function ($value, $key, iterable $iterable): bool` e deve restituire `true` per ogni elemento affinché il metodo `every()` restituisca `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Questo metodo è utile per verificare che tutti gli elementi di un insieme soddisfino una certa condizione, ad esempio se tutti i numeri sono inferiori a un valore specifico.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Crea un nuovo iteratore che contiene solo gli elementi dell'iteratore originale che soddisfano la condizione definita in `$predicate`. La funzione `$predicate` ha la firma `function ($value, $key, iterable $iterable): bool` e deve restituire `true` per gli elementi che devono essere mantenuti.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Il metodo utilizza un generatore, il che significa che il filtraggio avviene in modo incrementale durante l'iterazione. Questo metodo è efficiente dal punto di vista della memoria e consente di gestire raccolte molto grandi. Se non si iterano tutti gli elementi dell'iteratore risultante, si risparmia in termini di calcolo, poiché non vengono elaborati tutti gli elementi dell'iteratore originale.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Restituisce il primo elemento dell'iteratore. Se viene fornito `$predicate`, restituisce il primo elemento che soddisfa la condizione data. La funzione `$predicate` ha la firma `function ($value, $key, iterable $iterable): bool`. Se non viene trovato alcun elemento corrispondente, viene richiamata la funzione `$else` (se fornita) e viene restituito il suo risultato. Se `$else` non è fornito, viene restituito `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Questo metodo è utile quando è necessario recuperare rapidamente il primo elemento di un insieme o il primo elemento che soddisfa una determinata condizione, senza dover iterare manualmente l'intero insieme.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Restituisce la chiave del primo elemento dell'iteratore. Se viene fornito `$predicate`, restituisce la chiave del primo elemento che soddisfa la condizione data. La funzione `$predicate` ha la firma `function ($value, $key, iterable $iterable): bool`. Se non viene trovato alcun elemento corrispondente, viene richiamata la funzione `$else` (se fornita) e viene restituito il suo risultato. Se `$else` non viene fornito, viene restituito `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Crea un nuovo iteratore applicando la funzione `$transformer` a ogni elemento dell'iteratore originale. La funzione `$transformer` ha la firma `function ($value, $key, iterable $iterable): mixed` e il suo valore di ritorno viene utilizzato come nuovo valore dell'elemento.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Il metodo utilizza un generatore, il che significa che la trasformazione avviene in modo incrementale durante l'iterazione. Questo metodo è efficiente dal punto di vista della memoria e consente di gestire collezioni molto grandi. Se non si iterano tutti gli elementi dell'iteratore risultante, si risparmia in termini di calcolo, poiché non vengono elaborati tutti gli elementi dell'iteratore originale.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Crea un nuovo iteratore trasformando i valori e le chiavi dell'iteratore originale. La funzione `$transformer` ha la firma `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Se `$transformer` restituisce `null`, l'elemento viene saltato. Per gli elementi mantenuti, il primo elemento dell'array restituito viene utilizzato come nuova chiave e il secondo elemento come nuovo valore.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Come `map()`, questo metodo utilizza un generatore per l'elaborazione incrementale e l'efficienza della memoria. In questo modo è possibile lavorare con collezioni di grandi dimensioni e risparmiare sullo sforzo computazionale elaborando solo una parte del risultato.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Crea un wrapper attorno a un iteratore che memorizza nella cache le chiavi e i valori durante l'iterazione. Ciò consente di ripetere l'iterazione dei dati senza dover rielaborare la fonte di dati originale.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Questo metodo è utile nelle situazioni in cui è necessario iterare più volte sullo stesso insieme di dati, ma l'iteratore originale non supporta l'iterazione ripetuta o l'iterazione ripetuta sarebbe costosa (ad esempio, la lettura di dati da un database o da un file).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Verifica se almeno un elemento dell'iteratore soddisfa la condizione definita in `$predicate`. La funzione `$predicate` ha la firma `function ($value, $key, iterable $iterable): bool` e deve restituire `true` per almeno un elemento affinché il metodo `some()` restituisca `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Questo metodo è utile per verificare rapidamente se in un insieme c'è almeno un elemento che soddisfa una certa condizione, ad esempio se l'insieme contiene almeno un numero pari.
+
+Vedere [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Converte qualsiasi oggetto iterabile (array, Traversable) in un iteratore. Se l'input è già un iteratore, viene restituito invariato.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Questo metodo è utile quando è necessario assicurarsi di avere un Iteratore, indipendentemente dal tipo di dati in ingresso. Può essere utile quando si creano funzioni che lavorano con diversi tipi di dati iterabili.
diff --git a/utils/it/json.texy b/utils/it/json.texy
index 6a4771124b..1948062ef6 100644
--- a/utils/it/json.texy
+++ b/utils/it/json.texy
@@ -77,7 +77,7 @@ L'impostazione `$forceArray` forza la restituzione di array invece che di oggett
 
 ```php
 Json::decode('{"variable": true}'); // restituisce un oggetto di tipo stdClass
-Json::decode('{"variable": true}', forceArray: true); // restituisce un array
+Json::decode('{"variable": true}', forceArrays: true); // restituisce un array
 ```
 
 Lancia un'eccezione `Nette\Utils\JsonException` in caso di errore.
diff --git a/utils/it/smartobject.texy b/utils/it/smartobject.texy
index aefed8cef1..a9247d68bc 100644
--- a/utils/it/smartobject.texy
+++ b/utils/it/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject e StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject aggiunge il supporto per le *proprietà* alle classi PHP. StaticClass è usato per indicare le classi statiche.
+SmartObject correggeva il comportamento degli oggetti in molti modi, ma il PHP di oggi include già la maggior parte di questi miglioramenti in modo nativo. Tuttavia, aggiunge ancora il supporto per le *proprietà*.
 
 
 Installazione:
@@ -65,31 +65,16 @@ echo $circle->visible; // chiama isVisible()
 Le proprietà sono principalmente "zucchero sintattico" ((syntactic sugar)), che ha lo scopo di rendere più dolce la vita del programmatore semplificando il codice. Se non le si vuole, non è necessario usarle.
 
 
-Classi statiche .[#toc-static-classes]
-======================================
+Uno sguardo alla storia .[#toc-a-glimpse-into-history]
+======================================================
 
-Le classi statiche, cioè quelle che non sono destinate ad essere istanziate, possono essere contrassegnate con il tratto `Nette\StaticClass`:
+SmartObject era solito perfezionare il comportamento degli oggetti in molti modi, ma il PHP di oggi incorpora già la maggior parte di questi miglioramenti in modo nativo. Il testo che segue è uno sguardo nostalgico alla storia, che ci ricorda come si sono evolute le cose.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Quando si tenta di creare un'istanza, viene lanciata l'eccezione `Error`, che indica che la classe è statica.
-
-
-Uno sguardo alla storia .[#toc-a-look-into-the-history]
-=======================================================
-
-SmartObject migliorava e correggeva il comportamento delle classi in molti modi, ma l'evoluzione di PHP ha reso superflua la maggior parte delle caratteristiche originali. Di seguito viene presentata la storia di come si sono evolute le cose.
-
-Fin dall'inizio, il modello a oggetti di PHP soffriva di una serie di gravi difetti e inefficienze. Questo è stato il motivo della creazione della classe `Nette\Object` (nel 2007), che ha cercato di porvi rimedio e di migliorare l'esperienza d'uso di PHP. È bastato che altre classi ereditassero da essa per trarne i benefici. Quando PHP 5.4 ha introdotto il supporto ai trait, la classe `Nette\Object` è stata sostituita da `Nette\SmartObject`. Pertanto, non era più necessario ereditare da un antenato comune. Inoltre, i trait potevano essere usati in classi che già ereditavano da un'altra classe. La fine definitiva di `Nette\Object` avvenne con il rilascio di PHP 7.2, che proibiva alle classi di chiamarsi `Object`.
+Fin dall'inizio, il modello a oggetti di PHP soffriva di una miriade di gravi mancanze e carenze. Questo ha portato alla creazione della classe `Nette\Object` (nel 2007), che mirava a correggere questi problemi e a migliorare il comfort dell'utilizzo di PHP. Bastava che altre classi ereditassero da essa per ottenere i vantaggi che offriva. Quando PHP 5.4 ha introdotto il supporto ai tratti, la classe `Nette\Object` è stata sostituita dal tratto `Nette\SmartObject`. Questo ha eliminato la necessità di ereditare da un antenato comune. Inoltre, il tratto poteva essere usato in classi che già ereditavano da un'altra classe. La fine definitiva di `Nette\Object` avvenne con il rilascio di PHP 7.2, che proibiva alle classi di chiamarsi `Object`.
 
-Con il proseguire dello sviluppo di PHP, il modello a oggetti e le funzionalità del linguaggio sono stati migliorati. Le singole funzioni della classe `SmartObject` sono diventate superflue. Dal rilascio di PHP 8.2, l'unica caratteristica rimasta che non è ancora direttamente supportata in PHP è la possibilità di usare le cosiddette [proprietà |#Properties, Getters and Setters].
+Con il proseguire dello sviluppo di PHP, il suo modello di oggetti e le capacità del linguaggio sono migliorati. Diverse funzioni della classe `SmartObject` sono diventate superflue. Dal rilascio di PHP 8.2, rimane solo una caratteristica non supportata direttamente da PHP: la possibilità di usare le cosiddette [proprietà |#Properties, getters, and setters].
 
-Quali funzioni offrivano un tempo `Nette\Object` e `Nette\Object`? Ecco una panoramica. (Gli esempi utilizzano la classe `Nette\Object`, ma la maggior parte delle proprietà si applicano anche al tratto `Nette\SmartObject` ).
+Quali caratteristiche offrivano `Nette\Object` e, per estensione, `Nette\SmartObject`? Ecco una panoramica. (Negli esempi viene utilizzata la classe `Nette\Object`, ma la maggior parte delle caratteristiche si applicano anche al tratto `Nette\SmartObject` ).
 
 
 Errori inconsistenti .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Il PHP di oggi potrebbe non avere alcuna forma di "did you mean?", ma [Tracy |tracy:] aggiunge questa appendice agli errori. E può persino [correggere |tracy:open-files-in-ide#toc-demos] tali errori da solo.
+Sebbene il PHP di oggi non disponga di una funzione di "hai inteso?", questa frase può essere aggiunta agli errori da [Tracy |tracy:]. Può anche [correggere automaticamente tali errori |tracy:open-files-in-ide#toc-demos].
 
 
 Metodi di estensione .[#toc-extension-methods]
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/it/staticclass.texy b/utils/it/staticclass.texy
new file mode 100644
index 0000000000..50cdbf5ebd
--- /dev/null
+++ b/utils/it/staticclass.texy
@@ -0,0 +1,21 @@
+Classi statiche
+***************
+
+.[perex]
+StaticClass è usato per indicare le classi statiche.
+
+
+Installazione:
+
+```shell
+composer require nette/utils
+```
+
+Le classi statiche, cioè quelle che non sono destinate a essere istanziate, possono essere contrassegnate con il tratto [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/it/strings.texy b/utils/it/strings.texy
index f3c27865d7..d82f83168c 100644
--- a/utils/it/strings.texy
+++ b/utils/it/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modifica la stringa UTF-8 nella forma usata nell'URL, cioè rimuove i diacritici e sostituisce tutti i caratteri tranne le lettere dell'alfabeto inglese e i numeri con un trattino.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Richiede l'estensione PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Rimuove tutti gli spazi a sinistra e a destra (o i caratteri passati come secondo argomento) da una stringa codificata UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Restituisce una parte della stringa UTF-8 specificata dalla posizione iniziale `$start` e dalla lunghezza `$length`. Se `$start` è negativo, la stringa restituita inizierà a partire dal `$start`'esimo carattere dalla fine della stringa.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Utilizzare `str_contains()` nativo :https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Confronta due stringhe UTF-8 o le loro parti, senza tenere conto del caso dei caratteri. Se `$length` è nullo, vengono confrontate le stringhe intere, se è negativo, viene confrontato il numero corrispondente di caratteri dalla fine delle stringhe, altrimenti viene confrontato il numero appropriato di caratteri dall'inizio.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Cerca nella stringa tutte le occorrenze che corrispondono all'espressione regolare e restituisce un array di array contenenti l'espressione trovata e ogni sottoespressione.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Se `$lazy` è `true`, la funzione restituisce un `Generator` invece di un array, con notevoli vantaggi in termini di prestazioni quando si lavora con stringhe di grandi dimensioni. Il generatore consente di trovare le corrispondenze in modo incrementale, anziché elaborare l'intera stringa in una sola volta. Ciò consente di gestire in modo efficiente testi di input molto grandi. Inoltre, è possibile interrompere l'elaborazione in qualsiasi momento se si trova la corrispondenza desiderata, risparmiando tempo di calcolo.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/it/validators.texy b/utils/it/validators.texy
index e76da8432a..97e3599fa4 100644
--- a/utils/it/validators.texy
+++ b/utils/it/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Verifica che l'elemento `$key` nell'array `$array` sia dei [tipi previsti |#expected types] separati da pipe. In caso contrario, lancia l'eccezione [api:Nette\Utils\AssertionException]. La stringa `item '%' in array` nel messaggio di eccezione può essere sostituita dal parametro `$label`.
 
diff --git a/utils/pl/@home.texy b/utils/pl/@home.texy
index 6912d59579..7e11a511f6 100644
--- a/utils/pl/@home.texy
+++ b/utils/pl/@home.texy
@@ -10,16 +10,17 @@ W pakiecie `nette/utils` znajdziesz zestaw przydatnych klas do codziennego użyt
 | [elementów HTML |html-elements] | Nette\Utils\Html
 | [JSON |json] | Nette\Utils\Json
 | [Losowe ciągi znaków |random]  | Nette\Utils\Random
-| [Model Obiektów |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Obrazki |images] | Nette\Utils\Image
 | [Odbicie w PHP |reflection] | Nette\Utils\Reflection
 | [typy PHP |type] Nette\Utils\Type
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [Arrays |arrays] | Nette\Utils\Arrays
 | [Helper Functions |helpers] | Nette\Utils\Helpers
 | [Porównywanie pływaków |floats]  | Nette\Utils\Floats
 | [Strings |strings] | Nette\Utils\Strings
 | [System plików |filesystem] | Nette\Utils\Filesystem
 | [Paginator |paginator] | Nette\Utils\Paginator
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Walidator |validators] | Nette\Utils\Validator
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | wersja zgodna z PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/pl/@left-menu.texy b/utils/pl/@left-menu.texy
index 73189365a3..2cd09d7774 100644
--- a/utils/pl/@left-menu.texy
+++ b/utils/pl/@left-menu.texy
@@ -8,13 +8,15 @@ Pakiet Nette/utils
 - [JSON |JSON]
 - [Losowe ciągi |random]
 - [Obrazy |images]
+- [Iterables |iterables]
 - [Paginator |paginator]
 - [Refleksja w PHP |reflection]
 - [Rodzaje PHP |type]
 - [Tablice |arrays]
 - [Funkcje pomocnicze |helpers]
 - [Struny |strings]
-- [SmartObject |smartobject]
+- [SmartObject]
+- [StaticClass]
 - [System plików |filesystem]
 - [Walidator |validators]
 
diff --git a/utils/pl/arrays.texy b/utils/pl/arrays.texy
index f53b6e0e62..bd3a0c1461 100644
--- a/utils/pl/arrays.texy
+++ b/utils/pl/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Tablice .[#toc-arrays]
 ======================
 
-[api:Nette\Utils\Arrays] jest klasą statyczną zawierającą przydatne funkcje do pracy z tablicami.
+[api:Nette\Utils\Arrays] to statyczna klasa, która zawiera kilka przydatnych funkcji tablicowych. Jej odpowiednikiem dla iteratorów jest [Nette\Utils\Iterables |iterables].
 
 Poniższe przykłady zakładają, że alias został utworzony:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Funkcja elastycznie przekształca `$array` w tablicę asocjacyjną lub obiekty zgodnie z określoną ścieżką `$path`. Ścieżka może być łańcuchem lub tablicą. Składa się z nazw kluczy w tablicy wejściowej i operatorów takich jak "[]", "->", "=" i "|". Rzuca `Nette\InvalidArgumentException` jeśli ścieżka jest nieprawidłowa.
+
+```php
+// Konwersja do tablicy asocjacyjnej przy użyciu klucza prostego
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// przypisywanie wartości z jednego klucza do drugiego przy użyciu operatora =
+$result = Arrays::associate($arr, 'name=age'); // lub ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// tworzenie obiektu przy użyciu operatora ->
+$result = Arrays::associate($arr, '->name'); // lub ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// łączenie kluczy za pomocą operatora |
+$result = Arrays::associate($arr, 'name|age'); // lub ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// dodawanie do tablicy przy użyciu []
+$result = Arrays::associate($arr, 'name[]'); // lub ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,10 +76,10 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
-Testuje czy wszystkie elementy w tablicy przechodzą test zaimplementowany w `$callback` z podpisem `function ($value, $key, array $array): bool`.
+Testuje czy wszystkie elementy w tablicy przechodzą test zaimplementowany w `$predicate` z podpisem `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 30, 39, 29, 10, 13];
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Zobacz [some() |#some].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Zwraca nową tablicę zawierającą wszystkie pary klucz-wartość pasujące do podanego `$predicate`. Wywołanie zwrotne ma sygnaturę `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Zwraca pierwszy wpis z tablicy lub null jeśli tablica jest pusta. Nie zmienia wewnętrznego wskaźnika w przeciwieństwie do `reset()`.
+Zwraca pierwszy element (pasujący do określonego predykatu, jeśli został podany). Jeśli nie ma takiego elementu, zwraca wynik wywołania `$else` lub null.
+Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`.
+
+W przeciwieństwie do `reset()` nie zmienia wewnętrznego wskaźnika. Parametry `$predicate` i `$else` istnieją od wersji 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Zobacz [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Zwraca klucz pierwszego elementu (pasującego do określonego predykatu, jeśli został podany) lub null, jeśli nie ma takiego elementu. Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Zobacz [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Zwraca element `$array[$key]`. Jeśli nie istnieje, to albo rzuca wyjątek `Nette\InvalidArgumentException`, albo jeśli podano trzeci parametr `$default`, to zwraca to.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Zwraca ostatni element (pasujący do określonego predykatu, jeśli został podany). Jeśli nie ma takiego elementu, zwraca wynik wywołania `$else` lub null.
+Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`.
+
+W przeciwieństwie do `end()` nie zmienia wewnętrznego wskaźnika. Parametry `$predicate` i `$else` istnieją od wersji 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Zobacz [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Zwraca ostatni wpis tablicy lub null jeśli tablica jest pusta. Nie zmienia wewnętrznego wskaźnika w przeciwieństwie do `end()`.
+Zwraca klucz ostatniego elementu (pasującego do określonego predykatu, jeśli został podany) lub null, jeśli nie ma takiego elementu. Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Zobacz [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Wywołuje `$callback` na wszystkich elementach tablicy i zwraca tablicę wartości zwrotnych. Callback ma podpis `function ($value, $key, array $array): bool`.
+Wywołuje `$transformer` na wszystkich elementach tablicy i zwraca tablicę wartości zwrotnych. Callback ma podpis `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Tworzy nową tablicę, przekształcając wartości i klucze oryginalnej tablicy. Funkcja `$transformer` ma sygnaturę `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Jeśli `$transformer` zwróci `null`, element jest pomijany. W przypadku zachowanych elementów, pierwszy element zwróconej tablicy jest używany jako nowy klucz, a drugi element jako nowa wartość.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Metoda ta jest przydatna w sytuacjach, gdy trzeba zmienić strukturę tablicy (zarówno klucze, jak i wartości jednocześnie) lub filtrować elementy podczas transformacji (zwracając wartość null dla niechcianych elementów).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Wartości z drugiej tablicy są zawsze dodawane do końca pierwszej. Zniknięcie wartości `10` z drugiego pola może wydawać się nieco mylące. Zauważ, że ta wartość, podobnie jak wartość `5` v poli prvním mají přiřazený stejný numerický klíč `0`, dlatego w tablicy wynikowej znajduje się tylko element z pierwszego pola.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizuje tablicę do tablicy asocjacyjnej. Zastępuje klawisze numeryczne ich wartościami, nowa wartość będzie miała postać `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Zwraca i usuwa wartość elementu z tablicy. Jeśli nie istnieje, rzuca wyjątek lub zwraca wartość `$default`, jeśli jest obecny.
 
@@ -284,10 +397,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
-Testuje czy przynajmniej jeden element w tablicy przechodzi test zaimplementowany w `$callback` z podpisem `function ($value, $key, array $array): bool`.
+Testuje czy przynajmniej jeden element w tablicy przechodzi test zaimplementowany w `$predicate` z podpisem `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 2, 3, 4];
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Wypisuje każdy element tablicy do łańcucha i opakowuje go prefiksem `$prefix` i sufiksem `$suffix`.
 
diff --git a/utils/pl/datetime.texy b/utils/pl/datetime.texy
index 0351423ed4..95ecc93e05 100644
--- a/utils/pl/datetime.texy
+++ b/utils/pl/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Rozšiřuje [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] o možnost zadatku timezone jako řetězec.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
diff --git a/utils/pl/filesystem.texy b/utils/pl/filesystem.texy
index 05514e25fd..01382d8eb5 100644
--- a/utils/pl/filesystem.texy
+++ b/utils/pl/filesystem.texy
@@ -2,9 +2,11 @@ Funkcje systemu plików
 **********************
 
 .[perex]
-[api:Nette\Utils\FileSystem] jest statyczną klasą, która zawiera przydatne funkcje do pracy z systemem plików. Jedną z zalet w stosunku do natywnych funkcji PHP jest to, że w przypadku błędów rzucają one wyjątki.
+[api:Nette\Utils\FileSystem] to klasa, która zawiera przydatne funkcje do pracy z systemem plików. Jedną z zalet w porównaniu z natywnymi funkcjami PHP jest to, że rzucają wyjątki w przypadku błędów.
 
 
+Jeśli chcesz wyszukać pliki na dysku, użyj [Finder |finder].
+
 Instalacja:
 
 ```shell
@@ -174,3 +176,26 @@ Konwertuje ukośniki na znaki specyficzne dla bieżącej platformy, tj. `\` w sy
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Podejście statyczne i niestatyczne .[#toc-static-vs-non-static-approach]
+========================================================================
+
+Aby łatwo zastąpić klasę `FileSystem` inną klasą, na przykład do celów testowych, należy użyć jej w sposób niestatyczny:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/pl/finder.texy b/utils/pl/finder.texy
index 4b2d449b2c..65cb8ea709 100644
--- a/utils/pl/finder.texy
+++ b/utils/pl/finder.texy
@@ -61,6 +61,8 @@ Alternatywą dla metod statycznych jest utworzenie instancji za pomocą `new Fin
 
 W masce można używać [znaków wieloznacznych |#Excluding] `*`, `**`, `?` a `[...]`. Możesz nawet określić w katalogach, na przykład `src/*.php` będzie szukać wszystkich plików PHP w katalogu `src`.
 
+Symlinki są również uważane za katalogi lub pliki.
+
 
 Gdzie szukać? .[#toc-kde-se-ma-hledat]
 --------------------------------------
diff --git a/utils/pl/floats.texy b/utils/pl/floats.texy
index d10b3e72ae..feed8fea69 100644
--- a/utils/pl/floats.texy
+++ b/utils/pl/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Podczas próby porównania `NAN` rzuca wyjątek `\LogicException`.
 
+.[tip]
+Klasa `Floats` toleruje różnice mniejsze niż `1e-10`. Jeśli potrzebujesz pracować z większą precyzją, użyj zamiast tego biblioteki BCMath.
+
 
 Porównywanie pływaków .[#toc-float-comparison]
 ==============================================
diff --git a/utils/pl/html-elements.texy b/utils/pl/html-elements.texy
index 34de52bedf..6ca67d17e0 100644
--- a/utils/pl/html-elements.texy
+++ b/utils/pl/html-elements.texy
@@ -219,10 +219,10 @@ $el = Html::el('span')
 Inny sposób tworzenia i wstawiania nowego węzła `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('první');
-// <ul><li class="first">první</li></ul>
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
+// <ul><li class="first">hello</li></ul>
 ```
 
 Możesz pracować z węzłami tak, jakby były tablicami. To znaczy, uzyskać dostęp do każdego z nich za pomocą nawiasów kwadratowych, policzyć je za pomocą `count()` i iterować nad nimi:
diff --git a/utils/pl/images.texy b/utils/pl/images.texy
index aff3da3f5d..cf50a6c159 100644
--- a/utils/pl/images.texy
+++ b/utils/pl/images.texy
@@ -17,6 +17,8 @@ Wszystkie przykłady zakładają, że alias został utworzony:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Możesz opcjonalnie określić kolor tła (domyślnie jest to kolor czarny):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Albo załadować obraz z pliku:
@@ -41,17 +43,6 @@ Albo załadować obraz z pliku:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Obsługiwane formaty to JPEG, PNG, GIF, WebP, AVIF i BMP, ale twoja wersja PHP musi je również obsługiwać (sprawdź `phpinfo()`, sekcja GD). Animacje nie są obsługiwane.
-
-Czy musisz wykryć format obrazu podczas ładowania? Metoda zwraca go w drugim parametrze:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type to Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF lub Image::BMP
-```
-
-Tylko wykrywanie bez ładowania obrazu odbywa się przez `Image::detectTypeFromFile()`.
-
 
 Zapisywanie obrazu .[#toc-save-the-image]
 =========================================
@@ -68,25 +59,45 @@ Możemy określić jakość kompresji w zakresie 0..100 dla JPEG (domyślnie 85)
 $image->save('resampled.jpg', 80); // JPEG, jakość 80%
 ```
 
-Jeśli format nie jest oczywisty na podstawie rozszerzenia pliku, może być określony przez jedną ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, oraz `Image::BMP`:
+Jeśli format nie jest oczywisty na podstawie rozszerzenia pliku, można go określić za pomocą [stałej |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Obraz może być zapisany do zmiennej zamiast na dysk:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, qualita 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, qualita 80%
 ```
 
 lub wysyłane bezpośrednio do przeglądarki z odpowiednim nagłówkiem HTTP `Content-Type`:
 
 ```php
 // wysyła nagłówek Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formaty .[#toc-formats]
+=======================
+
+Obsługiwane formaty to JPEG, PNG, GIF, WebP, AVIF i BMP. Muszą być one jednak również obsługiwane przez daną wersję PHP, co można zweryfikować za pomocą funkcji [isTypeSupported() |#isTypeSupported()]. Animacje nie są obsługiwane.
+
+Formaty są reprezentowane przez stałe `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` i `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Chcesz wykryć format obrazu podczas ładowania? Metoda zwraca go w drugim parametrze:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Rzeczywiste wykrywanie bez ładowania obrazu jest wykonywane przez `Image::detectTypeFromFile()`.
+
 
 Zmień rozmiar .[#toc-image-resize]
 ==================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Metoda `cropAuto()` jest obiektowym zamiennikiem funkcji `imagecropauto()`, więcej informacji można znaleźć w [jej dokumentacji |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Kolory .[#toc-colors]
+=====================
+
+Metoda `ImageColor::rgb()` umożliwia zdefiniowanie koloru przy użyciu wartości czerwonego, zielonego i niebieskiego (RGB). Opcjonalnie można również określić wartość przezroczystości w zakresie od 0 (całkowicie przezroczysty) do 1 (całkowicie nieprzezroczysty), podobnie jak w CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Metoda `ImageColor::hex()` umożliwia zdefiniowanie koloru przy użyciu formatu szesnastkowego, podobnie jak w CSS. Obsługuje formaty `#rgb`, `#rrggbb`, `#rgba` i `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Kolory mogą być używane w innych metodach, takich jak `ellipse()`, `fill()`, itp.
+
+
 Rysowanie i edycja .[#toc-drawing-and-editing]
 ==============================================
 
-Możesz rysować, możesz pisać, ale nie drzyj kartek. Wszystkie funkcje PHP do pracy z obrazami, takie jak [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], są dostępne dla Ciebie, ale w obiektowym domyśle:
+Możesz rysować, możesz pisać, możesz używać wszystkich funkcji PHP do manipulacji obrazem, patrz [Przegląd metod |#Overview of methods], ale w opakowaniu obiektowym:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Zobacz [Przegląd metod |#Overview-of-Methods].
+Ponieważ funkcje PHP do rysowania prostokątów są niepraktyczne ze względu na konieczność określania współrzędnych, klasa `Image` oferuje ich zamienniki w postaci funkcji [rectangleWH |#rectangleWH()] [( |#filledRectangleWH()] [) |#rectangleWH()] i [filledRectangleWH() |#filledRectangleWH()].
 
 
 Łączenie wielu obrazów .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Możesz łatwo wstawić inny obraz do obrazu:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // współrzędne mogą być ponownie podane w procentach
 $blank->place($logo, '80%', '80%'); // wstawiamy w pobliżu prawego dolnego rogu
@@ -219,53 +250,68 @@ Przegląd metod .[#toc-overview-of-methods]
 ==========================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Tworzy nowy obraz w kolorze rzeczywistym o podanych wymiarach. Domyślnym kolorem jest czarny.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Odczytuje obraz z pliku i zwraca jego typ w `$detectedFormat`. Obsługiwane typy to `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` oraz `Image::BMP`.
+Odczytuje obraz z pliku i zwraca jego [typ |#Formats] w `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Odczytuje obraz z łańcucha i zwraca jego typ w `$detectedFormat`. Obsługiwane typy to `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, oraz `Image::BMP`.
+Odczytuje obraz z ciągu znaków i zwraca jego [typ |#Formats] w `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Tworzy kolor, który może być używany w innych metodach, takich jak `ellipse()`, `fill()`, itp.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Funkcja ta została zastąpiona przez klasę `ImageColor`, patrz [kolory |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Zwraca rozszerzenie pliku dla podanej stałej `Image::XXX`.
+Zwraca rozszerzenie pliku dla podanego [typu |#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Zwraca typ mime dla podanej stałej `Image::XXX`.
+Zwraca typ mime dla podanego [typu |#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Zwraca typ obrazu jako stałą `Image::XXX` zgodnie z rozszerzeniem pliku.
+Zwraca [typ |#Formats] obrazu zgodnie z rozszerzeniem pliku.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Zwraca typ obrazu jako stałą `Image::XXX`, a także jego wymiary w parametrach `$width` i `$height`.
+Zwraca [typ |#Formats] pliku obrazu, a w parametrach `$width` i `$height` także jego wymiary.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Zwraca typ obrazu z ciągu jako stałą `Image::XXX` oraz jego wymiary w parametrach `$width` i `$height`.
+Zwraca [typ |#Formats] obrazu z ciągu znaków, a w parametrach `$width` i `$height` również jego wymiary.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Określa, czy dany [typ |#Formats] obrazu jest obsługiwany.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Zwraca tablicę obsługiwanych typów obrazów (stałe `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Oblicza wymiary prostokąta otaczającego tekst o określonej czcionce i rozmiarze. Zwraca tablicę asocjacyjną zawierającą klucze `left`, `top`, `width`, `height`. Lewy margines może być ujemny, jeśli tekst zaczyna się od lewego nawisu.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Zwróć obraz zawierający affine-transformed src image używając opcjonalnego regionu przycinania ([więcej |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Zwraca konkatenację dwóch macierzy przekształceń afinicznych, co jest przydatne, gdy do tego samego obrazu należy zastosować wiele przekształceń jednocześnie. ([więcej |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Zwraca macierz przekształcenia macierzy ([więcej |https://www.php.net/manual/en/function.imageaffinematrixget]).
 
 
@@ -291,21 +337,11 @@ Aktywuj rysowanie linii wygładzonych i wielokątów. Nie obsługuje kanałów a
 Użycie antyaliasowanego prymitywu z przezroczystym kolorem tła może skończyć się nieoczekiwanymi rezultatami. Metoda blend wykorzystuje kolor tła jak każdy inny kolor. ([więcej |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Rysuje łuk okręgu o środku w podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Rysuje pierwszy znak `$char` w obrazie z lewym górnym rogiem na `$x`, `$y` (lewy górny to 0, 0) w kolorze `$color`. ([więcej |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Rysuje znak `$char` w pionie na określonej współrzędnej w podanym obrazie. ([więcej |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Zwraca identyfikator koloru reprezentujący kolor złożony z podanych składowych RGB. Musi być wywołany, aby stworzyć każdy kolor, który ma być użyty w obrazie. ([więcej |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Zwraca liczbę kolorów w palecie obrazów. ([więcej |https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Uzyskuje lub ustawia kolor przezroczysty w obrazie. ([więcej |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Przycina obraz do zadanego prostokątnego obszaru. Wymiary mogą być określone jako liczby całkowite w pikselach lub ciągi znaków w procentach (na przykład `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Automatycznie przycina obraz zgodnie z podanym `$mode`. ([więcej |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Rysuje elipsę wyśrodkowaną na podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Wypełnia obszar zaczynający się na podanej współrzędnej (lewa górna to 0, 0) podaną `$color`. ([więcej |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Rysuje częściowy łuk o środku w podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Rysuje elipsę wyśrodkowaną na podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Tworzy wypełniony wielokąt w obrazie. ([więcej |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Tworzy prostokąt wypełniony stroną `$color` w obrazie zaczynając od punktu 1 i kończąc w punkcie 2. Punkt 0, 0 jest lewym górnym rogiem obrazu. ([więcej |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Tworzy prostokąt wypełniony `$color` na obrazie, zaczynając od `$x1` i `$y1`, a kończąc na `$x2` i `$y2`. Punkt 0, 0 to lewy górny róg obrazu. ([więcej |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Tworzy prostokąt wypełniony `$color` na obrazie, zaczynając od punktów `$left` i `$top` o szerokości `$width` i wysokości `$height`. Punkt 0, 0 to lewy górny róg obrazu.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Tworzy wypełnienie, którego kolor jest określony przez `$border`. Punktem początkowym wypełnienia jest `$x`, `$y` (lewa górna część to 0, 0), a obszar jest wypełniony kolorem `$color`. ([więcej |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Odwraca obraz za pomocą podanego `$mode`. ([więcej |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Napisz tekst w obrazie za pomocą czcionek z FreeType 2. ([więcej |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Wpisz tekst na obrazku. ([więcej |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Zwraca szerokość obrazu.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Włącza lub wyłącza tryb przeplotu. Jeśli ustawiony jest tryb z przeplotem, a obraz jest zapisywany jako JPEG, zostanie on zapisany jako JPEG progresywny. ([więcej |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Ustaw flagę alfa blend, aby użyć efektów warstwowych. ([więcej |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Rysuje linię pomiędzy dwoma podanymi punktami. ([więcej |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Rysuje na obrazie otwarty wielokąt. W odróżnieniu od `polygon()`, między ostatnim a pierwszym punktem nie rysuje się linii. ([więcej |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Kopiuje stronę `$image` do obrazu na współrzędnych `$left` i `$top`. Współrzędne mogą być określone jako liczby całkowite w pikselach lub łańcuchy w procentach (na przykład `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Tworzy wielokąt w obrazie. ([więcej |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Tworzy prostokąt na podanych współrzędnych ([więcej |https://www.php.net/manual/en/function.imagerectangle]).
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Tworzy prostokąt o podanych współrzędnych.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Zmienia rozmiar obrazu, [więcej informacji |#Image-Resize]. Wymiary mogą być określone jako liczby całkowite w pikselach lub ciągi znaków w procentach (na przykład `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Ustawia lub zwraca rozdzielczość obrazu w DPI (punkty na cal). Jeśli żaden z opcjonalnych parametrów nie zostanie określony, bieżąca rozdzielczość jest zwracana jako indeksowane pole. Jeśli określona jest tylko `$resX`, rozdzielczość pozioma i pionowa są ustawione na tę wartość. Jeśli oba opcjonalne parametry są określone, rozdzielczości pozioma i pionowa są ustawione na te wartości.
 
 Rozdzielczość jest używana jako meta informacja tylko wtedy, gdy obrazy są odczytywane i zapisywane w formatach obsługujących ten rodzaj informacji (obecnie PNG i JPEG). Nie ma to wpływu na żadne operacje rysunkowe. Domyślna rozdzielczość nowych zdjęć to 96 DPI. ([więcej |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Obraca obraz przy użyciu określonej `$angle` w stopniach. Środek obrotu jest
 Wymaga obecności rozszerzenia *Bundled GD*, więc może nie działać wszędzie.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Zapisuje obraz do pliku.
 
-Jakość kompresji jest w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Jeśli typ nie jest oczywisty na podstawie rozszerzenia pliku, można go określić za pomocą jednej ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, oraz `Image::BMP`.
+Jakość kompresji mieści się w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Jeśli typ nie jest oczywisty z rozszerzenia pliku, można go określić za pomocą jednej ze stałych `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Skalowanie obrazu z wykorzystaniem podanego algorytmu interpolacji. ([więcej |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Drukuje obraz do przeglądarki.
 
-Jakość kompresji jest w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Typ jest jedną ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` oraz `Image::BMP`.
+Jakość kompresji mieści się w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Ustawia metodę interpolacji, która wpływa na metody `rotate()` i `affine()`. ([więcej |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Rysuje piksel na określonej współrzędnej. ([więcej |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Wyostrza obraz.
 Wymaga obecności rozszerzenia *Bundled GD*, więc może nie działać wszędzie.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Wypisuje ciąg znaków na podane współrzędne. ([więcej |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Wypisuje ciąg znaków w pionie na podane współrzędne. ([więcej |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Zapisuje obraz w postaci ciągu znaków.
 
-Jakość kompresji jest w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Typ jest jedną ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` oraz `Image::BMP`.
+Jakość kompresji mieści się w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Konwertuje obraz truecolor na obraz palety. ([więcej |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Drukuje podany tekst do obrazu przy użyciu czcionek TrueType. ([więcej |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Zapisuje podany tekst na obrazie. ([więcej |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/pl/iterables.texy b/utils/pl/iterables.texy
new file mode 100644
index 0000000000..6bf8fb8a34
--- /dev/null
+++ b/utils/pl/iterables.texy
@@ -0,0 +1,170 @@
+Funkcje iteratora
+*****************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] to statyczna klasa z funkcjami do pracy z iteratorami. Jej odpowiednikiem dla tablic jest [Nette\Utils\Arrays |arrays].
+
+
+Instalacja:
+
+```shell
+composer require nette/utils
+```
+
+Wszystkie przykłady zakładają utworzenie następującego aliasu:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Wyszukuje daną wartość w iteratorze. Używa ścisłego porównania (`===`), aby sprawdzić dopasowanie. Zwraca `true` jeśli wartość zostanie znaleziona, w przeciwnym razie `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Ta metoda jest przydatna, gdy trzeba szybko określić, czy określona wartość jest obecna w iteratorze bez ręcznego iterowania przez wszystkie elementy.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Wyszukuje dany klucz w iteratorze. Używa ścisłego porównania (`===`) do sprawdzenia dopasowania. Zwraca `true` jeśli klucz został znaleziony, w przeciwnym razie `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Sprawdza, czy wszystkie elementy iteratora spełniają warunek zdefiniowany w `$predicate`. Funkcja `$predicate` ma sygnaturę `function ($value, $key, iterable $iterable): bool` i musi zwrócić `true` dla każdego elementu, aby metoda `every()` zwróciła `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Metoda ta jest przydatna do sprawdzania, czy wszystkie elementy w kolekcji spełniają określony warunek, np. czy wszystkie liczby są poniżej określonej wartości.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Tworzy nowy iterator, który zawiera tylko te elementy z oryginalnego iteratora, które spełniają warunek zdefiniowany w `$predicate`. Funkcja `$predicate` ma sygnaturę `function ($value, $key, iterable $iterable): bool` i musi zwracać `true` dla elementów, które powinny zostać zachowane.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Metoda wykorzystuje generator, co oznacza, że filtrowanie odbywa się przyrostowo podczas iteracji. Jest to wydajne pod względem pamięci i pozwala na obsługę bardzo dużych kolekcji. Jeśli nie iterujesz przez wszystkie elementy wynikowego iteratora, oszczędzasz wysiłek obliczeniowy, ponieważ nie wszystkie elementy oryginalnego iteratora są przetwarzane.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Zwraca pierwszy element iteratora. Jeśli podano `$predicate`, zwraca pierwszy element, który spełnia podany warunek. Funkcja `$predicate` ma sygnaturę `function ($value, $key, iterable $iterable): bool`. Jeśli nie zostanie znaleziony żaden pasujący element, wywoływana jest funkcja `$else` (jeśli została podana) i zwracany jest jej wynik. Jeśli nie podano `$else`, zwracana jest `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Ta metoda jest przydatna, gdy trzeba szybko pobrać pierwszy element kolekcji lub pierwszy element spełniający określony warunek bez ręcznego iterowania przez całą kolekcję.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Zwraca klucz pierwszego elementu iteratora. Jeśli podano `$predicate`, zwraca klucz pierwszego elementu, który spełnia podany warunek. Funkcja `$predicate` ma sygnaturę `function ($value, $key, iterable $iterable): bool`. Jeśli nie zostanie znaleziony żaden pasujący element, wywoływana jest funkcja `$else` (jeśli została podana) i zwracany jest jej wynik. Jeśli nie podano `$else`, zwracana jest `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Tworzy nowy iterator poprzez zastosowanie funkcji `$transformer` do każdego elementu oryginalnego iteratora. Funkcja `$transformer` ma sygnaturę `function ($value, $key, iterable $iterable): mixed`, a jej wartość zwracana jest używana jako nowa wartość elementu.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Metoda ta wykorzystuje generator, co oznacza, że transformacja odbywa się przyrostowo podczas iteracji. Jest to wydajne pod względem pamięci i pozwala na obsługę bardzo dużych kolekcji. Jeśli nie iterujesz przez wszystkie elementy wynikowego iteratora, oszczędzasz wysiłek obliczeniowy, ponieważ nie wszystkie elementy oryginalnego iteratora są przetwarzane.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Tworzy nowy iterator poprzez przekształcenie wartości i kluczy oryginalnego iteratora. Funkcja `$transformer` ma sygnaturę `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Jeśli `$transformer` zwróci `null`, element jest pomijany. Dla zachowanych elementów, pierwszy element zwróconej tablicy jest używany jako nowy klucz, a drugi element jako nowa wartość.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Podobnie jak `map()`, metoda ta wykorzystuje generator do przetwarzania przyrostowego i wydajności pamięci. Pozwala to na pracę z dużymi kolekcjami i oszczędność wysiłku obliczeniowego poprzez przetwarzanie tylko części wyniku.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Tworzy opakowanie wokół iteratora, które buforuje jego klucze i wartości podczas iteracji. Pozwala to na wielokrotną iterację danych bez konieczności ponownego przetwarzania oryginalnego źródła danych.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Metoda ta jest przydatna w sytuacjach, gdy trzeba wielokrotnie iterować po tym samym zestawie danych, ale oryginalny iterator nie obsługuje wielokrotnej iteracji lub wielokrotna iteracja byłaby kosztowna (np. odczytywanie danych z bazy danych lub pliku).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Sprawdza, czy co najmniej jeden element iteratora spełnia warunek zdefiniowany w `$predicate`. Funkcja `$predicate` ma sygnaturę `function ($value, $key, iterable $iterable): bool` i musi zwrócić `true` dla co najmniej jednego elementu, aby metoda `some()` zwróciła `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Metoda ta jest przydatna do szybkiego sprawdzenia, czy w kolekcji znajduje się co najmniej jeden element spełniający określony warunek, np. czy kolekcja zawiera co najmniej jedną liczbę parzystą.
+
+Zobacz [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Konwertuje dowolny obiekt iterowalny (tablicę, Traversable) na Iterator. Jeśli dane wejściowe są już Iteratorem, są zwracane bez zmian.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Ta metoda jest przydatna, gdy trzeba upewnić się, że mamy Iterator, niezależnie od typu danych wejściowych. Może to być przydatne podczas tworzenia funkcji, które działają z różnymi typami danych iterowalnych.
diff --git a/utils/pl/json.texy b/utils/pl/json.texy
index 379ea35dbb..05fc0a0ae8 100644
--- a/utils/pl/json.texy
+++ b/utils/pl/json.texy
@@ -77,7 +77,7 @@ Ustawienie `$forceArray` wymusza zwracanie tablic zamiast obiektów:
 
 ```php
 Json::decode('{"variable": true}'); // zwraca obiekt typu stdClass
-Json::decode('{"variable": true}', forceArray: true); // zwraca tablicę
+Json::decode('{"variable": true}', forceArrays: true); // zwraca tablicę
 ```
 
 Rzuca wyjątek w przypadku wystąpienia błędu `Nette\Utils\JsonException`.
diff --git a/utils/pl/smartobject.texy b/utils/pl/smartobject.texy
index 138a67a5fc..199dd1fd8c 100644
--- a/utils/pl/smartobject.texy
+++ b/utils/pl/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject i StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject dodaje do klas PHP wsparcie dla *property*. StaticClass służy do oznaczania klas statycznych.
+SmartObject poprawiał zachowanie obiektów na wiele sposobów, ale dzisiejszy PHP zawiera już większość tych ulepszeń natywnie. Wciąż jednak dodaje wsparcie dla *property*.
 
 
 Instalacja:
@@ -65,31 +65,16 @@ echo $circle->visible; // volá isVisible()
 Właściwości to przede wszystkim "cukier syntaktyczny"((syntactic sugar)), który ma uczynić życie programisty słodszym poprzez uproszczenie kodu. Jeśli ich nie chcesz, nie musisz z nich korzystać.
 
 
-Klasy statyczne .[#toc-staticke-tridy]
-======================================
+Rzut oka na historię .[#toc-a-glimpse-into-history]
+===================================================
 
-Klasy statyczne, czyli takie, które nie są przeznaczone do instancjonowania, mogą być oznaczone cechą `Nette\StaticClass`:
+SmartObject udoskonalał zachowanie obiektów na wiele sposobów, ale dzisiejszy PHP zawiera już większość tych ulepszeń natywnie. Poniższy tekst jest nostalgicznym spojrzeniem wstecz na historię, przypominającym nam, jak rzeczy ewoluowały.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Podczas próby utworzenia instancji rzucany jest wyjątek `Error` wskazujący, że klasa jest statyczna.
-
-
-Spojrzenie na historię
-======================
-
-SmartObject kiedyś poprawiał i naprawiał zachowanie klasy na wiele sposobów, ale ewolucja PHP sprawiła, że większość oryginalnych funkcji stała się zbędna. Poniżej przedstawiamy więc spojrzenie na historię tego, jak sprawy się rozwijały.
-
-Model obiektowy PHP od początku cierpiał na szereg poważnych wad i nieefektywności. Z tego powodu powstała klasa `Nette\Object` (w 2007 roku), która starała się im zaradzić i poprawić doświadczenia związane z używaniem PHP. Wystarczyło, aby inne klasy dziedziczyły po niej i czerpały korzyści, które przynosiła. Kiedy w PHP 5.4 pojawiła się obsługa cech, klasa `Nette\Object` została zastąpiona przez `Nette\SmartObject`. Tym samym nie było już konieczności dziedziczenia po wspólnym przodku. Dodatkowo trait można było wykorzystać w klasach, które już dziedziczyły po innej klasie. Ostateczny koniec `Nette\Object` nastąpił wraz z wydaniem PHP 7.2, który zabronił klasom nadawania nazw `Object`.
+Od samego początku model obiektowy PHP cierpiał na niezliczoną ilość poważnych niedociągnięć i braków. Doprowadziło to do stworzenia klasy `Nette\Object` (w 2007 roku), która miała na celu naprawienie tych problemów i zwiększenie komfortu korzystania z PHP. Wystarczyło tylko, by inne klasy po niej dziedziczyły, a zyskałyby oferowane przez nią korzyści. Gdy w PHP 5.4 wprowadzono obsługę cech, klasa `Nette\Object` została zastąpiona cechą `Nette\SmartObject`. Wyeliminowało to potrzebę dziedziczenia po wspólnym przodku. Co więcej, cecha mogła być używana w klasach, które już dziedziczyły po innej klasie. Ostateczny koniec `Nette\Object` nastąpił wraz z wydaniem PHP 7.2, które zabroniło klasom nazywania się `Object`.
 
-Wraz z rozwojem PHP udoskonalano model obiektowy i możliwości języka. Poszczególne funkcje klasy `SmartObject` stały się zbędne. Od wydania PHP 8.2 jedyną cechą, która pozostała, a która nie jest jeszcze bezpośrednio wspierana w PHP, jest możliwość korzystania z tzw. [właściwości |#Properties, gettery a settery].
+W miarę rozwoju PHP, jego model obiektowy i możliwości językowe ulegały poprawie. Różne funkcje klasy `SmartObject` stały się zbędne. Od wydania PHP 8.2 pozostała tylko jedna funkcja nieobsługiwana bezpośrednio w PHP: możliwość korzystania z tak zwanych [właściwości |#Properties, getters, and setters].
 
-Jakie funkcje oferowały kiedyś `Nette\Object` i `Nette\Object`? Oto przegląd. (W przykładach użyto klasy `Nette\Object`, ale większość właściwości dotyczy również cechy `Nette\SmartObject`).
+Jakie funkcje oferowały `Nette\Object` i, rozszerzając, `Nette\SmartObject`? Oto przegląd. (W przykładach użyto klasy `Nette\Object`, ale większość funkcji dotyczy również cechy `Nette\SmartObject` ).
 
 
 Niespójne błędy .[#toc-nekonzistentni-chyby]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Dzisiejszy PZP może nie ma żadnej formy "czy miałeś na myśli?", ale [Tracy |tracy:] może dodać ten dodatek do błędów. I może nawet [sam naprawić |tracy:open-files-in-ide#Demos] takie błędy.
+Podczas gdy dzisiejszy PHP nie ma funkcji "czy miałeś na myśli?", ta fraza może być dodawana do błędów przez [Tracy |tracy:]. Może nawet [automatycznie korygować takie błędy |tracy:open-files-in-ide#toc-demos].
 
 
 Metody rozszerzania .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // vrátí 'John Doe
+$reflection->getAnnotation('author'); // vrátí 'John Doe'
 ```
 
 Od PHP 8.0 możliwy jest dostęp do metainformacji w postaci atrybutów:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/pl/staticclass.texy b/utils/pl/staticclass.texy
new file mode 100644
index 0000000000..013de13034
--- /dev/null
+++ b/utils/pl/staticclass.texy
@@ -0,0 +1,21 @@
+Klasy statyczne
+***************
+
+.[perex]
+StaticClass służy do oznaczania klas statycznych.
+
+
+Instalacja:
+
+```shell
+composer require nette/utils
+```
+
+Klasy statyczne, tj. klasy, które nie są przeznaczone do instancjonowania, mogą być oznaczone cechą [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/pl/strings.texy b/utils/pl/strings.texy
index 0b9b0abd1d..db0646575c 100644
--- a/utils/pl/strings.texy
+++ b/utils/pl/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modyfikuje ciąg UTF-8 do formatu używanego w adresie URL, tj. usuwa znaki diakrytyczne i zastępuje wszystkie znaki z wyjątkiem liter alfabetu angielskiego i cyfr myślnikiem.
 
@@ -129,8 +129,8 @@ Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
 Wymaga rozszerzenia PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Wycina spacje (lub inne znaki określone przez drugi parametr) z początku i końca łańcucha UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Zwraca część łańcucha UTF-8 `$s` określoną przez pozycję początkową `$start` i długość `$length`. Jeśli `$start` jest ujemny, zwrócony łańcuch rozpocznie się od znaku -`$start` znak od końca.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Korzystaj z rodzimego `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Porównanie bez rozróżniania wielkości liter dwóch łańcuchów UTF-8 lub ich części. Jeśli `$length` zawiera null, to porównywane są całe ciągi, jeśli ujemnie, to porównywana jest odpowiednia liczba znaków z końca ciągów, w przeciwnym razie porównywana jest odpowiednia liczba znaków z początku.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Przeszukuje łańcuch w poszukiwaniu wszystkich wystąpień pasujących do wyrażenia regularnego i zwraca tablicę tablic zawierających dopasowane wyrażenie i każde podwyrażenie.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Jeśli `$lazy` to `true`, funkcja zwraca `Generator` zamiast tablicy, co zapewnia znaczne korzyści w zakresie wydajności podczas pracy z dużymi ciągami znaków. Generator pozwala na znajdowanie dopasowań przyrostowo, zamiast przetwarzania całego ciągu na raz. Umożliwia to wydajną obsługę bardzo dużych tekstów wejściowych. Dodatkowo, można przerwać przetwarzanie w dowolnym momencie, jeśli zostanie znalezione pożądane dopasowanie, oszczędzając czas obliczeniowy.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/pl/validators.texy b/utils/pl/validators.texy
index 16941729a4..9bdb19e91c 100644
--- a/utils/pl/validators.texy
+++ b/utils/pl/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Sprawdza, czy element pod kluczem `$key` w polu `$array` jest jednym z [oczekiwanych typów |#Expected-Types] oddzielonych odwrotnym ukośnikiem. Jeśli nie, rzuca wyjątek [api:Nette\Utils\AssertionException]. Ciąg `item '%' in array` w tekście wyjątku można zastąpić innym parametrem `$label`.
 
diff --git a/utils/pt/@home.texy b/utils/pt/@home.texy
index f9219966f1..51fbe85711 100644
--- a/utils/pt/@home.texy
+++ b/utils/pt/@home.texy
@@ -13,13 +13,14 @@ No pacote `nette/utils` você encontrará um conjunto de aulas úteis para o uso
 | [Ajudantes |helpers] | Nette\Utils\Helpers
 | [Elementos HTML |HTML Elements] | Nette\Utils\Html
 | [Imagens |Images] | Nette\Utils\Image
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [JSON |JSON] | Nette\Utils\Json
-| [Modelo do objeto |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginador de Paginadores |paginator] | Nette\Utils\Paginator
 | [Reflexão PHP Ref |reflection] | Nette\Utils\Reflection
 | [Tipos de PHP |type] | Nette\Utils\Type
 | [Random Strings |random] | Nette\Utils\Random
 | [Cordas |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validadores |validators] Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | versão | compatível com PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/pt/@left-menu.texy b/utils/pt/@left-menu.texy
index 487e5158bd..041f24a015 100644
--- a/utils/pt/@left-menu.texy
+++ b/utils/pt/@left-menu.texy
@@ -8,13 +8,15 @@ Pacote nette/utils
 - [Ajudantes |helpers]
 - [Elementos HTML |HTML Elements]
 - [Imagens |Images]
+- [Iteráveis |iterables]
 - [JSON |JSON]
 - [Paginador |paginator]
 - [Cordas Aleatórias |random]
-- [SmartObject |SmartObject]
 - [Reflexão PHP |reflection]
 - [Cordas |Strings]
 - [Flutuadores |Floats]
+- [SmartObject]
+- [StaticClass]
 - [Tipos de PHP |type]
 - [Validadores |validators]
 
diff --git a/utils/pt/arrays.texy b/utils/pt/arrays.texy
index c7b6db12bb..a523d132d5 100644
--- a/utils/pt/arrays.texy
+++ b/utils/pt/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Arrays .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] é uma classe estática, que contém um punhado de funções de matriz úteis.
+[api:Nette\Utils\Arrays] é uma classe estática que contém um punhado de funções úteis de matriz. Seu equivalente para iteradores é [Nette\Utils\Iterables |iterables].
 
 Os exemplos a seguir assumem que a seguinte classe está definida:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+A função transforma de forma flexível o `$array` em uma matriz associativa ou objetos de acordo com o caminho especificado `$path`. O caminho pode ser uma string ou uma matriz. Ele consiste nos nomes das chaves na matriz de entrada e em operadores como '[]', '->', '=' e '|'. Lança `Nette\InvalidArgumentException` se o caminho for inválido.
+
+```php
+// conversão em uma matriz associativa usando uma chave simples
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// atribuir valores de uma chave a outra usando o operador =
+$result = Arrays::associate($arr, 'name=age'); // ou ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// criar um objeto usando o operador ->
+$result = Arrays::associate($arr, '->name'); // ou ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// combinação de chaves usando o operador |
+$result = Arrays::associate($arr, 'name|age'); // ou ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// adicionando a uma matriz usando []
+$result = Arrays::associate($arr, 'name[]'); // ou ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Testa se todos os elementos da matriz passam no teste implementado pela função fornecida, que tem a assinatura `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Veja [algumas() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Retorna uma nova matriz contendo todos os pares de valores-chave que correspondem ao endereço `$predicate` fornecido. O retorno de chamada tem a assinatura `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Devolve o primeiro item da matriz ou nulo se a matriz estiver vazia. Ele não muda o ponteiro interno ao contrário de `reset()`.
+Retorna o primeiro item (que corresponde ao predicado especificado, se fornecido). Se não houver tal item, ele retorna o resultado da invocação de `$else` ou nulo.
+O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`.
+
+Ele não altera o ponteiro interno, ao contrário de `reset()`. Os parâmetros `$predicate` e `$else` existem desde a versão 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Consulte [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Retorna a chave do primeiro item (que corresponde ao predicado especificado, se fornecido) ou nula se não houver tal item. O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Consulte [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Devoluções `$array[$key]` item. Se ele não existir, `Nette\InvalidArgumentException` é lançado, a menos que um valor padrão seja definido como terceiro argumento.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Retorna o último item (que corresponde ao predicado especificado, se fornecido). Se não houver tal item, ele retorna o resultado da invocação de `$else` ou nulo.
+O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`.
+
+Ele não altera o ponteiro interno, ao contrário de `end()`. Os parâmetros `$predicate` e `$else` existem desde a versão 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Consulte [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Devolve o último item da matriz ou nulo se a matriz estiver vazia. Ele não muda o ponteiro interno ao contrário de `end()`.
+Retorna a chave do último item (que corresponde ao predicado especificado, se fornecido) ou nula se não houver tal item. O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Consulte [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Liga para `$callback` sobre todos os elementos da matriz e retorna a matriz de valores de retorno. A chamada de retorno tem a assinatura `function ($value, $key, array $array): bool`.
+Liga para `$transformer` sobre todos os elementos da matriz e retorna a matriz de valores de retorno. A chamada de retorno tem a assinatura `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Cria uma nova matriz transformando os valores e as chaves da matriz original. A função `$transformer` tem a assinatura `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Se `$transformer` retornar `null`, o elemento será ignorado. Para elementos retidos, o primeiro elemento da matriz retornada é usado como a nova chave e o segundo elemento como o novo valor.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Esse método é útil em situações em que você precisa alterar a estrutura de uma matriz (chaves e valores simultaneamente) ou filtrar elementos durante a transformação (retornando null para elementos indesejados).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Os valores da segunda matriz são sempre anexados à primeira. O desaparecimento do valor `10` da segunda matriz pode parecer um pouco confuso. Deve-se notar que tanto este valor quanto o valor `5` in the first array have the same numeric key `0`, portanto, no campo resultante há apenas um elemento do primeiro array.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normaliza o array para o array associativo. Substituindo as chaves numéricas por seus valores, o novo valor será `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Devolve e remove o valor de um item de uma matriz. Se ele não existir, ele lança uma exceção, ou retorna `$default`, se fornecido.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Testa se pelo menos um elemento da matriz passa no teste implementado pela callback fornecida com a assinatura `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Ele lança cada elemento da matriz para cordelar e o encerra com `$prefix` e `$suffix`.
 
diff --git a/utils/pt/datetime.texy b/utils/pt/datetime.texy
index 538e888c19..c02f412195 100644
--- a/utils/pt/datetime.texy
+++ b/utils/pt/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Prolonga o [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] com a capacidade de especificar um fuso horário como um fio.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create with custom timezone
diff --git a/utils/pt/filesystem.texy b/utils/pt/filesystem.texy
index 573e5b0859..5ef16b465e 100644
--- a/utils/pt/filesystem.texy
+++ b/utils/pt/filesystem.texy
@@ -2,9 +2,11 @@ Funções do sistema de arquivos
 ******************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] é uma classe estática, que contém funções úteis para trabalhar com um sistema de arquivos. Uma vantagem sobre as funções PHP nativas é que elas lançam exceções em caso de erros.
+[api:Nette\Utils\FileSystem] é uma classe que contém funções úteis para trabalhar com um sistema de arquivos. Uma vantagem sobre as funções nativas do PHP é que elas lançam exceções em caso de erros.
 
 
+Se você precisar procurar arquivos no disco, use o [Finder |finder].
+
 Instalação:
 
 ```shell
@@ -174,3 +176,26 @@ Converte cortes em caracteres específicos da plataforma atual, ou seja, `\` no
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Abordagem estática versus não estática .[#toc-static-vs-non-static-approach]
+============================================================================
+
+Para substituir facilmente a classe `FileSystem` por outra classe, por exemplo, para fins de teste, use-a de forma não estática:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/pt/finder.texy b/utils/pt/finder.texy
index 94e1cd48b0..0c8a31d15d 100644
--- a/utils/pt/finder.texy
+++ b/utils/pt/finder.texy
@@ -61,6 +61,8 @@ Uma alternativa aos métodos estáticos é criar uma instância usando `new Find
 
 Você pode usar [wildcards |#wildcards] `*`, `**`, `?` and `[...]` na máscara. Você pode até mesmo especificar em diretórios, por exemplo `src/*.php` procurará por todos os arquivos PHP no diretório `src`.
 
+Os links simbólicos também são considerados diretórios ou arquivos.
+
 
 Onde pesquisar? .[#toc-where-to-search]
 ---------------------------------------
diff --git a/utils/pt/floats.texy b/utils/pt/floats.texy
index 7ef9b4f49b..f624d64724 100644
--- a/utils/pt/floats.texy
+++ b/utils/pt/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 Ao tentar comparar `NAN`, ele lança uma exceção `\LogicException`.
 
+.[tip]
+A classe `Floats` tolera diferenças menores que `1e-10`. Se você precisar trabalhar com mais precisão, use a biblioteca BCMath.
+
 
 Comparação de flutuadores .[#toc-float-comparison]
 ==================================================
diff --git a/utils/pt/html-elements.texy b/utils/pt/html-elements.texy
index 670d28deba..434ba8507e 100644
--- a/utils/pt/html-elements.texy
+++ b/utils/pt/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Outra maneira de criar e inserir um novo nódulo `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/pt/images.texy b/utils/pt/images.texy
index fdf21d8eaa..35e3092eed 100644
--- a/utils/pt/images.texy
+++ b/utils/pt/images.texy
@@ -17,6 +17,8 @@ Os exemplos a seguir assumem que a seguinte classe está definida:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Opcionalmente, você pode especificar uma cor de fundo (o padrão é preto):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Ou carregamos a imagem de um arquivo:
@@ -41,17 +43,6 @@ Ou carregamos a imagem de um arquivo:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Os formatos suportados são JPEG, PNG, GIF, WebP, AVIF e BMP, mas sua versão do PHP também deve apoiá-los (verifique a `phpinfo()`, seção GD). As animações não são suportadas.
-
-Necessidade de detectar o formato da imagem ao carregar? O formato de retorno do método no segundo parâmetro:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type é Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ou Image::BMP
-```
-
-Somente a detecção sem carregar a imagem é feita por `Image::detectTypeFromFile()`.
-
 
 Salvar a imagem .[#toc-save-the-image]
 ======================================
@@ -68,25 +59,45 @@ Podemos especificar a qualidade de compressão na faixa 0..100 para JPEG (padrã
 $image->save('resampled.jpg', 80); // JPEG, qualidade 80%
 ```
 
-Se o formato não for óbvio pela extensão do arquivo, ele pode ser especificado por uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`:
+Se o formato não for óbvio a partir da extensão do arquivo, ele poderá ser especificado por uma [constante |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 A imagem pode ser escrita em uma variável ao invés de em disco:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, qualidade 80%.
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, qualidade 80%.
 ```
 
 ou enviar diretamente para o navegador com o cabeçalho HTTP apropriado `Content-Type`:
 
 ```php
 // envia cabeçalho Content-Type: imagem/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formatos .[#toc-formats]
+========================
+
+Os formatos suportados são JPEG, PNG, GIF, WebP, AVIF e BMP. No entanto, eles também devem ser compatíveis com sua versão do PHP, o que pode ser verificado usando a função [isTypeSupported() |#isTypeSupported()]. Não há suporte para animações.
+
+Os formatos são representados pelas constantes `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, e `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Precisa detectar o formato de uma imagem ao ser carregada? O método o retorna no segundo parâmetro:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+A detecção real sem carregar a imagem é realizada por `Image::detectTypeFromFile()`.
+
 
 Redimensionamento de imagem .[#toc-image-resize]
 ================================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 O método `cropAuto()` é um encapsulamento de objeto da função `imagecropauto()`, veja [sua documentação |https://www.php.net/manual/en/function.imagecropauto] para mais informações.
 
 
+Cores .[#toc-colors]
+====================
+
+O método `ImageColor::rgb()` permite que você defina uma cor usando valores de vermelho, verde e azul (RGB). Opcionalmente, você também pode especificar um valor de transparência que varia de 0 (totalmente transparente) a 1 (totalmente opaco), assim como no CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+O método `ImageColor::hex()` permite que você defina uma cor usando o formato hexadecimal, semelhante ao CSS. Ele é compatível com os formatos `#rgb`, `#rrggbb`, `#rgba` e `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+As cores podem ser usadas em outros métodos, como `ellipse()`, `fill()`, etc.
+
+
 Desenho e Edição .[#toc-drawing-and-editing]
 ============================================
 
-Você pode desenhar, você pode escrever, você pode usar todas as funções PHP para trabalhar com imagens, tais como [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], mas usando o estilo de objeto:
+Você pode desenhar, escrever e usar todas as funções do PHP para manipulação de imagens, consulte [Visão geral dos métodos |#Overview of methods], mas em um invólucro orientado a objetos:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Veja [Visão geral dos métodos |#Overview of Methods].
+Como as funções PHP para desenhar retângulos são impraticáveis devido à especificação de coordenadas, a classe `Image` oferece seus substitutos na forma das funções [rectangleWH() |#rectangleWH()] e [filledRectangleWH() |#filledRectangleWH()].
 
 
 Fundir várias imagens .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Você pode facilmente colocar outra imagem dentro da imagem:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // as coordenadas também podem ser definidas em porcentagem
 $blank->place($logo, '80%', '80%'); // perto do canto inferior direito
@@ -219,53 +250,68 @@ Visão geral dos métodos .[#toc-overview-of-methods]
 ===================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Cria uma nova imagem colorida verdadeira das dimensões dadas. A cor padrão é o preto.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Lê uma imagem de um arquivo e retorna seu tipo em `$detectedFormat`. Os tipos suportados são `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`.
+Lê uma imagem de um arquivo e retorna seu [tipo |#Formats] em `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Lê uma imagem de um fio e retorna seu tipo em `$detectedFormat`. Os tipos suportados são `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::AVIF`, `Image::WEBP`, , e `Image::BMP`.
+Lê uma imagem de uma string e retorna seu [tipo |#Formats] em `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Cria uma cor que pode ser usada em outros métodos, tais como `ellipse()`, `fill()` e assim por diante.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Esse recurso foi substituído pela classe `ImageColor`, consulte [cores |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Devolve a extensão do arquivo para a constante `Image::XXX` dada.
+Retorna a extensão do arquivo para o [tipo |#Formats] fornecido.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Devolve o tipo de mímica para a constante `Image::XXX` dada.
+Retorna o tipo de mime para o [tipo |#Formats] fornecido.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Retorna o tipo de imagem como uma constante `Image::XXX` de acordo com a extensão do arquivo.
+Retorna o [tipo |#Formats] de imagem de acordo com a extensão do arquivo.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Retorna o tipo de arquivo de imagem como constante `Image::XXX` e nos parâmetros `$width` e `$height` também suas dimensões.
+Retorna o [tipo |#Formats] de arquivo de imagem e, nos parâmetros `$width` e `$height`, também suas dimensões.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Retorna o tipo de imagem de corda como constante `Image::XXX` e nos parâmetros `$width` e `$height` também suas dimensões.
+Retorna o [tipo |#Formats] de imagem da string e, nos parâmetros `$width` e `$height`, também suas dimensões.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Determina se o [tipo |#Formats] de imagem fornecido é compatível.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Retorna uma matriz de tipos de imagens compatíveis (constantes `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Calcula as dimensões do retângulo que envolve o texto em uma fonte e tamanho especificados. Retorna uma matriz associativa contendo as chaves `left`, `top`, `width`, `height`. A margem esquerda pode ser negativa se o texto começar com uma saliência à esquerda.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Retorna uma imagem contendo a imagem src transformada afim, usando uma área de recorte opcional. ([mais |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Retorna a concatenação de duas matrizes de transformação afins, que é útil se múltiplas transformações devem ser aplicadas à mesma imagem de uma só vez. ([mais |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Devolve uma matriz de transformação afim. ([mais |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Ativar os métodos de desenho rápido antialiased para linhas e polígonos com f
 O uso de primitivos antialiased com cor de fundo transparente pode terminar com alguns resultados inesperados. O método de mistura utiliza a cor de fundo como qualquer outra cor. A falta de suporte de componentes alfa não permite um método antialiasing baseado em alfa. ([mais |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Desenha um arco de círculo centrado nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Traça o primeiro caractere de `$char` na imagem com sua parte superior esquerda em `$x`,`$y` (parte superior esquerda é 0, 0) com a cor `$color`. ([mais |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Traça o caracter `$char` verticalmente na coordenada especificada na imagem dada. ([mais |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Retorna um identificador de cor que representa a cor composta dos componentes RGB. Ela deve ser chamada para criar cada cor a ser usada na imagem. ([mais |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Retorna o número de cores em uma paleta de imagens ([mais |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Obtém ou define a cor transparente na imagem. ([mais |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Cortar uma imagem para a área retangular dada. As dimensões podem ser passadas como números inteiros em pixels ou cadeias em porcentagem (ou seja, `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Automaticamente cultiva uma imagem de acordo com o dado `$mode`. ([mais |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Desenha uma elipse centrada nas coordenadas especificadas. ([mais |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Realiza um enchimento de inundação a partir da coordenada dada (no canto superior esquerdo é 0, 0) com o dado `$color` na imagem. ([mais |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Desenha um arco parcial centrado na coordenada especificada na imagem. ([mais |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Desenha uma elipse centrada na coordenada especificada na imagem. ([mais |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Cria um polígono cheio na imagem de $. ([mais |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Cria um retângulo preenchido com `$color` na imagem começando no ponto 1 e terminando no ponto 2. 0, 0 é o canto superior esquerdo da imagem. ([mais |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Cria um retângulo preenchido com `$color` na imagem, começando em `$x1` e `$y1` e terminando em `$x2` e `$y2`. O ponto 0, 0 é o canto superior esquerdo da imagem. ([Mais |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Cria um retângulo preenchido com `$color` na imagem a partir dos pontos `$left` e `$top` com largura `$width` e altura `$height`. O ponto 0, 0 é o canto superior esquerdo da imagem.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Realiza um enchimento de inundação cuja cor da borda é definida por `$border`. O ponto de partida para o preenchimento é `$x`, `$y` (canto superior esquerdo é 0, 0) e a região é preenchida com a cor `$color`. ([mais |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Vira a imagem usando o dado `$mode`. ([mais |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Escrever texto na imagem usando fontes usando FreeType 2. ([mais |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Escreva o texto na figura. ([mais |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Retorna a largura da imagem.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Liga ou desliga o fio entrelaçado. Se a parte entrelaçada for definida e a imagem for usada como uma imagem JPEG, a imagem é criada como um JPEG progressivo. ([mais |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Coloque a bandeira de mistura alfa para usar efeitos de camadas. ([mais |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Traça uma linha entre os dois pontos dados. ([mais |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Desenha um polígono aberto sobre a imagem. Ao contrário de `polygon()`, nenhuma linha é traçada entre o último e o primeiro ponto. ([mais |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Copia `$image` para a imagem nas coordenadas `$left` e `$top`. As coordenadas podem ser passadas como números inteiros em pixels ou cadeias em porcentagem (ou seja, `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Cria um polígono na imagem. ([mais |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Cria um retângulo começando nas coordenadas especificadas. ([mais |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Cria um retângulo nas coordenadas fornecidas.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Escala uma imagem, veja [mais informações |#Image Resize]. As dimensões podem ser passadas como números inteiros em pixels ou cadeias em porcentagem (ou seja, `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Permite definir e obter a resolução de uma imagem em DPI (dots per inch). Se nenhum dos parâmetros opcionais for dado, a resolução atual é devolvida como matriz indexada. Se apenas `$resX` for dado, a resolução horizontal e vertical é definida para este valor. Se ambos os parâmetros opcionais são dados, a resolução horizontal e vertical são definidas para estes valores, respectivamente.
 
 A resolução só é usada como meta informação quando as imagens são lidas e escritas em formatos que suportam este tipo de informação (curently PNG e JPEG). Não afeta nenhuma operação de desenho. A resolução padrão para novas imagens é 96 DPI. ([mais |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Gira a imagem usando o dado `$angle` em graus. O centro de rotação é o centro
 Exige *extensão de GD fundida*, por isso não é certo que funcione em todos os lugares.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Salva uma imagem em um arquivo.
 
-A qualidade da compressão está na faixa 0..100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0..9 para PNG (padrão 9). Se o tipo não for óbvio a partir da extensão do arquivo, você pode especificá-lo usando uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`.
+A qualidade da compactação está no intervalo de 0 a 100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0 a 9 para PNG (padrão 9). Se o tipo não for óbvio a partir da extensão do arquivo, você poderá especificá-lo usando uma das constantes do site `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Escala uma imagem usando o algoritmo de interpolação dado. ([mais |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Produz uma imagem para o navegador.
 
-A qualidade da compressão está na faixa 0..100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0..9 para PNG (padrão 9). O tipo é uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::AVIF`, `Image::WEBP`, e `Image::BMP`.
+A qualidade da compactação está no intervalo de 0 a 100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0 a 9 para PNG (padrão 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Define o método de interpolação que afeta os métodos `rotate()` e `affine()`. ([mais |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Traça um pixel na coordenada especificada. ([mais |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Aguça um pouco a imagem.
 Requer uma extensão GD *Bundled GD, por isso não é certo que funcione em todos os lugares.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Traça um fio nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Traça um cordel verticalmente nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Produz uma imagem a fio.
 
-A qualidade da compressão está na faixa 0..100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0..9 para PNG (padrão 9). O tipo é uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::AVIF`, `Image::WEBP`, e `Image::BMP`.
+A qualidade da compactação está no intervalo de 0 a 100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0 a 9 para PNG (padrão 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Converte uma imagem truecolor em uma imagem de paleta. ([mais |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Escreve o texto dado na imagem usando fontes TrueType. ([mais |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Grava o texto fornecido na imagem. ([mais |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/pt/iterables.texy b/utils/pt/iterables.texy
new file mode 100644
index 0000000000..ac88f76b08
--- /dev/null
+++ b/utils/pt/iterables.texy
@@ -0,0 +1,170 @@
+Funções de iterador
+*******************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] é uma classe estática com funções para trabalhar com iteradores. Sua contraparte para matrizes é [Nette\Utils\Arrays |arrays].
+
+
+Instalação:
+
+```shell
+composer require nette/utils
+```
+
+Todos os exemplos pressupõem que o alias a seguir foi criado:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Procura por um determinado valor em um iterador. Usa comparação rigorosa (`===`) para verificar se há correspondência. Retorna `true` se o valor for encontrado, caso contrário, `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Esse método é útil quando você precisa determinar rapidamente se um valor específico está presente em um iterador sem iterar manualmente por todos os elementos.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Procura por uma determinada chave em um iterador. Usa comparação rigorosa (`===`) para verificar se há correspondência. Retorna `true` se a chave for encontrada, caso contrário, `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Verifica se todos os elementos do iterador satisfazem a condição definida em `$predicate`. A função `$predicate` tem a assinatura `function ($value, $key, iterable $iterable): bool` e deve retornar `true` para cada elemento para que o método `every()` retorne `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Esse método é útil para verificar se todos os elementos de uma coleção atendem a uma determinada condição, como, por exemplo, se todos os números estão abaixo de um valor específico.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Cria um novo iterador que contém somente os elementos do iterador original que satisfazem a condição definida em `$predicate`. A função `$predicate` tem a assinatura `function ($value, $key, iterable $iterable): bool` e deve retornar `true` para os elementos que devem ser mantidos.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+O método usa um gerador, o que significa que a filtragem ocorre de forma incremental durante a iteração. Isso é eficiente em termos de memória e permite lidar com coleções muito grandes. Se você não iterar por todos os elementos do iterador resultante, economizará esforço computacional, pois nem todos os elementos do iterador original serão processados.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Retorna o primeiro elemento do iterador. Se `$predicate` for fornecido, ele retornará o primeiro elemento que satisfaz a condição fornecida. A função `$predicate` tem a assinatura `function ($value, $key, iterable $iterable): bool`. Se nenhum elemento correspondente for encontrado, a função `$else` (se fornecida) será chamada e seu resultado será retornado. Se `$else` não for fornecido, `null` será retornado.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Esse método é útil quando você precisa recuperar rapidamente o primeiro elemento de uma coleção ou o primeiro elemento que atende a uma determinada condição sem iterar manualmente por toda a coleção.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Retorna a chave do primeiro elemento do iterador. Se `$predicate` for fornecido, ele retornará a chave do primeiro elemento que satisfaz a condição fornecida. A função `$predicate` tem a assinatura `function ($value, $key, iterable $iterable): bool`. Se nenhum elemento correspondente for encontrado, a função `$else` (se fornecida) será chamada e seu resultado será retornado. Se `$else` não for fornecido, `null` será retornado.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Cria um novo iterador aplicando a função `$transformer` a cada elemento do iterador original. A função `$transformer` tem a assinatura `function ($value, $key, iterable $iterable): mixed` e seu valor de retorno é usado como o novo valor do elemento.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+O método usa um gerador, o que significa que a transformação ocorre de forma incremental durante a iteração. Isso é eficiente em termos de memória e permite lidar com coleções muito grandes. Se você não iterar por todos os elementos do iterador resultante, economizará esforço computacional, pois nem todos os elementos do iterador original serão processados.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Cria um novo iterador transformando os valores e as chaves do iterador original. A função `$transformer` tem a assinatura `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Se `$transformer` retornar `null`, o elemento será ignorado. Para elementos retidos, o primeiro elemento da matriz retornada é usado como a nova chave e o segundo elemento como o novo valor.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Assim como o `map()`, esse método usa um gerador para processamento incremental e eficiência de memória. Isso permite trabalhar com grandes coleções e economizar esforço computacional ao processar apenas parte do resultado.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Cria um invólucro em torno de um iterador que armazena em cache suas chaves e valores durante a iteração. Isso permite a iteração repetida dos dados sem a necessidade de reprocessar a fonte de dados original.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Esse método é útil em situações em que você precisa iterar sobre o mesmo conjunto de dados várias vezes, mas o iterador original não oferece suporte à iteração repetida ou a iteração repetida seria dispendiosa (por exemplo, ler dados de um banco de dados ou arquivo).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Verifica se pelo menos um elemento do iterador satisfaz a condição definida em `$predicate`. A função `$predicate` tem a assinatura `function ($value, $key, iterable $iterable): bool` e deve retornar `true` para pelo menos um elemento para que o método `some()` retorne `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Esse método é útil para verificar rapidamente se há pelo menos um elemento em uma coleção que atenda a uma determinada condição, como, por exemplo, se a coleção contém pelo menos um número par.
+
+Consulte [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Converte qualquer objeto iterável (matriz, Traversable) em um Iterator. Se a entrada já for um Iterator, ela será retornada inalterada.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Esse método é útil quando você precisa garantir que tem um Iterator, independentemente do tipo de dados de entrada. Isso pode ser útil ao criar funções que funcionam com diferentes tipos de dados iteráveis.
diff --git a/utils/pt/json.texy b/utils/pt/json.texy
index 58bbc765a3..2b4615d182 100644
--- a/utils/pt/json.texy
+++ b/utils/pt/json.texy
@@ -77,7 +77,7 @@ A configuração `$forceArray` força o retorno de matrizes em vez de objetos:
 
 ```php
 Json::decode('{"variable": true}'); // retorna um objeto do tipo stdClass
-Json::decode('{"variable": true}', forceArray: true); // retorna um array
+Json::decode('{"variable": true}', forceArrays: true); // retorna um array
 ```
 
 Ele lança uma exceção de erro em `Nette\Utils\JsonException`.
diff --git a/utils/pt/smartobject.texy b/utils/pt/smartobject.texy
index cc43032dd3..e3f7e5f255 100644
--- a/utils/pt/smartobject.texy
+++ b/utils/pt/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject e StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-O SmartObject adiciona suporte para *propriedade* às classes PHP. O StaticClass é usado para denotar classes estáticas.
+O SmartObject costumava corrigir o comportamento dos objetos de várias maneiras, mas o PHP atual já inclui a maioria desses aprimoramentos nativamente. No entanto, ele ainda adiciona suporte para *property*.
 
 
 Instalação:
@@ -65,31 +65,16 @@ echo $circle->visible; // chamadas isVisible()
 As propriedades são principalmente o "açúcar sintático"((açúcar sintático)), que se destina a tornar a vida do programador mais doce, simplificando o código. Se você não os quer, não precisa usá-los.
 
 
-Classes estáticas .[#toc-static-classes]
-========================================
+Um vislumbre da história .[#toc-a-glimpse-into-history]
+=======================================================
 
-As classes estáticas, ou seja, classes que não se destinam a ser instanciadas, podem ser marcadas com o traço `Nette\StaticClass`:
+O SmartObject costumava refinar o comportamento dos objetos de várias maneiras, mas o PHP atual já incorpora a maioria desses aprimoramentos de forma nativa. O texto a seguir é um olhar nostálgico para a história, lembrando-nos de como as coisas evoluíram.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Quando você tenta criar uma instância, a exceção `Error` é lançada, indicando que a classe é estática.
-
-
-Um olhar sobre a história .[#toc-a-look-into-the-history]
-=========================================================
-
-SmartObject usado para melhorar e corrigir o comportamento de classe de muitas maneiras, mas a evolução do PHP tornou redundante a maioria das características originais. Portanto, o seguinte é um olhar sobre a história de como as coisas evoluíram.
-
-Desde o início, o modelo de objeto PHP sofreu uma série de falhas graves e ineficiências. Esta foi a razão da criação da classe `Nette\Object` (em 2007), que tentou remediá-los e melhorar a experiência de uso do PHP. Era o suficiente para que outras classes herdassem dela, e ganhassem os benefícios que ela trazia. Quando o PHP 5.4 veio com suporte de características, a classe `Nette\Object` foi substituída por `Nette\SmartObject`. Assim, não era mais necessário herdar de um ancestral comum. Além disso, a característica podia ser usada em classes que já herdaram de outra classe. O fim final de `Nette\Object` veio com o lançamento do PHP 7.2, que proibiu as classes de serem nomeadas `Object`.
+Desde seu início, o modelo de objeto do PHP sofria de uma infinidade de falhas e deficiências graves. Isso levou à criação da classe `Nette\Object` (em 2007), cujo objetivo era corrigir esses problemas e aumentar o conforto do uso do PHP. Tudo o que era necessário era que outras classes herdassem essa classe e obtivessem os benefícios que ela oferecia. Quando o PHP 5.4 introduziu o suporte a características, a classe `Nette\Object` foi substituída pela característica `Nette\SmartObject`. Isso eliminou a necessidade de herdar de um ancestral comum. Além disso, a característica poderia ser usada em classes que já herdavam de outra classe. O fim definitivo de `Nette\Object` veio com o lançamento do PHP 7.2, que proibiu que as classes fossem nomeadas `Object`.
 
-Com o desenvolvimento do PHP em andamento, o modelo de objeto e as capacidades de linguagem foram melhorados. As funções individuais da classe `SmartObject` se tornaram redundantes. Desde o lançamento do PHP 8.2, a única característica que ainda não é suportada diretamente no PHP é a capacidade de usar as chamadas [propriedades |#Properties, Getters and Setters].
+À medida que o desenvolvimento do PHP continuava, seu modelo de objeto e os recursos da linguagem foram aprimorados. Várias funções da classe `SmartObject` tornaram-se redundantes. Desde o lançamento do PHP 8.2, resta apenas um recurso não suportado diretamente no PHP: a capacidade de usar as chamadas [propriedades |#Properties, getters, and setters].
 
-Que características `Nette\Object` e `Nette\Object` ofereceram uma vez? Aqui está uma visão geral. (Os exemplos utilizam a classe `Nette\Object`, mas a maioria das propriedades também se aplica ao traço `Nette\SmartObject` ).
+Quais recursos o `Nette\Object` e, por extensão, o `Nette\SmartObject` ofereceram? Aqui está uma visão geral. (Nos exemplos, a classe `Nette\Object` é usada, mas a maioria dos recursos também se aplica à característica `Nette\SmartObject` ).
 
 
 Erros Inconsistentes .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-O PHP de hoje pode não ter nenhuma forma de "você quis dizer?", mas [Tracy |tracy:] acrescenta este adendo aos erros. E ele pode até [corrigir |tracy:open-files-in-ide#toc-demos] tais erros por si só.
+Embora o PHP atual não tenha um recurso "você quis dizer?", essa frase pode ser adicionada aos erros pela [Tracy |tracy:]. Ele pode até mesmo [corrigir automaticamente esses erros |tracy:open-files-in-ide#toc-demos].
 
 
 Métodos de extensão .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // devolve 'John Doe
+$reflection->getAnnotation('author'); // devolve 'John Doe'
 ```
 
 A partir do PHP 8.0, é possível acessar meta-informação sob a forma de atributos:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/pt/staticclass.texy b/utils/pt/staticclass.texy
new file mode 100644
index 0000000000..75a43f1f65
--- /dev/null
+++ b/utils/pt/staticclass.texy
@@ -0,0 +1,21 @@
+Classes estáticas
+*****************
+
+.[perex]
+StaticClass é usado para indicar classes estáticas.
+
+
+Instalação:
+
+```shell
+composer require nette/utils
+```
+
+Classes estáticas, ou seja, classes que não se destinam a ser instanciadas, podem ser marcadas com a característica [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/pt/strings.texy b/utils/pt/strings.texy
index 0c771b5c15..151391aa12 100644
--- a/utils/pt/strings.texy
+++ b/utils/pt/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modifica a cadeia UTF-8 para a forma usada na URL, ou seja, remove os diacríticos e substitui todos os caracteres exceto letras do alfabeto inglês e números por um hífen.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Requer extensão PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Remove todos os espaços do lado esquerdo e direito (ou os caracteres passados como segundo argumento) de uma cadeia codificada UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Retorna uma parte da cadeia UTF-8 especificada pela posição inicial `$start` e comprimento `$length`. Se `$start` for negativo, a cadeia de caracteres retornada começará no `$start`'th character from the end of string'.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Use nativo `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Compara duas cordas UTF-8 ou suas partes, sem levar em conta o caso de caracteres. Se `$length` for nulo, cordas inteiras são comparadas, se for negativo, o número correspondente de caracteres do final das cordas é comparado, caso contrário, o número apropriado de caracteres do início é comparado.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Procura na cadeia todas as ocorrências que correspondem à expressão regular e retorna uma matriz de matrizes contendo a expressão encontrada e cada subexpressão.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Se `$lazy` for `true`, a função retornará um `Generator` em vez de uma matriz, o que proporciona benefícios significativos de desempenho ao trabalhar com cadeias de caracteres grandes. O gerador permite que as correspondências sejam encontradas de forma incremental, em vez de processar a cadeia inteira de uma só vez. Isso permite o manuseio eficiente de textos de entrada extremamente grandes. Além disso, você pode interromper o processamento a qualquer momento se encontrar a correspondência desejada, economizando tempo computacional.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/pt/validators.texy b/utils/pt/validators.texy
index c5f3592942..da9893c0d6 100644
--- a/utils/pt/validators.texy
+++ b/utils/pt/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Verifica que o elemento `$key` na matriz `$array` é de [tipos esperados |#expected types] separados por tubo. Caso contrário, ele lança a exceção [api:Nette\Utils\AssertionException]. A string `item '%' in array` na mensagem de exceção pode ser substituída pelo parâmetro `$label`.
 
diff --git a/utils/ro/@home.texy b/utils/ro/@home.texy
index a9e20302c0..841a61083f 100644
--- a/utils/ro/@home.texy
+++ b/utils/ro/@home.texy
@@ -13,13 +13,14 @@ Utilități
  [Ajutoare |helpers] | Helpers | Nette\Utils\Helpers
 | [Elemente HTML |HTML Elements] | Nette\Utils\Html
  [Imagini |Images] | Imagini | Nette\Utils\Image
+[Iterables |iterables] | Iterables | Nette\Utils\Iterables
  [JSON |JSON] | JSON | Nette\Utils\Json
-| [Model de obiect |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginator |paginator] | Nette\Utils\Paginator
  [PHP Reflection |reflection] | [PHP |reflection] Reflection | Nette\Utils\Reflection
  [PHP Types |type] | [PHP Types |type] | Nette\Utils\Type
 | [Șiruri aleatorii |random] | Nette\Utils\Random
 | [Șiruri de caractere |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
  [Validatori |validators] | Validators | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | versiune | compatibil cu PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/ro/@left-menu.texy b/utils/ro/@left-menu.texy
index 8c32b60f04..5218142956 100644
--- a/utils/ro/@left-menu.texy
+++ b/utils/ro/@left-menu.texy
@@ -8,13 +8,15 @@ Pachetul nette/utils
 - [Ajutători |helpers]
 - [Elemente HTML |HTML Elements]
 - [Imagini |Images]
+- [Iterabile |iterables]
 - [JSON |JSON]
 - [Paginator |paginator]
 - [Șiruri aleatorii |random]
-- [SmartObject |SmartObject]
 - [Reflecție PHP |reflection]
 - [Șiruri de caractere |Strings]
 - [Flote |Floats]
+- [SmartObject]
+- [StaticClass]
 - [Tipuri PHP |type]
 - [Validatori |validators]
 
diff --git a/utils/ro/arrays.texy b/utils/ro/arrays.texy
index 7c76a41abd..be5539d24e 100644
--- a/utils/ro/arrays.texy
+++ b/utils/ro/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Array-uri .[#toc-arrays]
 ========================
 
-[api:Nette\Utils\Arrays] este o clasă statică, care conține o serie de funcții practice de matrice.
+[api:Nette\Utils\Arrays] este o clasă statică, care conține o serie de funcții practice de matrice. Echivalentul său pentru iteratori este [Nette\Utils\Iterables |iterables].
 
 Exemplele următoare presupun că este definit următorul alias de clasă:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Funcția transformă în mod flexibil `$array` într-o matrice asociativă sau obiecte în funcție de calea specificată `$path`. Calea poate fi un șir de caractere sau o matrice. Aceasta constă din numele cheilor din tabloul de intrare și operatori precum "[]", "->", "=" și "|". Se aruncă `Nette\InvalidArgumentException` în cazul în care calea nu este validă.
+
+```php
+// conversia într-un tablou asociativ utilizând o cheie simplă
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// atribuirea de valori de la o cheie la alta cu ajutorul operatorului =.
+$result = Arrays::associate($arr, 'name=age'); // sau ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// crearea unui obiect cu ajutorul operatorului ->
+$result = Arrays::associate($arr, '->name'); // sau ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// combinarea cheilor cu ajutorul operatorului |
+$result = Arrays::associate($arr, 'name|age'); // sau ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// adăugarea la un array folosind []
+$result = Arrays::associate($arr, 'name[]'); // sau ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Testează dacă toate elementele din matrice trec testul implementat de funcția furnizată, care are semnătura `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 A se vedea [some() |#some()].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Returnează o nouă matrice care conține toate perechile cheie-valoare care corespund cu `$predicate`. Callback-ul are semnătura `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Returnează primul element din tablou sau nul dacă tabloul este gol. Nu modifică pointerul intern, spre deosebire de `reset()`.
+Returnează primul element (care corespunde predicatului specificat, dacă este dat). Dacă nu există un astfel de element, se returnează rezultatul invocării `$else` sau null.
+ `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`.
+
+Nu modifică pointerul intern, spre deosebire de `reset()`. Parametrii `$predicate` și `$else` există începând cu versiunea 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+A se vedea [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Returnează cheia primului element (care corespunde predicatului specificat, dacă este dat) sau nulă dacă nu există un astfel de element. `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+A se vedea [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Returnează `$array[$key]` item. Dacă nu există, se aruncă `Nette\InvalidArgumentException`, cu excepția cazului în care se stabilește o valoare implicită ca al treilea argument.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Returnează ultimul element (care corespunde predicatului specificat, dacă este dat). Dacă nu există un astfel de element, se returnează rezultatul invocării `$else` sau null.
+ `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`.
+
+Nu modifică pointerul intern, spre deosebire de `end()`. Parametrii `$predicate` și `$else` există începând cu versiunea 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+A se vedea [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Returnează ultimul element din tablou sau zero dacă tabloul este gol. Spre deosebire de `end()`, nu modifică pointerul intern.
+Returnează cheia ultimului element (care corespunde predicatului specificat, dacă este dat) sau nulă dacă nu există un astfel de element. `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+A se vedea [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Solicită `$callback` pentru toate elementele din matrice și returnează matricea de valori de returnare. Callback-ul are semnătura `function ($value, $key, array $array): bool`.
+Solicită `$transformer` pentru toate elementele din matrice și returnează matricea de valori de returnare. Callback-ul are semnătura `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Creează un nou array prin transformarea valorilor și a cheilor array-ului original. Funcția `$transformer` are semnătura `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Dacă `$transformer` returnează `null`, elementul este ignorat. Pentru elementele păstrate, primul element al matricei returnate este utilizat ca nouă cheie, iar al doilea element ca nouă valoare.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Această metodă este utilă în situațiile în care trebuie să modificați structura unui array (atât cheile, cât și valorile simultan) sau să filtrați elementele în timpul transformării (returnând null pentru elementele nedorite).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Valorile din al doilea tablou sunt întotdeauna adăugate la primul. Dispariția valorii `10` din cel de-al doilea tablou poate părea puțin confuză. Trebuie remarcat faptul că această valoare, precum și valoarea `5` in the first array have the same numeric key `0`, astfel încât în câmpul rezultat există doar un element din prima matrice.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizează matricea în matrice asociativă. Înlocuiește cheile numerice cu valorile lor, noua valoare va fi `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Returnează și elimină valoarea unui element dintr-un tablou. Dacă acesta nu există, se aruncă o excepție sau se returnează `$default`, dacă este furnizat.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returnează null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Testează dacă cel puțin un element din matrice trece testul implementat de callback-ul furnizat cu semnătura `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // setează $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Transformă fiecare element al tabloului în șir de caractere și îl închide cu `$prefix` și `$suffix`.
 
diff --git a/utils/ro/datetime.texy b/utils/ro/datetime.texy
index 482a4b9c7a..881f4aee28 100644
--- a/utils/ro/datetime.texy
+++ b/utils/ro/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Extinde [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] cu posibilitatea de a specifica un fus orar sub forma unui șir de caractere.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // creați cu un fus orar personalizat
diff --git a/utils/ro/filesystem.texy b/utils/ro/filesystem.texy
index 08c0be3261..f57c3eaa54 100644
--- a/utils/ro/filesystem.texy
+++ b/utils/ro/filesystem.texy
@@ -2,9 +2,11 @@ Funcțiile sistemului de fișiere
 *******************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] este o clasă statică, care conține funcții utile pentru lucrul cu un sistem de fișiere. Un avantaj față de funcțiile native PHP este că acestea aruncă excepții în caz de erori.
+[api:Nette\Utils\FileSystem] este o clasă care conține funcții utile pentru lucrul cu un sistem de fișiere. Un avantaj față de funcțiile native PHP este că acestea aruncă excepții în caz de erori.
 
 
+Dacă trebuie să căutați fișiere pe disc, utilizați [Finder |finder].
+
 Instalare:
 
 ```shell
@@ -174,3 +176,26 @@ Convertește slash-urile în caractere specifice platformei curente, de exemplu
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Abordare statică vs. non-statică .[#toc-static-vs-non-static-approach]
+======================================================================
+
+Pentru a înlocui cu ușurință clasa `FileSystem` cu o altă clasă, de exemplu în scopuri de testare, utilizați-o în mod non-static:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/ro/finder.texy b/utils/ro/finder.texy
index a2a2fafd0e..46799f331b 100644
--- a/utils/ro/finder.texy
+++ b/utils/ro/finder.texy
@@ -61,6 +61,8 @@ O alternativă la metodele statice este de a crea o instanță folosind `new Fin
 
 Puteți utiliza [caractere wildcards |#wildcards] `*`, `**`, `?` and `[...]` în mască. Puteți specifica chiar și în directoare, de exemplu `src/*.php` va căuta toate fișierele PHP din directorul `src`.
 
+Legăturile simbolice sunt considerate, de asemenea, directoare sau fișiere.
+
 
 Unde să căutați? .[#toc-where-to-search]
 ----------------------------------------
diff --git a/utils/ro/floats.texy b/utils/ro/floats.texy
index 373fe66b1c..21422ca9ab 100644
--- a/utils/ro/floats.texy
+++ b/utils/ro/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same': 'not same'; // același
 
 Când se încearcă să se compare `NAN`, se aruncă o excepție `\LogicException`.
 
+.[tip]
+Clasa `Floats` tolerează diferențe mai mici de `1e-10`. Dacă aveți nevoie să lucrați cu o precizie mai mare, utilizați în schimb biblioteca BCMath.
+
 
 Compararea flotorilor .[#toc-float-comparison]
 ==============================================
diff --git a/utils/ro/html-elements.texy b/utils/ro/html-elements.texy
index fbad55d212..043d1c4390 100644
--- a/utils/ro/html-elements.texy
+++ b/utils/ro/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 O altă modalitate de a crea și insera un nou nod `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/ro/images.texy b/utils/ro/images.texy
index 996e346bc6..ff266e8989 100644
--- a/utils/ro/images.texy
+++ b/utils/ro/images.texy
@@ -17,6 +17,8 @@ Următoarele exemple presupun că este definit următorul alias de clasă:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Opțional, puteți specifica o culoare de fundal (culoarea implicită este negru):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Sau încărcăm imaginea dintr-un fișier:
@@ -41,17 +43,6 @@ Sau încărcăm imaginea dintr-un fișier:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Formatele acceptate sunt JPEG, PNG, GIF, WebP, AVIF și BMP, dar versiunea dvs. de PHP trebuie să le accepte și ea (consultați `phpinfo()`, secțiunea GD). Animațiile nu sunt acceptate.
-
-Trebuie să detectați formatul imaginii la încărcare? Metoda returnează formatul în cel de-al doilea parametru:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type este Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF sau Image::BMP
-```
-
-Doar detecția fără încărcarea imaginii este realizată de `Image::detectTypeFromFile()`.
-
 
 Salvați imaginea .[#toc-save-the-image]
 =======================================
@@ -68,25 +59,45 @@ Putem specifica calitatea compresiei în intervalul 0..100 pentru JPEG (implicit
 $image->save('resampled.jpg', 80); // JPEG, calitate 80%
 ```
 
-În cazul în care formatul nu este evident din extensia fișierului, acesta poate fi specificat prin una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, și `Image::BMP`:
+În cazul în care formatul nu este evident din extensia fișierului, acesta poate fi specificat prin [constantă |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Imaginea poate fi scrisă într-o variabilă în loc de pe disc:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, calitate 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, calitate 80%
 ```
 
 sau trimiteți direct la browser cu antetul HTTP corespunzător `Content-Type`:
 
 ```php
 // trimite antet Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formate .[#toc-formats]
+=======================
+
+Formatele acceptate sunt JPEG, PNG, GIF, WebP, AVIF și BMP. Cu toate acestea, ele trebuie să fie acceptate și de versiunea dumneavoastră de PHP, ceea ce poate fi verificat cu ajutorul funcției [isTypeSupported() |#isTypeSupported()]. Animațiile nu sunt acceptate.
+
+Formatele sunt reprezentate de constantele `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, și `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Aveți nevoie să detectați formatul unei imagini la încărcare? Metoda îl returnează în cel de-al doilea parametru:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Detectarea efectivă fără a încărca imaginea este realizată de `Image::detectTypeFromFile()`.
+
 
 Redimensionarea imaginii .[#toc-image-resize]
 =============================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Metoda `cropAuto()` este o încapsulare în obiect a funcției `imagecropauto()`, a se vedea [documentația acesteia |https://www.php.net/manual/en/function.imagecropauto] pentru mai multe informații.
 
 
+Culori .[#toc-colors]
+=====================
+
+Metoda `ImageColor::rgb()` vă permite să definiți o culoare folosind valorile roșu, verde și albastru (RGB). Opțional, puteți specifica, de asemenea, o valoare de transparență de la 0 (complet transparent) la 1 (complet opac), la fel ca în CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Metoda `ImageColor::hex()` vă permite să definiți o culoare utilizând formatul hexazecimal, similar cu CSS. Aceasta acceptă formatele `#rgb`, `#rrggbb`, `#rgba` și `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Culorile pot fi utilizate în alte metode, cum ar fi `ellipse()`, `fill()`, etc.
+
+
 Desen și editare .[#toc-drawing-and-editing]
 ============================================
 
-Puteți desena, puteți scrie, puteți utiliza toate funcțiile PHP pentru a lucra cu imagini, cum ar fi [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], dar folosind stilul obiect:
+Puteți desena, puteți scrie, puteți utiliza toate funcțiile PHP pentru manipularea imaginilor, vedeți [Prezentare generală a metodelor |#Overview of methods], dar într-o învelitoare orientată pe obiecte:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-A se vedea [Prezentare generală a metodelor |#Overview of Methods].
+Deoarece funcțiile PHP pentru desenarea [dreptunghiurilor |#filledRectangleWH()] sunt nepractice din cauza specificării coordonatelor, clasa `Image` oferă înlocuitori sub forma funcțiilor [rectangleWH() |#rectangleWH()] și [filledRectangleWH() |#filledRectangleWH()].
 
 
 Îmbinarea mai multor imagini .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Puteți plasa cu ușurință o altă imagine în imagine:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // coordonatele pot fi stabilite și în procente
 $blank->place($logo, '80%', '80%'); // lângă colțul din dreapta jos
@@ -219,53 +250,68 @@ Prezentare generală a metodelor .[#toc-overview-of-methods]
 ===========================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Creează o nouă imagine în culori reale cu dimensiunile date. Culoarea implicită este negru.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Citește o imagine dintr-un fișier și returnează tipul acesteia în `$detectedFormat`. Tipurile acceptate sunt `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` și `Image::BMP`.
+Citește o imagine dintr-un fișier și returnează [tipul |#Formats] acesteia în `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Citește o imagine dintr-un șir de caractere și returnează tipul acesteia în `$detectedFormat`. Tipurile acceptate sunt `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, și `Image::BMP`.
+Citește o imagine dintr-un șir de caractere și returnează [tipul |#Formats] acesteia în `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Creează o culoare care poate fi utilizată în alte metode, cum ar fi `ellipse()`, `fill()`, etc.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Această caracteristică a fost înlocuită de clasa `ImageColor`, a se vedea [culori |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Returnează extensia de fișier pentru constanta `Image::XXX` dată.
+Returnează extensia de fișier pentru [tipul |#Formats] dat.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Returnează tipul mime pentru constanta `Image::XXX` dată.
+Returnează tipul mime pentru [tipul |#Formats] dat.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Returnează tipul de imagine ca o constantă `Image::XXX` în funcție de extensia fișierului.
+Returnează [tipul de |#Formats] imagine în funcție de extensia fișierului.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Returnează tipul de fișier de imagine ca și constantă `Image::XXX`, iar în parametrii `$width` și `$height` și dimensiunile sale.
+Returnează [tipul |#Formats] de fișier imagine și, în parametrii `$width` și `$height`, și dimensiunile acestuia.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Returnează tipul de imagine din șirul de caractere ca și constanta `Image::XXX`, iar în parametrii `$width` și `$height` și dimensiunile acesteia.
+Returnează [tipul |#Formats] de imagine din șirul de caractere, iar în parametrii `$width` și `$height` și dimensiunile acesteia.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Determină dacă [tipul de |#Formats] imagine dat este acceptat.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Returnează o matrice de tipuri de imagini acceptate (constante `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Calculează dimensiunile dreptunghiului care înconjoară textul cu un font și o dimensiune specificate. Se returnează un tablou asociativ care conține cheile `left`, `top`, `width`, `height`. Marja stângă poate fi negativă dacă textul începe cu o depășire la stânga.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Returnează o imagine care conține imaginea sursă transformată afine, folosind o zonă de tăiere opțională. ([mai mult |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Returnează concatenarea a două matrici de transformare afină, ceea ce este util în cazul în care mai multe transformări trebuie aplicate aceleiași imagini dintr-o singură dată. ([mai mult |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Returnează o matrice de transformare afină. ([mai mult |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Activați metodele de desenare rapidă antialiasată pentru linii și poligoane
 Utilizarea primitivelor antialiasate cu o culoare de fundal transparentă poate avea rezultate neașteptate. Metoda de amestecare utilizează culoarea de fundal ca orice altă culoare. Lipsa suportului pentru componenta alfa nu permite o metodă de antialiasing bazată pe alfa. ([mai mult |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Desenează un arc de cerc centrat pe coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Desenează primul caracter din `$char` în imagine cu partea superioară stângă la `$x`,`$y` (partea superioară stângă este 0, 0) cu culoarea `$color`. ([mai mult |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Desenează caracterul `$char` pe verticală la coordonatele specificate pe imaginea dată. ([mai mult |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Returnează un identificator de culoare care reprezintă culoarea compusă din componentele RGB date. Acesta trebuie apelat pentru a crea fiecare culoare care urmează să fie utilizată în imagine. ([mai mult |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Returnează numărul de culori dintr-o paletă de imagini ([mai multe |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Obține sau stabilește culoarea transparentă a imaginii. ([mai mult |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Recuperează o imagine în zona dreptunghiulară dată. Dimensiunile pot fi transmise ca numere întregi în pixeli sau ca șiruri de caractere în procente (de exemplu, `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Recuperează automat o imagine în funcție de datele furnizate `$mode`. ([mai mult |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Desenează o elipsă centrată la coordonatele specificate. ([mai mult |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Efectuează o umplere de inundație începând de la coordonata dată (stânga sus este 0, 0) cu `$color` în imagine. ([mai mult |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Desenează un arc parțial centrat pe coordonata specificată în imagine. ([mai mult |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Desenează o elipsă centrată la coordonatele specificate în imagine. ([mai mult |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Creează un poligon umplut în imaginea $image. ([mai mult |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Creează un dreptunghi umplut cu `$color` în imagine începând cu punctul 1 și terminând cu punctul 2. 0, 0 este colțul din stânga sus al imaginii. ([mai mult |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Creează un dreptunghi umplut cu `$color` în imagine, începând cu `$x1` & `$y1` și terminând cu `$x2` & `$y2`. Punctul 0, 0 este colțul din stânga sus al imaginii. ([mai mult |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Creează un dreptunghi umplut cu `$color` în imagine pornind de la punctul `$left` & `$top` cu lățimea `$width` și înălțimea `$height`. Punctul 0, 0 este colțul din stânga sus al imaginii.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Efectuează o umplere de inundație a cărei culoare a marginii este definită de `$border`. Punctul de plecare pentru umplere este `$x`, `$y` (stânga sus este 0, 0) și regiunea este umplută cu culoarea `$color`. ([mai mult |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Întoarce imaginea folosind datele `$mode`. ([mai mult |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Scrieți text pe imagine folosind fonturi cu FreeType 2. ([mai mult |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Scrieți textul din imagine. ([mai mult |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Returnează lățimea imaginii.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Activează sau dezactivează bitul de întrepătrundere. Dacă bitul de întrepătrundere este setat și imaginea este utilizată ca imagine JPEG, imaginea este creată ca o imagine JPEG progresivă. ([mai mult |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Setați indicatorul de amestecare alfa pentru a utiliza efectele de stratificare. ([mai mult |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Trasează o linie între cele două puncte date. ([mai mult |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Desenează un poligon deschis pe imagine. Spre deosebire de `polygon()`, nu se trasează nicio linie între ultimul și primul punct. ([mai mult |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Copiază `$image` în imagine la coordonatele `$left` și `$top`. Coordonatele pot fi transmise ca numere întregi în pixeli sau ca șiruri de caractere în procente (de exemplu, `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Creează un poligon în imagine. ([mai mult |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Creează un dreptunghi care începe la coordonatele specificate. ([mai mult |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Creează un dreptunghi la coordonatele date.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Scală o imagine, vezi [mai multe informații |#Image Resize]. Dimensiunile pot fi transmise ca numere întregi în pixeli sau ca șiruri de caractere în procente (de exemplu, `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Permite setarea și obținerea rezoluției unei imagini în DPI (dots per inch). Dacă nu se furnizează niciunul dintre parametrii opționali, rezoluția curentă este returnată sub formă de matrice indexată. Dacă se indică doar `$resX`, rezoluția orizontală și verticală este setată la această valoare. În cazul în care sunt furnizați ambii parametri opționali, rezoluția orizontală și verticală sunt stabilite la aceste valori.
 
 Rezoluția este utilizată ca meta-informație doar atunci când imaginile sunt citite și scrise în formate care acceptă acest tip de informații (în prezent PNG și JPEG). Aceasta nu afectează nicio operațiune de desenare. Rezoluția implicită pentru imaginile noi este de 96 DPI. ([mai mult |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Rotește imaginea folosind `$angle` în grade. Centrul de rotație este centrul
 Necesită *Extensie GD la pachet*, deci nu este sigur că va funcționa peste tot.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Salvează o imagine într-un fișier.
 
-Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). În cazul în care tipul nu este evident din extensia fișierului, îl puteți specifica folosind una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, și `Image::BMP`.
+Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). În cazul în care tipul nu este evident din extensia fișierului, îl puteți specifica folosind una dintre constantele `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Redimensionează o imagine folosind algoritmul de interpolare dat. ([mai mult |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Trimite o imagine în browser.
 
-Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). Tipul este una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` și `Image::BMP`.
+Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Stabilește metoda de interpolare care afectează metodele `rotate()` și `affine()`. ([mai mult |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Desenează un pixel la coordonatele specificate. ([mai mult |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Acutizează puțin imaginea.
 Necesită *Extensie GD la pachet*, deci nu este sigur că va funcționa peste tot.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Desenează un șir de caractere la coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Desenează un șir pe verticală la coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Produce o imagine în șir de caractere.
 
-Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). Tipul este una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` și `Image::BMP`.
+Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Convertește o imagine truecolor într-o imagine paletă. ([mai mult |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Scrie textul dat în imagine folosind fonturi TrueType. ([mai mult |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Scrie textul dat în imagine. ([mai mult |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/ro/iterables.texy b/utils/ro/iterables.texy
new file mode 100644
index 0000000000..1b23305ee5
--- /dev/null
+++ b/utils/ro/iterables.texy
@@ -0,0 +1,170 @@
+Funcții Iterator
+****************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] este o clasă statică cu funcții pentru lucrul cu iteratori. Omologul său pentru array-uri este [Nette\Utils\Arrays |arrays].
+
+
+Instalare:
+
+```shell
+composer require nette/utils
+```
+
+Toate exemplele presupun că este creat următorul alias:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Caută o valoare dată într-un iterator. Utilizează comparația strictă (`===`) pentru a verifica dacă există o potrivire. Returnează `true` dacă valoarea este găsită, altfel `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Această metodă este utilă atunci când trebuie să determinați rapid dacă o anumită valoare este prezentă într-un iterator fără a itera manual prin toate elementele.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Caută o cheie dată într-un iterator. Utilizează comparația strictă (`===`) pentru a verifica dacă există o potrivire. Returnează `true` dacă cheia este găsită, altfel `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Verifică dacă toate elementele iteratorului îndeplinesc condiția definită în `$predicate`. Funcția `$predicate` are semnătura `function ($value, $key, iterable $iterable): bool` și trebuie să returneze `true` pentru fiecare element pentru ca metoda `every()` să returneze `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Această metodă este utilă pentru a verifica dacă toate elementele unei colecții îndeplinesc o anumită condiție, cum ar fi dacă toate numerele sunt sub o anumită valoare.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Creează un nou iterator care conține numai elementele din iteratorul inițial care îndeplinesc condiția definită la `$predicate`. Funcția `$predicate` are semnătura `function ($value, $key, iterable $iterable): bool` și trebuie să returneze `true` pentru elementele care trebuie păstrate.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Metoda utilizează un generator, ceea ce înseamnă că filtrarea are loc în mod incremental în timpul iterației. Acest lucru este eficient din punct de vedere al memoriei și permite gestionarea colecțiilor foarte mari. Dacă nu iterați prin toate elementele iteratorului rezultat, economisiți efort de calcul, deoarece nu sunt procesate toate elementele iteratorului original.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Returnează primul element al iteratorului. Dacă se furnizează `$predicate`, aceasta returnează primul element care îndeplinește condiția dată. Funcția `$predicate` are semnătura `function ($value, $key, iterable $iterable): bool`. Dacă nu se găsește niciun element corespunzător, funcția `$else` (dacă este furnizată) este apelată și rezultatul său este returnat. Dacă `$else` nu este furnizat, se returnează `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Această metodă este utilă atunci când trebuie să recuperați rapid primul element al unei colecții sau primul element care îndeplinește o anumită condiție fără a parcurge manual întreaga colecție.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Returnează cheia primului element al iteratorului. Dacă se furnizează `$predicate`, aceasta returnează cheia primului element care îndeplinește condiția dată. Funcția `$predicate` are semnătura `function ($value, $key, iterable $iterable): bool`. Dacă nu se găsește niciun element corespunzător, funcția `$else` (dacă este furnizată) este apelată și rezultatul său este returnat. Dacă `$else` nu este furnizat, se returnează `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Creează un nou iterator prin aplicarea funcției `$transformer` la fiecare element al iteratorului original. Funcția `$transformer` are semnătura `function ($value, $key, iterable $iterable): mixed`, iar valoarea sa de retur este utilizată ca noua valoare a elementului.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Metoda utilizează un generator, ceea ce înseamnă că transformarea are loc în mod incremental în timpul iterației. Acest lucru este eficient din punct de vedere al memoriei și permite gestionarea colecțiilor foarte mari. Dacă nu iterați prin toate elementele iteratorului rezultat, economisiți efort de calcul, deoarece nu sunt prelucrate toate elementele iteratorului original.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Creează un nou iterator prin transformarea valorilor și a cheilor iteratorului inițial. Funcția `$transformer` are semnătura `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Dacă `$transformer` returnează `null`, elementul este ignorat. Pentru elementele reținute, primul element al matricei returnate este utilizat ca nouă cheie, iar al doilea element ca nouă valoare.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Ca și `map()`, această metodă utilizează un generator pentru procesare incrementală și eficiență în memorie. Aceasta permite lucrul cu colecții mari și economisirea efortului de calcul prin prelucrarea doar a unei părți din rezultat.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Creează un înveliș în jurul unui iterator care memorează cheile și valorile acestuia în timpul iterației. Acest lucru permite iterarea repetată a datelor fără a fi necesară prelucrarea din nou a sursei de date originale.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Această metodă este utilă în situațiile în care trebuie să iterați asupra aceluiași set de date de mai multe ori, dar iteratorul original nu acceptă iterația repetată sau iterația repetată ar fi costisitoare (de exemplu, citirea datelor dintr-o bază de date sau dintr-un fișier).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Verifică dacă cel puțin un element al iteratorului îndeplinește condiția definită în `$predicate`. Funcția `$predicate` are semnătura `function ($value, $key, iterable $iterable): bool` și trebuie să returneze `true` pentru cel puțin un element pentru ca metoda `some()` să returneze `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Această metodă este utilă pentru a verifica rapid dacă există cel puțin un element într-o colecție care îndeplinește o anumită condiție, cum ar fi dacă colecția conține cel puțin un număr par.
+
+Consultați [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Convertește orice obiect iterabil (array, Traversable) într-un Iterator. Dacă intrarea este deja un Iterator, acesta este returnat neschimbat.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Această metodă este utilă atunci când trebuie să vă asigurați că aveți un Iterator, indiferent de tipul de date de intrare. Acest lucru poate fi util atunci când se creează funcții care lucrează cu diferite tipuri de date iterabile.
diff --git a/utils/ro/json.texy b/utils/ro/json.texy
index c9e39ef738..29689b2f95 100644
--- a/utils/ro/json.texy
+++ b/utils/ro/json.texy
@@ -77,7 +77,7 @@ Setarea `$forceArray` forțează returnarea de matrici în loc de obiecte:
 
 ```php
 Json::decode('{"variable": true}'); // returnează un obiect de tip stdClass
-Json::decode('{"variable": true}', forceArray: true); // returnează o matrice
+Json::decode('{"variable": true}', forceArrays: true); // returnează o matrice
 ```
 
 În caz de eroare, se aruncă o excepție `Nette\Utils\JsonException`.
diff --git a/utils/ro/smartobject.texy b/utils/ro/smartobject.texy
index d487e98cfd..3d1ed9e89f 100644
--- a/utils/ro/smartobject.texy
+++ b/utils/ro/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject și StaticClass
-**************************
+SmartObject
+***********
 
 .[perex]
-SmartObject adaugă suport pentru *proprietăți* la clasele PHP. StaticClass este utilizat pentru a desemna clasele statice.
+SmartObject obișnuia să corecteze comportamentul obiectelor în mai multe moduri, dar PHP-ul de astăzi include deja majoritatea acestor îmbunătățiri în mod nativ. Cu toate acestea, se adaugă încă suport pentru *proprietate*.
 
 
 Instalare:
@@ -65,31 +65,16 @@ echo $circle->visible; // solicită isVisible()
 Proprietățile sunt în primul rând "zahăr sintactic"((zahăr sintactic)), care are rolul de a face viața programatorului mai ușoară prin simplificarea codului. Dacă nu le doriți, nu trebuie să le folosiți.
 
 
-Clase statice .[#toc-static-classes]
-====================================
+O privire în istorie .[#toc-a-glimpse-into-history]
+===================================================
 
-Clasele statice, adică clasele care nu sunt destinate a fi instanțiate, pot fi marcate cu trăsătura `Nette\StaticClass`:
+SmartObject obișnuia să rafineze comportamentul obiectelor în numeroase moduri, dar PHP-ul de astăzi încorporează deja majoritatea acestor îmbunătățiri în mod nativ. Următorul text este o privire nostalgică asupra istoriei, amintindu-ne cum au evoluat lucrurile.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Atunci când încercați să creați o instanță, se aruncă excepția `Error`, indicând că clasa este statică.
-
-
-O privire în istorie .[#toc-a-look-into-the-history]
-====================================================
-
-SmartObject obișnuia să îmbunătățească și să corecteze comportamentul clasei în multe feluri, dar evoluția PHP a făcut ca majoritatea caracteristicilor originale să fie redundante. Așadar, în cele ce urmează este o privire în istoria evoluției lucrurilor.
-
-Încă de la început, modelul de obiecte PHP a suferit de o serie de defecte și ineficiențe grave. Acesta a fost motivul pentru crearea clasei `Nette\Object` (în 2007), care a încercat să le remedieze și să îmbunătățească experiența de utilizare a PHP. A fost suficient pentru ca alte clase să moștenească din ea și să obțină beneficiile pe care le-a adus. Când PHP 5.4 a venit cu suport pentru trăsături, clasa `Nette\Object` a fost înlocuită cu `Nette\SmartObject`. Astfel, nu a mai fost necesară moștenirea de la un strămoș comun. În plus, trait putea fi utilizat în clase care moșteneau deja de la o altă clasă. Sfârșitul final al `Nette\Object` a venit odată cu lansarea PHP 7.2, care a interzis ca clasele să fie denumite `Object`.
+Încă de la începuturile sale, modelul de obiecte din PHP a suferit de o multitudine de deficiențe și neajunsuri grave. Acest lucru a dus la crearea clasei `Nette\Object` (în 2007), care a avut ca scop rectificarea acestor probleme și îmbunătățirea confortului de utilizare a PHP. Tot ceea ce era necesar era ca alte clase să moștenească din ea și să obțină beneficiile oferite de aceasta. Când PHP 5.4 a introdus suportul pentru trăsături, clasa `Nette\Object` a fost înlocuită cu trăsătura `Nette\SmartObject`. Acest lucru a eliminat necesitatea de a moșteni de la un strămoș comun. În plus, trăsătura putea fi utilizată în clase care moșteneau deja de la o altă clasă. Sfârșitul definitiv al `Nette\Object` a venit odată cu lansarea PHP 7.2, care a interzis ca clasele să fie denumite `Object`.
 
-Pe măsură ce dezvoltarea PHP a continuat, modelul de obiecte și capacitățile limbajului au fost îmbunătățite. Funcțiile individuale ale clasei `SmartObject` au devenit redundante. De la lansarea PHP 8.2, singura caracteristică rămasă care nu este încă direct suportată în PHP este capacitatea de a utiliza așa-numitele [proprietăți |#Properties, Getters and Setters].
+Pe măsură ce dezvoltarea PHP a continuat, modelul său de obiecte și capacitățile limbajului s-au îmbunătățit. Diverse funcții ale clasei `SmartObject` au devenit redundante. De la lansarea PHP 8.2, a rămas o singură funcție care nu este direct suportată în PHP: capacitatea de a utiliza așa-numitele [proprietăți |#Properties, getters, and setters].
 
-Ce caracteristici ofereau cândva `Nette\Object` și `Nette\Object`? Iată o prezentare generală. (Exemplele folosesc clasa `Nette\Object`, dar majoritatea proprietăților se aplică și la trăsătura `Nette\SmartObject` ).
+Ce caracteristici au oferit `Nette\Object` și, prin extensie, `Nette\SmartObject`? Iată o prezentare generală. (În exemple, este utilizată clasa `Nette\Object`, dar majoritatea caracteristicilor se aplică și trăsăturii `Nette\SmartObject` ).
 
 
 Erori inconsistente .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Este posibil ca PHP-ul de astăzi să nu aibă nicio formă de "ai vrut să spui?", dar [Tracy |tracy:] adaugă acest addendum la erori. Și poate chiar să [corecteze |tracy:open-files-in-ide#toc-demos] singur astfel de erori.
+În timp ce PHP-ul actual nu are o funcție "ai vrut să spui?", această frază poate fi adăugată la erori de către [Tracy |tracy:]. Acesta poate chiar să [corecteze automat astfel de erori |tracy:open-files-in-ide#toc-demos].
 
 
 Metode de extensie .[#toc-extension-methods]
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/ro/staticclass.texy b/utils/ro/staticclass.texy
new file mode 100644
index 0000000000..76eaa09869
--- /dev/null
+++ b/utils/ro/staticclass.texy
@@ -0,0 +1,21 @@
+Clase statice
+*************
+
+.[perex]
+StaticClass este utilizat pentru a desemna clasele statice.
+
+
+Instalare:
+
+```shell
+composer require nette/utils
+```
+
+Clasele statice, adică clasele care nu sunt destinate a fi instanțiate, pot fi marcate cu trăsătura [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/ro/strings.texy b/utils/ro/strings.texy
index 2f57b83871..4441c30d96 100644
--- a/utils/ro/strings.texy
+++ b/utils/ro/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Modifică șirul UTF-8 în forma utilizată în URL, adică elimină diacriticele și înlocuiește toate caracterele, cu excepția literelor din alfabetul englez și a numerelor, cu o cratimă.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Necesită extensia PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Îndepărtează toate spațiile din stânga și din dreapta (sau caracterele trecute ca al doilea argument) dintr-un șir de caractere codificat UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Returnează o parte din șirul UTF-8 specificat prin poziția de pornire `$start` și lungimea `$length`. Dacă `$start` este negativ, șirul returnat va începe la al `$start`-lea caracter de la sfârșitul șirului.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Utilizează codul nativ `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Compară două șiruri UTF-8 sau părți ale acestora, fără a lua în considerare cazul caracterelor. Dacă `$length` este nul, se compară șiruri întregi, dacă este negativ, se compară numărul corespunzător de caractere de la sfârșitul șirurilor, altfel se compară numărul corespunzător de caractere de la început.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Caută în șirul de caractere toate ocurențele care corespund expresiei regulate și returnează o matrice de matrici care conține expresia găsită și fiecare subexpresie.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Dacă `$lazy` este `true`, funcția returnează un `Generator` în loc de un array, ceea ce oferă beneficii semnificative de performanță atunci când se lucrează cu șiruri mari. Generatorul permite găsirea incrementală a potrivirilor, în loc să proceseze întregul șir odată. Acest lucru permite gestionarea eficientă a textelor de intrare extrem de mari. În plus, puteți întrerupe procesarea în orice moment dacă găsiți potrivirea dorită, economisind astfel timp de calcul.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/ro/validators.texy b/utils/ro/validators.texy
index 8c2e721b57..8fed8b8714 100644
--- a/utils/ro/validators.texy
+++ b/utils/ro/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Verifică dacă elementul `$key` din array-ul `$array` este format din [tipurile așteptate |#expected types], separate prin pipe. În caz contrar, se aruncă excepția [api:Nette\Utils\AssertionException]. Șirul `item '%' in array` din mesajul de excepție poate fi înlocuit cu parametrul `$label`.
 
diff --git a/utils/ru/@home.texy b/utils/ru/@home.texy
index e75c6199af..67d3255340 100644
--- a/utils/ru/@home.texy
+++ b/utils/ru/@home.texy
@@ -11,15 +11,16 @@
 | [Генерация случайных строк |random] | Nette\Utils\Random
 | [Дата и время |datetime] | Nette\Utils\DateTime
 | [Изображения |images] | Nette\Utils\Image
-| [Модель объекта |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Пагинация |paginator] | Nette\Utils\Paginator
 | [Парсинг и генерация JSON |json] | Nette\Utils\Json
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [Поле |arrays] | Nette\Utils\Arrays
 | [Строки |strings] | Nette\Utils\Strings
 | [Типы |type] | Nette\Utils\Type
 | [Файловая система |filesystem] | Nette\Utils\FileSystem
 | [Функции-помощники |helpers] | Nette\Utils\Helpers
 | [Элементы HTML |html-elements] | Nette\Utils\Html
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [PHP Отражение |reflection] | Nette\Utils\Reflection
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | Версия, совместимая с PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/ru/@left-menu.texy b/utils/ru/@left-menu.texy
index 4c34b12008..62c1662dd5 100644
--- a/utils/ru/@left-menu.texy
+++ b/utils/ru/@left-menu.texy
@@ -8,6 +8,7 @@
 - [Изображения |images]
 - [Обратные вызовы |callback]
 - [Пагинатор |paginator]
+- [Итерабельные таблицы |iterables]
 - [Поле |arrays]
 - [Случайные строки |random]
 - [Строки |strings]
@@ -15,8 +16,9 @@
 - [Файловая система |filesystem]
 - [Функции-помощники |helpers]
 - [Элементы HTML |html-elements]
+- [SmartObject]
+- [StaticClass]
 - [PHP Отражение |reflection]
-- [SmartObject |smartobject]
 
 
 Другие инструменты
diff --git a/utils/ru/arrays.texy b/utils/ru/arrays.texy
index 05dca37498..06de535fd9 100644
--- a/utils/ru/arrays.texy
+++ b/utils/ru/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Массивы .[#toc-arrays]
 ======================
 
-[api:Nette\Utils\Arrays] это статический класс, содержащий полезные функции для работы с массивами.
+[api:Nette\Utils\Arrays] это статический класс, который содержит несколько удобных функций для работы с массивами. Его эквивалентом для итераторов является [Nette\Utils\Iterables |iterables].
 
 В следующих примерах предполагается, что псевдоним уже создан:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Функция гибко преобразует `$array` в ассоциативный массив или объекты в соответствии с заданным путем `$path`. Путь может быть строкой или массивом. Он состоит из имен ключей входного массива и операторов типа '[]', '->', '=' и '|'. Выбрасывает `Nette\InvalidArgumentException`, если путь недопустим.
+
+```php
+// Преобразование в ассоциативный массив с помощью простого ключа
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// Присвоение значений от одного ключа к другому с помощью оператора =
+$result = Arrays::associate($arr, 'name=age'); // или ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// создание объекта с помощью оператора ->
+$result = Arrays::associate($arr, '->name'); // или ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// объединение ключей с помощью оператора |
+$result = Arrays::associate($arr, 'name|age'); // или ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// добавление в массив с помощью []
+$result = Arrays::associate($arr, 'name[]'); // или ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,10 +76,10 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
-Проверяет, все ли элементы в массиве проходят тест, реализованный в `$callback` с сигнатурой `function ($value, $key, array $array): bool`.
+Проверяет, все ли элементы в массиве проходят тест, реализованный в `$predicate` с сигнатурой `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 30, 39, 29, 10, 13];
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 См. [some() |#some].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Возвращает новый массив, содержащий все пары ключ-значение, соответствующие заданному `$predicate`. Обратный вызов имеет сигнатуру `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Возвращает первую запись из массива или null, если массив пуст. Не изменяет внутренний указатель, в отличие от `reset()`.
+Возвращает первый элемент (соответствующий указанному предикату, если он задан). Если такого элемента нет, возвращается результат вызова `$else` или null.
+Функция `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`.
+
+Она не изменяет внутренний указатель, в отличие от `reset()`. Параметры `$predicate` и `$else` существуют с версии 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+См. [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Возвращает ключ первого элемента (соответствующего указанному предикату, если он задан) или null, если такого элемента нет. Ключ `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+См. [lastKey() |#lastKey()].
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Возвращает элемент `$array[$key]`. Если он не существует, то либо выдается исключение `Nette\InvalidArgumentException`, либо, если задан третий параметр `$default`, то возвращается этот параметр.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Возвращает последний элемент (соответствующий указанному предикату, если он задан). Если такого элемента нет, возвращается результат вызова `$else` или null.
+Функция `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`.
+
+Она не изменяет внутренний указатель, в отличие от `end()`. Параметры `$predicate` и `$else` существуют с версии 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+См. раздел [first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Возвращает последнюю запись массива или null, если массив пуст. Не изменяет внутренний указатель, в отличие от `end()`.
+Возвращает ключ последнего элемента (соответствующего указанному предикату, если он задан) или null, если такого элемента нет. Ключ `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+См. [firstKey() |#firstKey()].
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Вызывает `$callback` на всех элементах массива и возвращает массив возвращаемых значений. Обратный вызов имеет сигнатуру `function ($value, $key, array $array): bool`.
+Вызывает `$transformer` на всех элементах массива и возвращает массив возвращаемых значений. Обратный вызов имеет сигнатуру `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Создает новый массив путем преобразования значений и ключей исходного массива. Функция `$transformer` имеет сигнатуру `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Если `$transformer` возвращает `null`, элемент пропускается. Для сохраненных элементов первый элемент возвращаемого массива используется в качестве нового ключа, а второй - в качестве нового значения.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Этот метод полезен в ситуациях, когда необходимо изменить структуру массива (одновременно ключи и значения) или отфильтровать элементы при преобразовании (возвращая null для ненужных элементов).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Значения из второго массива всегда добавляются к концу первого. Исчезновение значения `10` из второго поля может показаться немного непонятным. Обратите внимание, что это значение, как и значение `5` v poli prvním mají přiřazený stejný numerický klíč `0`, поэтому в результирующий массив попадает только элемент из первого поля.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Нормализует массив к ассоциативному массиву. Заменяет цифровые клавиши их значениями, новое значение будет `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Возвращает и удаляет значение элемента из массива. Если он не существует, выдает исключение или возвращает значение `$default`, если оно существует.
 
@@ -284,10 +397,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
-Проверяет, проходит ли хотя бы один элемент в массиве тест, реализованный в `$callback` с сигнатурой `function ($value, $key, array $array): bool`.
+Проверяет, проходит ли хотя бы один элемент в массиве тест, реализованный в `$predicate` с сигнатурой `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 2, 3, 4];
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Выводит каждый элемент массива в строку и оборачивает ее префиксом `$prefix` и суффиксом `$suffix`.
 
diff --git a/utils/ru/datetime.texy b/utils/ru/datetime.texy
index d6e82906ca..b602c58b81 100644
--- a/utils/ru/datetime.texy
+++ b/utils/ru/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Расширяет [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] возможностью ввода часового пояса в виде строки.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
diff --git a/utils/ru/filesystem.texy b/utils/ru/filesystem.texy
index 0e83acb07b..8704cd54e9 100644
--- a/utils/ru/filesystem.texy
+++ b/utils/ru/filesystem.texy
@@ -2,9 +2,11 @@
 ****************
 
 .[perex]
-[api:Nette\Utils\FileSystem] это статический класс, содержащий полезные функции для работы с файловой системой. Одно из преимуществ перед собственными функциями PHP заключается в том, что они бросают исключения в случае ошибок.
+[api:Nette\Utils\FileSystem] это класс, содержащий полезные функции для работы с файловой системой. Преимущество перед собственными функциями PHP заключается в том, что в случае ошибок они выбрасывают исключения.
 
 
+Если необходимо найти файлы на диске, используйте [Finder |finder].
+
 Установка:
 
 ```shell
@@ -174,3 +176,26 @@ platformSlashes(string $path): string .[method]
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Статический и нестатический подход .[#toc-static-vs-non-static-approach]
+========================================================================
+
+Чтобы легко заменить класс `FileSystem` на другой класс, например, для тестирования, используйте нестатический подход:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/ru/finder.texy b/utils/ru/finder.texy
index f873f51610..e749cd0e14 100644
--- a/utils/ru/finder.texy
+++ b/utils/ru/finder.texy
@@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // все каталоги
 
 Вы можете использовать [подстановочные знаки |#wildcards] `*`, `**`, `?` and `[...]` в маске. Можно даже указывать в каталогах, например, `src/*.php` будет искать все файлы PHP в каталоге `src`.
 
+Симлинки также считаются каталогами или файлами.
+
 
 Где искать? .[#toc-where-to-search]
 -----------------------------------
diff --git a/utils/ru/floats.texy b/utils/ru/floats.texy
index ff06b4f298..769306a0e7 100644
--- a/utils/ru/floats.texy
+++ b/utils/ru/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 При попытке сравнить `NAN` возникает исключение `\LogicException`.
 
+.[tip]
+Класс `Floats` допускает различия меньше, чем `1e-10`. Если вам нужно работать с большей точностью, используйте библиотеку BCMath.
+
 
 Сравнение плавающих значений .[#toc-float-comparison]
 =====================================================
diff --git a/utils/ru/html-elements.texy b/utils/ru/html-elements.texy
index dc898cf51e..e7593eee5a 100644
--- a/utils/ru/html-elements.texy
+++ b/utils/ru/html-elements.texy
@@ -219,10 +219,10 @@ $el = Html::el('span')
 Другой способ создания и вставки нового узла `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('první');
-// <ul><li class="first">první</li></ul>
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
+// <ul><li class="first">hello</li></ul>
 ```
 
 Вы можете работать с узлами так, как если бы они были массивами. То есть, обращайтесь к каждому из них с помощью квадратных скобок, считайте их с помощью `count()` и выполняйте итерации:
diff --git a/utils/ru/images.texy b/utils/ru/images.texy
index e7c5cba4c3..ecc34ceca4 100644
--- a/utils/ru/images.texy
+++ b/utils/ru/images.texy
@@ -17,6 +17,8 @@ composer require nette/utils
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 По желанию можно указать цвет фона (по умолчанию черный):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Или загрузите изображение из файла:
@@ -41,17 +43,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
 $image = Image::fromFile('nette.jpg');
 ```
 
-Поддерживаются форматы JPEG, PNG, GIF, WebP, AVIF и BMP, но ваша версия PHP также должна их поддерживать (проверьте `phpinfo()`, раздел GD). Анимация не поддерживается.
-
-Нужно ли определять формат изображения при загрузке? Метод возвращает его во втором параметре:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type - Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF или Image::BMP
-```
-
-Только обнаружение без загрузки изображения выполняется `Image::detectTypeFromFile()`.
-
 
 Сохранение изображения .[#toc-save-the-image]
 =============================================
@@ -68,25 +59,45 @@ $image->save('resampled.jpg');
 $image->save('resampled.jpg', 80); // JPEG, 80% качества
 ```
 
-Если формат не очевиден из расширения файла, он может быть указан одной из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`:
+Если формат не очевиден из расширения файла, он может быть задан [константой |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Изображение может быть записано не на диск, а в переменную:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, 80% качества
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, 80% качества
 ```
 
 или отправляется непосредственно в браузер с соответствующим HTTP-заголовком `Content-Type`:
 
 ```php
 // отправляет заголовок Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Форматы .[#toc-formats]
+=======================
+
+Поддерживаются следующие форматы: JPEG, PNG, GIF, WebP, AVIF и BMP. Однако они также должны поддерживаться вашей версией PHP, что можно проверить с помощью функции [isTypeSupported() |#isTypeSupported()]. Анимация не поддерживается.
+
+Форматы представлены константами `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` и `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Нужно определить формат изображения при загрузке? Метод возвращает его во втором параметре:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Фактическое определение без загрузки изображения выполняется с помощью `Image::detectTypeFromFile()`.
+
 
 Изменить размер .[#toc-image-resize]
 ====================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Метод `cropAuto()` является объектной заменой функции `imagecropauto()`, более подробную информацию см. в [документации к ней |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Цвета .[#toc-colors]
+====================
+
+Метод `ImageColor::rgb()` позволяет задать цвет, используя значения красного, зеленого и синего цветов (RGB). Опционально можно указать значение прозрачности от 0 (полностью прозрачный) до 1 (полностью непрозрачный), как в CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Метод `ImageColor::hex()` позволяет задать цвет, используя шестнадцатеричный формат, аналогично CSS. Он поддерживает форматы `#rgb`, `#rrggbb`, `#rgba` и `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Цвета могут использоваться и в других методах, таких как `ellipse()`, `fill()` и т.д.
+
+
 Рисование и редактирование .[#toc-drawing-and-editing]
 ======================================================
 
-Вы можете рисовать, можете писать, но не рвите страницы. Все функции PHP для работы с изображениями, такие как [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], доступны вам, но в объектно-ориентированном обличье:
+Можно рисовать, можно писать, можно использовать все функции PHP для работы с изображениями, см. раздел " [Обзор методов |#Overview of methods]", но в объектно-ориентированной обертке:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-См. раздел [Обзор методов |#Overview-of-Methods].
+Поскольку функции PHP для рисования прямоугольников непрактичны из-за необходимости указания координат, класс `Image` предлагает их замену в виде функций [rectangleWH() |#rectangleWH()] и [filledRectangleWH() |#filledRectangleWH()].
 
 
 Объединение нескольких изображений .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // координаты могут быть снова заданы в процентах
 $blank->place($logo, '80%', '80%'); // вставьте в правый нижний угол
@@ -219,53 +250,68 @@ $blank->place($image, '80%', '80%', 25); // прозрачность соста
 =========================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Создает новое истинно цветное изображение заданных размеров. По умолчанию используется черный цвет.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Считывает изображение из файла и возвращает его тип в формате `$detectedFormat`. Поддерживаются следующие типы: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Считывает изображение из файла и возвращает его [тип |#Formats] в формате `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Считывает изображение из строки и возвращает его тип в формате `$detectedFormat`. Поддерживаются следующие типы: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Считывает изображение из строки и возвращает его [тип |#Formats] в формате `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Создает цвет, который может быть использован в других методах, таких как `ellipse()`, `fill()` и т.д.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Эта функция была заменена классом `ImageColor`, см. [цвета |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Возвращает расширение файла для заданной константы `Image::XXX`.
+Возвращает расширение файла для заданного [типа |#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Возвращает тип mime для заданной константы `Image::XXX`.
+Возвращает тип mime для заданного [типа |#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Возвращает тип изображения в виде константы `Image::XXX` в соответствии с расширением файла.
+Возвращает [тип |#Formats] изображения в соответствии с расширением файла.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Возвращает тип изображения в виде константы `Image::XXX`, а также его размеры в параметрах `$width` и `$height`.
+Возвращает [тип |#Formats] файла изображения, а в параметрах `$width` и `$height` также его размеры.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Возвращает тип изображения из строки в виде константы `Image::XXX` и его размеры в параметрах `$width` и `$height`.
+Возвращает [тип |#Formats] изображения из строки, а в параметрах `$width` и `$height` также его размеры.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Определяет, поддерживается ли заданный [тип |#Formats] изображения.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Возвращает массив поддерживаемых типов изображений (константы `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Вычисляет размеры прямоугольника, в который заключен текст заданного шрифта и размера. Возвращается ассоциативный массив, содержащий ключи `left`, `top`, `width`, `height`. Левое поле может быть отрицательным, если текст начинается с левого свеса.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Возвращает изображение, содержащее аффинно-трансформированное изображение src с использованием необязательной области обрезания. ([подробнее |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Возвращает конкатенацию двух матриц аффинного преобразования, что полезно, если к одному изображению необходимо применить сразу несколько преобразований. ([подробнее |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Возвращает матрицу преобразования матрицы. ([подробнее |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ antialias(bool $on): void .[method]
 Использование сглаженного примитива с прозрачным цветом фона может привести к неожиданным результатам. Метод смешивания использует цвет фона как любой другой цвет. ([подробнее |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Рисует дугу окружности с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Нарисует первый символ `$char` в изображении с левым верхним углом `$x`, `$y` (левый верхний угол равен 0, 0) цветом `$color`. ([подробнее |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Рисует символ `$char` вертикально по указанной координате в заданном изображении. ([подробнее |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Возвращает идентификатор цвета, представляющий цвет, состоящий из заданных компонентов RGB. Должен быть вызван для создания каждого цвета, который будет использоваться в изображении. ([подробнее |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Возвращает количество цветов в палитре изображения. ([подробнее |https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Получает или устанавливает прозрачный цвет изображения. ([подробнее |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Обрезает изображение до заданной прямоугольной области. Размеры могут быть указаны как целые числа в пикселях или строки в процентах (например, `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Автоматическое кадрирование изображения в соответствии с заданным `$mode`. ([подробнее |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Рисует эллипс с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Заполняет область, начинающуюся в заданной координате (слева вверху 0, 0), заданным `$color`. ([подробнее |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Рисует неполную дугу с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Рисует эллипс с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Создает заполненный многоугольник на изображении. ([подробнее |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Создает прямоугольник, заполненный `$color` на изображении, начиная с точки 1 и заканчивая точкой 2. Точка 0, 0 - левый верхний угол изображения. ([подробнее |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Создает прямоугольник, заполненный `$color` на изображении, начиная с точек `$x1` и `$y1` и заканчивая точками `$x2` и `$y2`. Точка 0, 0 - левый верхний угол изображения. ([подробнее |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Создает на растре прямоугольник с заливкой `$color`, начиная с точек `$left` и `$top`, шириной `$width` и высотой `$height`. Точка 0, 0 - левый верхний угол изображения.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Создает заливку, цвет границы которой определяется `$border`. Начальная точка заливки - `$x`, `$y` (левый верхний угол - 0, 0), а область заливается цветом `$color`. ([подробнее |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Инвертирует изображение по заданному адресу `$mode`. ([подробнее |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Пишите текст на изображении, используя шрифты FreeType 2. ([подробнее |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Напишите текст по картинке. ([подробнее |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Возвращает ширину изображения.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Включение или выключение режима чересстрочной развертки. Если установлен чересстрочный режим и изображение сохраняется в формате JPEG, оно будет сохранено как прогрессивный JPEG. ([подробнее |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Установите флаг альфа-смешения для использования эффектов наслоения. ([подробнее |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Проводит линию между двумя заданными точками. ([подробнее |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Рисует открытый многоугольник на изображении. В отличие от `polygon()`, между последней и первой точкой не проводится линия. ([подробнее |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Копирует `$image` в изображение по координатам `$left` и `$top`. Координаты могут быть указаны как целые числа в пикселях или строки в процентах (например, `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Создает многоугольник на изображении. ([подробнее |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Создает прямоугольник по заданным координатам. ([подробнее |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Создает прямоугольник по заданным координатам.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Изменение размеров изображения, [дополнительная информация |#Image-Resize]. Размеры могут быть указаны как целые числа в пикселях или строки в процентах (например, `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Устанавливает или возвращает разрешение изображения в DPI (точках на дюйм). Если ни один из дополнительных параметров не указан, текущее разрешение возвращается в виде индексированного поля. Если указано только `$resX`, то горизонтальное и вертикальное разрешение устанавливается на это значение. Если указаны оба дополнительных параметра, горизонтальное и вертикальное разрешения устанавливаются на эти значения.
 
 Разрешение используется в качестве метаинформации только при чтении и записи изображений в форматы, поддерживающие такую информацию (в настоящее время это PNG и JPEG). Это не влияет ни на какие операции рисования. Разрешение новых изображений по умолчанию составляет 96 DPI. ([подробнее |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ rotate(float $angle, int $backgroundColor): Image .[method]
 Требует наличия *Bundled GD extension*, поэтому может работать не везде.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Сохраняет изображение в файл.
 
-Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Если тип не очевиден из расширения файла, вы можете указать его с помощью одной из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Если тип не очевиден из расширения файла, вы можете указать его с помощью одной из констант `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Масштабирование изображения с использованием заданного алгоритма интерполяции. ([подробнее |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Выводит изображение в браузер.
 
-Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Тип - одна из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Задает метод интерполяции, который влияет на методы `rotate()` и `affine()`. ([подробнее |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Рисует пиксель в указанной координате. ([подробнее |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ sharpen(): Image .[method]
 Требует наличия *Bundled GD extension*, поэтому может работать не везде.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Выводит строку по заданным координатам. ([подробнее |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Выводит строку по вертикали в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Сохраняет изображение в строке.
 
-Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Тип - одна из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`.
+Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Преобразует truecolor изображение в палитру. ([подробнее |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Печатает заданный текст в изображение с использованием шрифтов TrueType. ([подробнее |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Записывает заданный текст в изображение. ([подробнее |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/ru/iterables.texy b/utils/ru/iterables.texy
new file mode 100644
index 0000000000..17d8ad037a
--- /dev/null
+++ b/utils/ru/iterables.texy
@@ -0,0 +1,170 @@
+Функции итератора
+*****************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] это статический класс с функциями для работы с итераторами. Его аналог для массивов - [Nette\Utils\Arrays |arrays].
+
+
+Установка:
+
+```shell
+composer require nette/utils
+```
+
+Во всех примерах предполагается, что создан следующий псевдоним:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Поиск заданного значения в итераторе. Использует строгое сравнение (`===`) для проверки совпадения. Возвращает `true`, если значение найдено, иначе `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Этот метод полезен, когда нужно быстро определить, присутствует ли конкретное значение в итераторе, не перебирая вручную все элементы.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Поиск заданного ключа в итераторе. Использует строгое сравнение (`===`) для проверки совпадения. Возвращает `true`, если ключ найден, иначе `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Проверяет, все ли элементы итератора удовлетворяют условию, определенному в `$predicate`. Функция `$predicate` имеет сигнатуру `function ($value, $key, iterable $iterable): bool` и должна возвращать `true` для каждого элемента, чтобы метод `every()` вернул `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Этот метод полезен для проверки того, что все элементы коллекции удовлетворяют определенному условию, например, все ли числа меньше определенного значения.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Создает новый итератор, содержащий только те элементы из исходного итератора, которые удовлетворяют условию, определенному в `$predicate`. Функция `$predicate` имеет сигнатуру `function ($value, $key, iterable $iterable): bool` и должна возвращать `true` для элементов, которые должны быть сохранены.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Метод использует генератор, то есть фильтрация происходит инкрементально во время итерации. Это экономит память и позволяет работать с очень большими коллекциями. Если вы не выполняете итерацию по всем элементам результирующего итератора, вы экономите вычислительные усилия, поскольку не все элементы исходного итератора обрабатываются.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Возвращает первый элемент итератора. Если указано `$predicate`, возвращается первый элемент, удовлетворяющий заданному условию. Функция `$predicate` имеет сигнатуру `function ($value, $key, iterable $iterable): bool`. Если не найдено ни одного удовлетворяющего элемента, вызывается функция `$else` (если она предоставлена) и возвращается ее результат. Если `$else` не предоставлена, возвращается `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Этот метод полезен, когда нужно быстро получить первый элемент коллекции или первый элемент, удовлетворяющий определенному условию, без ручного итерационного просмотра всей коллекции.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Возвращает ключ первого элемента итератора. Если указано `$predicate`, возвращается ключ первого элемента, удовлетворяющего заданному условию. Функция `$predicate` имеет сигнатуру `function ($value, $key, iterable $iterable): bool`. Если ни один элемент не найден, вызывается функция `$else` (если она предоставлена) и возвращается ее результат. Если `$else` не предоставлена, возвращается `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Создает новый итератор путем применения функции `$transformer` к каждому элементу исходного итератора. Функция `$transformer` имеет сигнатуру `function ($value, $key, iterable $iterable): mixed`, а ее возвращаемое значение используется в качестве нового значения элемента.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Метод использует генератор, то есть преобразование происходит инкрементально во время итерации. Это экономит память и позволяет работать с очень большими коллекциями. Если вы не выполняете итерацию по всем элементам результирующего итератора, вы экономите вычислительные усилия, поскольку не все элементы исходного итератора обрабатываются.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Создает новый итератор путем преобразования значений и ключей исходного итератора. Функция `$transformer` имеет сигнатуру `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Если `$transformer` возвращает `null`, элемент пропускается. Для сохраненных элементов первый элемент возвращаемого массива используется в качестве нового ключа, а второй элемент - в качестве нового значения.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Как и `map()`, этот метод использует генератор для инкрементной обработки и эффективности использования памяти. Это позволяет работать с большими коллекциями и экономить вычислительные усилия, обрабатывая только часть результата.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Создает обертку вокруг итератора, которая кэширует его ключи и значения во время итерации. Это позволяет повторять итерации над данными без необходимости повторной обработки исходного источника данных.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Этот метод полезен в ситуациях, когда вам нужно несколько раз просмотреть один и тот же набор данных, но исходный итератор не поддерживает повторную итерацию или повторная итерация будет дорогостоящей (например, при чтении данных из базы данных или файла).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Проверяет, удовлетворяет ли хотя бы один элемент итератора условию, определенному в `$predicate`. Функция `$predicate` имеет сигнатуру `function ($value, $key, iterable $iterable): bool` и должна вернуть `true` хотя бы для одного элемента, чтобы метод `some()` вернул `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Этот метод полезен для быстрой проверки того, есть ли в коллекции хотя бы один элемент, удовлетворяющий определенному условию, например, содержит ли коллекция хотя бы одно четное число.
+
+Смотрите [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Преобразует любой итерируемый объект (массив, Traversable) в итератор. Если входной объект уже является итератором, он возвращается без изменений.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Этот метод полезен, когда нужно убедиться, что у вас есть итератор, независимо от типа входных данных. Это может быть полезно при создании функций, работающих с разными типами итерируемых данных.
diff --git a/utils/ru/json.texy b/utils/ru/json.texy
index be4e3967f5..365c142bbd 100644
--- a/utils/ru/json.texy
+++ b/utils/ru/json.texy
@@ -77,7 +77,7 @@ decode(string $json, bool $forceArray=false): mixed .[method]
 
 ```php
 Json::decode('{"variable": true}'); // возвращает объект типа stdClass
-Json::decode('{"variable": true}', forceArray: true); // возвращает массив
+Json::decode('{"variable": true}', forceArrays: true); // возвращает массив
 ```
 
 При возникновении ошибки выбрасывается исключение `Nette\Utils\JsonException`.
diff --git a/utils/ru/smartobject.texy b/utils/ru/smartobject.texy
index 458fd548d2..e0301323fd 100644
--- a/utils/ru/smartobject.texy
+++ b/utils/ru/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject и StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject добавляет поддержку *свойств* в классы PHP. StaticClass используется для обозначения статических классов.
+SmartObject во многом исправлял поведение объектов, но современный PHP уже включает большинство этих улучшений нативно. Тем не менее, в нем все еще добавлена поддержка *property*.
 
 
 Установка:
@@ -65,31 +65,16 @@ echo $circle->visible; // calls isVisible()
 Свойства - это прежде всего "синтаксический сахар"((syntactic sugar)), который призван сделать жизнь программиста слаще за счет упрощения кода. Если они вам не нужны, вы не обязаны их использовать.
 
 
-Статические классы .[#toc-static-classes]
-=========================================
+Взгляд в историю .[#toc-a-glimpse-into-history]
+===============================================
 
-Статические классы, т.е. классы, которые не предназначены для инстанцирования, могут быть помечены признаком `Nette\StaticClass`:
+SmartObject использовался для улучшения поведения объектов различными способами, но современный PHP уже включает в себя большинство из этих улучшений. Следующий текст - это ностальгический взгляд в историю, напоминающий нам о том, как все развивалось.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Когда вы пытаетесь создать экземпляр, возникает исключение `Error`, указывающее на то, что класс является статическим.
-
-
-Взгляд в историю .[#toc-a-look-into-the-history]
-================================================
-
-SmartObject использовался для улучшения и исправления поведения класса во многих отношениях, но развитие PHP сделало большинство первоначальных функций излишними. Поэтому ниже мы рассмотрим историю развития этих функций.
-
-С самого начала объектная модель PHP страдала от ряда серьезных недостатков и неэффективности. Это послужило причиной создания класса `Nette\Object` (в 2007 году), который попытался устранить их и улучшить опыт использования PHP. Этого оказалось достаточно, чтобы другие классы унаследовали от него и получили те преимущества, которые он принес. Когда в PHP 5.4 появилась поддержка трейтов, класс `Nette\Object` был заменен на `Nette\SmartObject`. Таким образом, больше не было необходимости наследоваться от общего предка. Кроме того, trait можно было использовать в классах, которые уже наследовались от другого класса. Окончательный конец `Nette\Object` наступил с выходом PHP 7.2, в котором было запрещено давать классам имена `Object`.
+С самого начала своего существования объектная модель PHP страдала от множества серьезных недостатков и недоработок. Это привело к созданию класса `Nette\Object` (в 2007 году), который был призван исправить эти недостатки и повысить удобство работы с PHP. Достаточно было наследовать от него другие классы, чтобы они получили те преимущества, которые он дает. Когда в PHP 5.4 появилась поддержка трейтов, класс `Nette\Object` был заменен трейтом `Nette\SmartObject`. Это избавило от необходимости наследоваться от общего предка. Более того, трейты можно было использовать в классах, которые уже наследовались от другого класса. Окончательный конец `Nette\Object` наступил с выходом PHP 7.2, который запретил называть классы `Object`.
 
-По мере развития PHP объектная модель и возможности языка совершенствовались. Отдельные функции класса `SmartObject` стали излишними. После выхода PHP 8.2 единственной функцией, которая пока не поддерживается в PHP напрямую, осталась возможность использовать так называемые [свойства |#Properties, getters and setters].
+По мере развития PHP его объектная модель и возможности языка совершенствовались. Различные функции класса `SmartObject` стали излишними. После выхода PHP 8.2 в PHP осталась только одна функция, не поддерживаемая напрямую: возможность использования так называемых [свойств |#Properties, getters, and setters].
 
-Какие функции предлагали `Nette\Object` и `Nette\Object`? Вот обзор. (В примерах используется класс `Nette\Object`, но большинство свойств применимо и к признаку `Nette\SmartObject` ).
+Какие же возможности предоставляли `Nette\Object` и, соответственно, `Nette\SmartObject`? Вот обзор. (В примерах используется класс `Nette\Object`, но большинство возможностей применимо и к свойству `Nette\SmartObject` ).
 
 
 Непоследовательные ошибки .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Современный PHP, возможно, не имеет формы "Вы имели в виду?", но [Tracy |tracy:] добавляет это дополнение к ошибкам. И он даже может сам [исправлять |tracy:open-files-in-ide#toc-demos] такие ошибки.
+Хотя современный PHP не имеет функции "Вы имели в виду?", эта фраза может быть добавлена к ошибкам [Tracy |tracy:]. Она даже может [автоматически исправлять такие ошибки |tracy:open-files-in-ide#toc-demos].
 
 
 Методы расширения .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // returns 'John Doe
+$reflection->getAnnotation('author'); // returns 'John Doe'
 ```
 
 Начиная с PHP 8.0, появилась возможность доступа к мета-информации в виде атрибутов:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/ru/staticclass.texy b/utils/ru/staticclass.texy
new file mode 100644
index 0000000000..97f573e878
--- /dev/null
+++ b/utils/ru/staticclass.texy
@@ -0,0 +1,21 @@
+Статические классы
+******************
+
+.[perex]
+StaticClass используется для обозначения статических классов.
+
+
+Установка:
+
+```shell
+composer require nette/utils
+```
+
+Статические классы, т.е. классы, не предназначенные для инстанцирования, могут быть помечены признаком [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/ru/strings.texy b/utils/ru/strings.texy
index 7a15e209a4..4221264249 100644
--- a/utils/ru/strings.texy
+++ b/utils/ru/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Изменяет строку UTF-8 до формата, используемого в URL, т.е. удаляет диакритические знаки и заменяет все символы, кроме букв английского алфавита и цифр, на дефис.
 
@@ -129,8 +129,8 @@ Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
 Требуется расширение PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Обрезает пробелы (или другие символы, указанные вторым параметром) из начала и конца строки UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Возвращает часть строки UTF-8 `$s`, заданную начальной позицией `$start` и длиной `$length`. Если `$start` отрицательный, то возвращаемая строка будет начинаться с символа -`$start` символа с конца.
 
@@ -266,8 +266,8 @@ Strings::length('červená'); // 7
 \--
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Сравнение двух строк UTF-8 или частей строк без учета регистра. Если `$length` содержит null, то сравниваются целые строки, если отрицательно, то сравнивается соответствующее количество символов с конца строк, иначе сравнивается соответствующее количество символов с начала.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Ищет в строке все вхождения, соответствующие регулярному выражению, и возвращает массив массивов, содержащих найденное выражение и каждое подвыражение.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Если `$lazy` равно `true`, то вместо массива функция возвращает `Generator`, что дает значительный выигрыш в производительности при работе с большими строками. Генератор позволяет находить совпадения постепенно, а не обрабатывать всю строку сразу. Это позволяет эффективно работать с очень большими входными текстами. Кроме того, вы можете прервать обработку в любой момент, если нашли нужное совпадение, что экономит вычислительное время.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/ru/validators.texy b/utils/ru/validators.texy
index 09e97bebeb..24e469e120 100644
--- a/utils/ru/validators.texy
+++ b/utils/ru/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Проверяет, что элемент под ключом `$key` в поле `$array` является одним из [ожидаемых типов |#Expected-Types], разделенных звездочкой. Если нет, то выбрасывается исключение [api:Nette\Utils\AssertionException]. Строка `item '%' in array` в тексте исключения может быть заменена другим параметром `$label`.
 
diff --git a/utils/sl/@home.texy b/utils/sl/@home.texy
index 131197c536..9a942e4e92 100644
--- a/utils/sl/@home.texy
+++ b/utils/sl/@home.texy
@@ -13,13 +13,14 @@ V paketu `nette/utils` boste našli niz uporabnih razredov za vsakdanjo uporabo:
 | [Pomočniki |helpers] | Nette\Utils\Helpers
 | [Elementi HTML |HTML Elements] | Nette\Utils\Html
 | [Slike |Images] | Nette\Utils\Image
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [JSON |JSON] | Nette\Utils\Json
-| [Objektni model |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginator |paginator] | Nette\Utils\Paginator
 | [PHP Reflection |reflection] | Nette\Utils\Reflection
 | [Tipi PHP |type] | Nette\Utils\Type
 | [Naključni nizi |random] | Nette\Utils\Random
  [Nizi |Strings] | Nette\Utils\Nizi | Nette\Utils\Nizi
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Validatorji |validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | različica | združljivo s PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/sl/@left-menu.texy b/utils/sl/@left-menu.texy
index 0e2cbfd550..dbd800f038 100644
--- a/utils/sl/@left-menu.texy
+++ b/utils/sl/@left-menu.texy
@@ -8,13 +8,15 @@ Paket nette/utils
 - [Pomočniki |helpers]
 - [Elementi HTML |HTML Elements]
 - [Slike |Images]
+- [Iterables |iterables]
 - [JSON |JSON]
 - [Paginator |paginator]
 - [Naključni nizi |random]
-- [SmartObject |SmartObject]
 - [Odsev PHP |reflection]
 - [Nizi |Strings]
 - [Plavaji |Floats]
+- [SmartObject]
+- [StaticClass]
 - [Tipi PHP |type]
 - [Validatorji |validators]
 
diff --git a/utils/sl/arrays.texy b/utils/sl/arrays.texy
index ba1f546b28..e31e791ce1 100644
--- a/utils/sl/arrays.texy
+++ b/utils/sl/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Mreže .[#toc-arrays]
 ====================
 
-[api:Nette\Utils\Arrays] je statični razred, ki vsebuje nekaj priročnih funkcij za polja.
+[api:Nette\Utils\Arrays] je statični razred, ki vsebuje nekaj priročnih funkcij za polja. Njegov ekvivalent za iteratorje je [Nette\Utils\Iterables |iterables].
 
 Naslednji primeri predpostavljajo, da je definiran naslednji vzdevek razreda:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Funkcija fleksibilno preoblikuje `$array` v asociativno polje ali predmete v skladu z določeno potjo `$path`. Pot je lahko niz ali polje. Sestavljena je iz imen ključev v vhodnem polju in operatorjev, kot so "[]", "->", "=" in "|". Če je pot neveljavna, se vrže `Nette\InvalidArgumentException`.
+
+```php
+// pretvorba v asociativno polje z uporabo preprostega ključa
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// pripisovanje vrednosti z ene tipke na drugo s pomočjo operatorja =
+$result = Arrays::associate($arr, 'name=age'); // ali ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// ustvarjanje objekta z uporabo operatorja ->
+$result = Arrays::associate($arr, '->name'); // ali ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// združevanje tipk z uporabo operatorja |
+$result = Arrays::associate($arr, 'name|age'); // ali ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// dodajanje v polje z uporabo []
+$result = Arrays::associate($arr, 'name[]'); // ali ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Preizkusi, ali vsi elementi v polju prestanejo test, ki ga izvaja navedena funkcija s podpisom `function ($value, $key, array $array): bool`.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Glejte [some( |#some()]).
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Vrne novo polje, ki vsebuje vse pare ključ-vrednost, ki ustrezajo danemu `$predicate`. Povratni klic ima podpis `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Vrne prvi element iz polja ali nič, če je polje prazno. Za razliko od `reset()` ne spremeni notranjega kazalca.
+Vrne prvi element (ki ustreza določenemu predikatu, če je podan). Če takega elementa ni, vrne rezultat klica `$else` ali nič.
+ `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`.
+
+Za razliko od `reset()` ne spreminja notranjega kazalca. Parametra `$predicate` in `$else` obstajata od različice 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Glej [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Vrne ključ prvega elementa (ki ustreza določenemu predikatu, če je podan) ali nič, če takega elementa ni. `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Glej [lastKey( |#lastKey()]).
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Vrne `$array[$key]` item. Če ne obstaja, se vrže `Nette\InvalidArgumentException`, razen če je kot tretji argument določena privzeta vrednost.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Vrne zadnji element (ki ustreza določenemu predikatu, če je podan). Če takega elementa ni, vrne rezultat klica `$else` ali nič.
+ `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`.
+
+Za razliko od `end()` ne spreminja notranjega kazalca. Parametra `$predicate` in `$else` obstajata od različice 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Glej [first( |#first()]).
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Vrne zadnji element iz polja ali nič, če je polje prazno. Za razliko od `end()` ne spremeni notranjega kazalca.
+Vrne ključ zadnjega elementa (ki ustreza določenemu predikatu, če je podan) ali nič, če takega elementa ni. `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Glej [firstKey( |#firstKey()]).
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Kliče `$callback` na vse elemente v polju in vrne polje vrnjenih vrednosti. Povratni klic ima podpis `function ($value, $key, array $array): bool`.
+Kliče `$transformer` na vse elemente v polju in vrne polje vrnjenih vrednosti. Povratni klic ima podpis `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Ustvari novo polje s preoblikovanjem vrednosti in ključev prvotnega polja. Funkcija `$transformer` ima podpis `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Če `$transformer` vrne `null`, se element preskoči. Pri ohranjenih elementih se prvi element vrnjenega polja uporabi kot novi ključ, drugi element pa kot nova vrednost.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Ta metoda je uporabna v primerih, ko je treba spremeniti strukturo polja (hkrati ključe in vrednosti) ali filtrirati elemente med transformacijo (tako, da se za neželene elemente vrne ničla).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Vrednosti iz drugega polja se vedno dodajo prvemu. Izginotje vrednosti `10` iz drugega polja se lahko zdi nekoliko zmedeno. Opozoriti je treba, da je ta vrednost kot tudi vrednost `5` in the first array have the same numeric key `0`, zato je v dobljenem polju samo element iz prvega polja.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Normalizira polje v asociativno polje. Numerične ključe zamenja z njihovimi vrednostmi, nova vrednost bo `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Vrne in odstrani vrednost elementa iz polja. Če ne obstaja, vrže izjemo ali vrne `$default`, če je naveden.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrne nič
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Preizkusi, ali vsaj en element v polju prestane test, ki ga izvaja posredovani povratni klic s podpisom `function ($value, $key, array $array): bool`.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // nastavi $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Vsak element polja pretvori v niz in ga obkroži z objektoma `$prefix` in `$suffix`.
 
diff --git a/utils/sl/datetime.texy b/utils/sl/datetime.texy
index f16a86ba84..e51d052630 100644
--- a/utils/sl/datetime.texy
+++ b/utils/sl/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Razširi [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] z možnostjo določitve časovnega pasu kot niza.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // ustvarite s časovnim območjem po meri
diff --git a/utils/sl/filesystem.texy b/utils/sl/filesystem.texy
index e51281d06c..6c144c173b 100644
--- a/utils/sl/filesystem.texy
+++ b/utils/sl/filesystem.texy
@@ -2,9 +2,11 @@ Funkcije datotečnega sistema
 ****************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] je statični razred, ki vsebuje uporabne funkcije za delo z datotečnim sistemom. Ena od prednosti v primerjavi z izvornimi funkcijami PHP je, da v primeru napak mečejo izjeme.
+[api:Nette\Utils\FileSystem] je razred, ki vsebuje uporabne funkcije za delo z datotečnim sistemom. Prednost pred izvornimi funkcijami PHP je, da v primeru napak mečejo izjeme.
 
 
+Če želite poiskati datoteke na disku, uporabite [Finder |finder].
+
 Namestitev:
 
 ```shell
@@ -174,3 +176,26 @@ Pretvarja poševnice v znake, značilne za trenutno platformo, tj. `\` v sistemu
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Statični in nestatični pristop .[#toc-static-vs-non-static-approach]
+====================================================================
+
+Če želite razred `FileSystem` preprosto zamenjati z drugim razredom, na primer za namene testiranja, ga uporabite nestatično:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/sl/finder.texy b/utils/sl/finder.texy
index c548de7150..93c2c0e7f7 100644
--- a/utils/sl/finder.texy
+++ b/utils/sl/finder.texy
@@ -61,6 +61,8 @@ Alternativa statičnim metodam je, da ustvarite primerek z uporabo `new Finder`
 
 Uporabite lahko [nadomestne znake |#wildcards] `*`, `**`, `?` and `[...]` v maski. Navedete lahko celo imenike, na primer `src/*.php` bo poiskal vse datoteke PHP v imeniku `src`.
 
+Za imenike ali datoteke se štejejo tudi simelne povezave.
+
 
 Kje iskati? .[#toc-where-to-search]
 -----------------------------------
diff --git a/utils/sl/floats.texy b/utils/sl/floats.texy
index 6832099a97..bf5337b071 100644
--- a/utils/sl/floats.texy
+++ b/utils/sl/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same': 'not same'; // enako
 
 Ko poskuša primerjati `NAN`, pa vrže izjemo `\LogicException`.
 
+.[tip]
+Razred `Floats` dopušča razlike, manjše od `1e-10`. Če morate delati z večjo natančnostjo, uporabite knjižnico BCMath.
+
 
 Primerjava floatov .[#toc-float-comparison]
 ===========================================
diff --git a/utils/sl/html-elements.texy b/utils/sl/html-elements.texy
index ed97eb4f06..3b111863f5 100644
--- a/utils/sl/html-elements.texy
+++ b/utils/sl/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Drug način za ustvarjanje in vstavljanje novega vozlišča `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/sl/images.texy b/utils/sl/images.texy
index 88c5d52f1f..57fbdc9d7a 100644
--- a/utils/sl/images.texy
+++ b/utils/sl/images.texy
@@ -17,6 +17,8 @@ Naslednji primeri predpostavljajo, da je definiran naslednji vzdevek razreda:
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 Po želji lahko določite barvo ozadja (privzeto je črna):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Sliko lahko naložimo iz datoteke:
@@ -41,17 +43,6 @@ Sliko lahko naložimo iz datoteke:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Podprti formati so JPEG, PNG, GIF, WebP, AVIF in BMP, vendar jih mora podpirati tudi vaša različica PHP (preverite `phpinfo()`, oddelek GD). Animacije niso podprte.
-
-Potrebujete zaznati format slike pri nalaganju? Metoda vrne format v drugem parametru:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type je Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ali Image::BMP
-```
-
-Samo zaznavanje brez nalaganja slike se izvede s spletno stranjo `Image::detectTypeFromFile()`.
-
 
 Shranjevanje slike .[#toc-save-the-image]
 =========================================
@@ -68,25 +59,45 @@ Določimo lahko kakovost stiskanja v območju 0..100 za JPEG (privzeto 85), WEBP
 $image->save('resampled.jpg', 80); // JPEG, kakovost 80%
 ```
 
-Če format ni razviden iz končnice datoteke, ga lahko določite z eno od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`:
+Če format ni razviden iz končnice datoteke, ga lahko določite s [konstanto |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Sliko lahko namesto na disk zapišete v spremenljivko:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, kakovost 80%
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, kakovost 80%
 ```
 
 ali pošljete neposredno brskalniku z ustreznim glavo HTTP `Content-Type`:
 
 ```php
 // pošilja glavo Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formati .[#toc-formats]
+=======================
+
+Podprti formati so JPEG, PNG, GIF, WebP, AVIF in BMP. Vendar jih mora podpirati tudi vaša različica PHP, kar lahko preverite s funkcijo [isTypeSupported() |#isTypeSupported()]. Animacije niso podprte.
+
+Formati so predstavljeni s konstantami `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` in `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Potrebujete zaznati format slike ob nalaganju? Metoda ga vrne v drugem parametru:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Dejansko zaznavanje brez nalaganja slike izvede `Image::detectTypeFromFile()`.
+
 
 Spreminjanje velikosti slike .[#toc-image-resize]
 =================================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Metoda `cropAuto()` je objektna enkapsulacija funkcije `imagecropauto()`, za več informacij si oglejte [njeno dokumentacijo |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Barve .[#toc-colors]
+====================
+
+Z metodo `ImageColor::rgb()` lahko barvo določite z uporabo rdeče, zelene in modre (RGB) vrednosti. Po želji lahko določite tudi vrednost prosojnosti od 0 (popolnoma prosojno) do 1 (popolnoma neprosojno), tako kot v CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Metoda `ImageColor::hex()` vam omogoča, da barvo določite z uporabo šestnajstiške oblike, podobno kot v CSS. Podpira oblike `#rgb`, `#rrggbb`, `#rgba` in `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Barve lahko uporabite tudi v drugih metodah, kot so `ellipse()`, `fill()` itd.
+
+
 Risanje in urejanje .[#toc-drawing-and-editing]
 ===============================================
 
-Lahko rišete, pišete, uporabljate vse funkcije PHP za delo s slikami, kot je [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], vendar v objektnem slogu:
+Lahko rišete, pišete, uporabljate vse funkcije PHP za manipulacijo s slikami, glejte [Pregled metod |#Overview of methods], vendar v objektno usmerjenem ovoju:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Glejte [Pregled metod |#Overview of Methods].
+Ker so funkcije PHP za risanje pravokotnikov zaradi določanja koordinat nepraktične, razred `Image` ponuja njihove nadomestke v obliki funkcij [rectangleWH() |#rectangleWH()] in [filledRectangleWH() |#filledRectangleWH()].
 
 
 Združitev več slik .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ V sliko lahko preprosto vstavite drugo sliko:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // koordinate lahko nastavite tudi v odstotkih.
 $blank->place($logo, '80%', '80%'); // v desnem spodnjem kotu
@@ -219,53 +250,68 @@ Pregled metod .[#toc-overview-of-methods]
 =========================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Ustvari novo pravo barvno sliko danih dimenzij. Privzeta barva je črna.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Prebere sliko iz datoteke in vrne njeno vrsto v `$detectedFormat`. Podprte vrste so `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`.
+Prebere sliko iz datoteke in vrne njeno [vrsto |#Formats] v `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Preberi sliko iz niza in vrne njeno vrsto v `$detectedFormat`. Podprte vrste so `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`.
+Preberi sliko iz niza in vrne njeno [vrsto |#Formats] v `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Ustvari barvo, ki jo lahko uporabite v drugih metodah, kot so `ellipse()`, `fill()` in tako naprej.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+To funkcijo je nadomestil razred `ImageColor`, glejte [barve |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Vrne končnico datoteke za podano konstanto `Image::XXX`.
+Vrne končnico datoteke za dano [vrsto |#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Vrne vrsto mime za podano konstanto `Image::XXX`.
+Vrne tip mime za dani [tip |#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Vrne vrsto slike kot konstanto `Image::XXX` glede na končnico datoteke.
+Vrne [vrsto |#Formats] slike glede na razširitev datoteke.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Vrne vrsto slikovne datoteke kot konstanto `Image::XXX`, v parametrih `$width` in `$height` pa tudi njene dimenzije.
+Vrne [vrsto |#Formats] slikovne datoteke in v parametrih `$width` in `$height` tudi njene dimenzije.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Vrne vrsto slike iz niza kot konstanto `Image::XXX`, v parametrih `$width` in `$height` pa tudi njene dimenzije.
+Vrne [vrsto |#Formats] slike iz niza in v parametrih `$width` in `$height` tudi njene dimenzije.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Ugotovi, ali je dana [vrsta |#Formats] slike podprta.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Vrne polje podprtih tipov slik (konstante `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Izračuna dimenzije pravokotnika, ki obkroža besedilo v določeni pisavi in velikosti. Vrne asociativno polje, ki vsebuje ključe `left`, `top`, `width`, `height`. Levi rob je lahko negativen, če se besedilo začne z levim previsom.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Vrne sliko, ki vsebuje afino transformirano sliko src z uporabo neobveznega območja obrezovanja. ([več |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Vrne združitev dveh matrik afine transformacije, kar je uporabno, če je treba na isto sliko uporabiti več transformacij naenkrat. ([več |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Vrne matriko afine transformacije. ([več |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ Aktivirajte metode hitrega risanja z izravnavo za črte in žične poligone. Ne
 Uporaba izravnanih primitivov s prozorno barvo ozadja lahko privede do nepričakovanih rezultatov. Metoda mešanja uporablja barvo ozadja kot vse druge barve. Pomanjkanje podpore za komponento alfa ne omogoča metode za izravnavo na podlagi alfa. ([več |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Nariše lok kroga s središčem na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Nariše prvi znak `$char` na sliki z zgornjim levim delom na `$x`,`$y` (zgornji levi del je 0, 0) z barvo `$color`. ([več |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Nariše znak `$char` navpično na določeno koordinato na dani sliki. ([več |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Vrne identifikator barve, ki predstavlja barvo, sestavljeno iz danih komponent RGB. Klicati ga je treba za ustvarjanje vsake barve, ki bo uporabljena v sliki. ([več |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Vrne število barv v slikovni paleti ([več |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Pridobi ali nastavi prozorno barvo na sliki. ([več |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Obreže sliko na podano pravokotno območje. Dimenzije lahko posredujete kot cela števila v pikslih ali kot nize v odstotkih (npr. `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Samodejno obreže sliko v skladu z danim `$mode`. ([več |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Nariše elipso s središčem na določenih koordinatah. ([več |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Izvede zapolnitev z zalivko, ki se začne na dani koordinati (levo zgoraj je 0, 0) z danim `$color` v sliki. ([več |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Nariše delni lok s središčem na določeni koordinati na sliki. ([več |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Nariše elipso s središčem na določeni koordinati na sliki. ([več |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Ustvari zapolnjen poligon v $sliki. ([več |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Ustvari pravokotnik, zapolnjen s `$color` na sliki, ki se začne v točki 1 in konča v točki 2. 0, 0 je zgornji levi kot slike. ([več |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Ustvari pravokotnik, zapolnjen s `$color` na sliki, ki se začne pri `$x1` in `$y1` ter konča pri `$x2` in `$y2`. Točka 0, 0 je zgornji levi vogal slike. ([več) |https://www.php.net/manual/en/function.imagefilledrectangle]
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Ustvari pravokotnik, zapolnjen s `$color` na sliki, ki se začne v točki `$left` in `$top`, s širino `$width` in višino `$height`. Točka 0, 0 je zgornji levi vogal slike.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Izvede zalivko, katere barva roba je določena s `$border`. Začetna točka za zapolnitev je `$x`, `$y` (levo zgoraj je 0, 0), območje pa je zapolnjeno z barvo `$color`. ([več |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Obrne sliko z uporabo danega `$mode`. ([več |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Besedilo v sliko zapišite s pisavami FreeType 2. ([več |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Napišite besedilo na sliko. ([več) |https://www.php.net/manual/en/function.imagefttext]
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Vrne širino slike.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Vklopi ali izklopi bit prepletanja. Če je nastavljen bit prepletanja in se slika uporablja kot slika JPEG, se slika ustvari kot progresivni JPEG. ([več |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Nastavite zastavico mešanja alfa, če želite uporabiti učinke plastenja. ([več |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Nariše črto med dvema danima točkama. ([več |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Na sliko nariše odprt poligon. V nasprotju s spletno stranjo `polygon()` med zadnjo in prvo točko ni potegnjena črta. ([več |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Kopira `$image` v sliko na koordinatah `$left` in `$top`. Koordinate lahko posredujete kot cela števila v pikslih ali kot nize v odstotkih (npr. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Ustvari poligon na sliki. ([več |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Ustvari pravokotnik, ki se začne na določenih koordinatah. ([več |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Ustvari pravokotnik na danih koordinatah.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Skaliranje slike, glejte [več informacij |#Image Resize]. Dimenzije lahko posredujete kot cela števila v pikslih ali kot nize v odstotkih (npr. `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Omogoča nastavitev in pridobitev ločljivosti slike v DPI (točkah na palec). Če ni podan nobeden od neobveznih parametrov, se trenutna ločljivost vrne kot indeksirano polje. Če je podan samo naslov `$resX`, se vodoravna in navpična ločljivost nastavita na to vrednost. Če sta podana oba neobvezna parametra, se vodoravna in navpična ločljivost nastavita na ti vrednosti.
 
 Ločljivost se kot meta informacija uporablja le pri branju slik iz formatov, ki podpirajo tovrstne informacije (trenutno sta to formata PNG in JPEG), in pri zapisovanju v te formate. To ne vpliva na nobeno risanje. Privzeta ločljivost novih slik je 96 DPI. ([več |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Obrne sliko z uporabo danega `$angle` v stopinjah. Središče vrtenja je središ
 Zahteva razširitev *Bundled GD extension*, zato ni gotovo, da bo delovala povsod.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Sliko shrani v datoteko.
 
-Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Če tip ni razviden iz končnice datoteke, ga lahko določite z eno od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`.
+Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Če vrsta ni razvidna iz končnice datoteke, jo lahko določite z eno od konstant `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Skalira sliko z uporabo danega algoritma interpolacije. ([več |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Izpiše sliko v brskalnik.
 
-Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Tip je ena od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`.
+Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Nastavi metodo interpolacije, ki vpliva na metodi `rotate()` in `affine()`. ([več |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Nariše piksel na določeni koordinati. ([več |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Nekoliko izostri sliko.
 Zahteva razširitev *Bundled GD extension*, zato ni gotovo, da bo delovala povsod.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Nariše niz na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Vertikalno nariše niz na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Izpiše sliko v niz.
 
-Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Tip je ena od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`.
+Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Pretvori sliko truecolor v sliko palete. ([več |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-V sliko zapiše podano besedilo z uporabo pisav TrueType. ([več |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+V sliko zapiše podano besedilo. ([več) |https://www.php.net/manual/en/function.imagettftext]
diff --git a/utils/sl/iterables.texy b/utils/sl/iterables.texy
new file mode 100644
index 0000000000..f396a6d65d
--- /dev/null
+++ b/utils/sl/iterables.texy
@@ -0,0 +1,170 @@
+Funkcije iteratorja
+*******************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] je statični razred s funkcijami za delo z iteratorji. Njegova ustreznica za polja je [Nette\Utils\Arrays |arrays].
+
+
+Namestitev:
+
+```shell
+composer require nette/utils
+```
+
+Vsi primeri predvidevajo, da je ustvarjen naslednji vzdevek:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Poišče določeno vrednost v iteratorju. Za preverjanje ujemanja uporablja strogo primerjavo (`===`). Če je vrednost najdena, vrne `true`, sicer `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Ta metoda je uporabna, kadar morate hitro ugotoviti, ali je določena vrednost prisotna v iteratorju, ne da bi ročno iterirali skozi vse elemente.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Poišče dani ključ v iteratorju. Za preverjanje ujemanja uporablja strogo primerjavo (`===`). Če je ključ najden, vrne `true`, sicer `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Preveri, ali vsi elementi iteratorja izpolnjujejo pogoj, opredeljen v `$predicate`. Funkcija `$predicate` ima podpis `function ($value, $key, iterable $iterable): bool` in mora vrniti `true` za vsak element, da metoda `every()` vrne `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Ta metoda je uporabna za preverjanje, ali vsi elementi v zbirki izpolnjujejo določen pogoj, na primer ali so vsa števila pod določeno vrednostjo.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Ustvari nov iterator, ki vsebuje samo elemente iz prvotnega iteratorja, ki izpolnjujejo pogoj, določen v `$predicate`. Funkcija `$predicate` ima podpis `function ($value, $key, iterable $iterable): bool` in mora vrniti `true` za elemente, ki jih je treba ohraniti.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Metoda uporablja generator, kar pomeni, da filtriranje poteka postopoma med iteracijo. To je pomnilniško učinkovito in omogoča obdelavo zelo velikih zbirk. Če ne iteriramo skozi vse elemente dobljenega iteratorja, prihranimo pri računskem naporu, saj niso obdelani vsi elementi prvotnega iteratorja.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Vrne prvi element iteratorja. Če je podan `$predicate`, vrne prvi element, ki izpolnjuje dani pogoj. Funkcija `$predicate` ima podpis `function ($value, $key, iterable $iterable): bool`. Če ni najden noben ustrezen element, se pokliče funkcija `$else` (če je zagotovljena) in vrne njen rezultat. Če funkcija `$else` ni navedena, se vrne `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Ta metoda je uporabna, kadar je treba hitro pridobiti prvi element zbirke ali prvi element, ki izpolnjuje določen pogoj, ne da bi ročno iterirali po celotni zbirki.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Vrne ključ prvega elementa iteratorja. Če je podan `$predicate`, vrne ključ prvega elementa, ki izpolnjuje dani pogoj. Funkcija `$predicate` ima podpis `function ($value, $key, iterable $iterable): bool`. Če ni najden noben ustrezen element, se pokliče funkcija `$else` (če je zagotovljena) in vrne njen rezultat. Če funkcija `$else` ni podana, se vrne `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Ustvari nov iterator z uporabo funkcije `$transformer` za vsak element prvotnega iteratorja. Funkcija `$transformer` ima podpis `function ($value, $key, iterable $iterable): mixed`, njena vrnjena vrednost pa se uporabi kot nova vrednost elementa.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Metoda uporablja generator, kar pomeni, da se preoblikovanje izvaja postopoma med iteracijo. To je pomnilniško učinkovito in omogoča obdelavo zelo velikih zbirk. Če ne iteriramo skozi vse elemente dobljenega iteratorja, prihranimo pri računskem naporu, saj niso obdelani vsi elementi prvotnega iteratorja.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Ustvari nov iterator s preoblikovanjem vrednosti in ključev prvotnega iteratorja. Funkcija `$transformer` ima podpis `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Če `$transformer` vrne `null`, se element preskoči. Pri ohranjenih elementih se prvi element vrnjenega polja uporabi kot novi ključ, drugi element pa kot nova vrednost.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Tako kot `map()` tudi ta metoda uporablja generator za postopno obdelavo in pomnilniško učinkovitost. To omogoča delo z velikimi zbirkami in prihranek računskega napora z obdelavo le dela rezultata.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Ustvari ovoj okoli iteratorja, ki med iteracijo predpomni njegove ključe in vrednosti. To omogoča ponavljajoče se iteracije nad podatki, ne da bi bilo treba ponovno obdelati izvirni vir podatkov.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Ta metoda je uporabna v primerih, ko je treba večkrat iterirati po istem nizu podatkov, vendar izvirni iterator ne podpira ponavljajoče se iteracije ali pa bi bila ponavljajoča se iteracija draga (npr. branje podatkov iz zbirke podatkov ali datoteke).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Preveri, ali vsaj en element iteratorja izpolnjuje pogoj, opredeljen v `$predicate`. Funkcija `$predicate` ima podpis `function ($value, $key, iterable $iterable): bool` in mora vrniti `true` za vsaj en element, da metoda `some()` vrne `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Ta metoda je uporabna za hitro preverjanje, ali je v zbirki vsaj en element, ki izpolnjuje določen pogoj, na primer ali zbirka vsebuje vsaj eno sodo število.
+
+Glejte [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Pretvori katerikoli objekt iterabla (polje, Traversable) v Iterator. Če je vhod že Iterator, se vrne nespremenjen.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Ta metoda je uporabna, kadar morate zagotoviti, da imate Iterator, ne glede na vrsto vhodnih podatkov. To je lahko koristno pri ustvarjanju funkcij, ki delajo z različnimi vrstami iterativnih podatkov.
diff --git a/utils/sl/json.texy b/utils/sl/json.texy
index 0ef442e444..8de57d8e49 100644
--- a/utils/sl/json.texy
+++ b/utils/sl/json.texy
@@ -77,7 +77,7 @@ Z nastavitvijo `$forceArray` se namesto objektov vrnejo polja:
 
 ```php
 Json::decode('{"variable": true}'); // vrne predmet tipa stdClass
-Json::decode('{"variable": true}', forceArray: true); // vrne polje
+Json::decode('{"variable": true}', forceArrays: true); // vrne polje
 ```
 
 Ob napaki vrže izjemo `Nette\Utils\JsonException`.
diff --git a/utils/sl/smartobject.texy b/utils/sl/smartobject.texy
index 212a575673..1045e03c54 100644
--- a/utils/sl/smartobject.texy
+++ b/utils/sl/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject in StaticClass
-**************************
+SmartObject
+***********
 
 .[perex]
-SmartObject razredom PHP doda podporo za *lastnosti*. StaticClass se uporablja za označevanje statičnih razredov.
+SmartObject je v preteklosti na različne načine popravljal obnašanje predmetov, vendar današnji PHP večino teh izboljšav že vključuje. Vendar pa še vedno dodaja podporo za *lastnost*.
 
 
 Namestitev:
@@ -65,31 +65,16 @@ echo $circle->visible; // pokliče isVisible()
 Lastnosti so predvsem "sintaktični sladkor"((sintactic sugar)), ki je namenjen temu, da programerju s poenostavitvijo kode osladi življenje. Če jih ne želite, vam jih ni treba uporabljati.
 
 
-Statični razredi .[#toc-static-classes]
-=======================================
+Pogled v zgodovino .[#toc-a-glimpse-into-history]
+=================================================
 
-Statične razrede, tj. razrede, ki niso namenjeni instanciranju, lahko označimo z lastnostjo `Nette\StaticClass`:
+SmartObject je v preteklosti na številne načine izboljševal obnašanje predmetov, vendar današnji PHP večino teh izboljšav že vključuje. Naslednje besedilo je nostalgičen pogled v zgodovino, ki nas spominja na razvoj stvari.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Pri poskusu ustvarjanja instance se vrže izjema `Error`, ki označuje, da je razred statičen.
-
-
-Pogled v zgodovino .[#toc-a-look-into-the-history]
-==================================================
-
-SmartObject je v preteklosti na različne načine izboljševal in popravljal obnašanje razredov, vendar je zaradi razvoja PHP večina prvotnih funkcij postala odveč. Zato je v nadaljevanju podan pogled v zgodovino, kako so se stvari razvijale.
-
-Objektni model PHP je že od začetka trpel zaradi številnih resnih pomanjkljivosti in neučinkovitosti. Zato je bil leta 2007 oblikovan razred `Nette\Object`, ki jih je poskušal odpraviti in izboljšati izkušnjo uporabe PHP. Dovolj je bilo, da so ga podedovali tudi drugi razredi in pridobili prednosti, ki jih je prinesel. Ko je PHP 5.4 začel podpirati lastnosti, je razred `Nette\Object` nadomestil razred `Nette\SmartObject`. Tako ni bilo več treba dedovati po skupnem predniku. Poleg tega je bilo trait mogoče uporabiti v razredih, ki so že dedovali od drugega razreda. Dokončni konec razreda `Nette\Object` se je zgodil z izdajo PHP 7.2, ki je prepovedal, da bi se razredi imenovali `Object`.
+Objektni model PHP je že od samega začetka trpel zaradi številnih resnih pomanjkljivosti in pomanjkljivosti. To je privedlo do oblikovanja razreda `Nette\Object` (leta 2007), katerega cilj je bil odpraviti te težave in povečati udobje pri uporabi PHP. Vse, kar je bilo potrebno, je bilo, da so drugi razredi podedovali razred in pridobili prednosti, ki jih je ponujal. Ko je PHP 5.4 uvedel podporo za lastnosti, je bil razred `Nette\Object` nadomeščen z lastnostjo `Nette\SmartObject`. S tem se je odpravila potreba po dedovanju od skupnega prednika. Poleg tega je bilo mogoče lastnost uporabiti v razredih, ki so že dedovali od drugega razreda. Dokončen konec `Nette\Object` se je zgodil z izdajo PHP 7.2, ki je prepovedal, da bi se razredi imenovali `Object`.
 
-Z nadaljnjim razvojem jezika PHP sta se izboljšala objektni model in zmožnosti jezika. Posamezne funkcije razreda `SmartObject` so postale nepotrebne. Od izdaje PHP 8.2 je ostala edina funkcija, ki še ni neposredno podprta v PHP, možnost uporabe tako imenovanih [lastnosti |#Properties, Getters and Setters].
+Z nadaljnjim razvojem PHP sta se izboljšala njegov objektni model in jezikovne zmožnosti. Različne funkcije razreda `SmartObject` so postale nepotrebne. Od izdaje PHP 8.2 je ostala le ena funkcija, ki ni neposredno podprta v PHP: možnost uporabe tako imenovanih [lastnosti |#Properties, getters, and setters].
 
-Katere funkcije sta nekoč ponujala razreda `Nette\Object` in `Nette\Object`? Tukaj je pregled. (Primeri uporabljajo razred `Nette\Object`, vendar večina lastnosti velja tudi za lastnost `Nette\SmartObject`.)
+Katere funkcije sta ponujala `Nette\Object` in posledično `Nette\SmartObject`? Tukaj je pregled. (V primerih je uporabljen razred `Nette\Object`, vendar večina lastnosti velja tudi za lastnost `Nette\SmartObject` ).
 
 
 Nedosledne napake .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Današnji PHP morda nima oblike "ali ste mislili?", vendar [Tracy |tracy:] napakam dodaja ta dodatek. In take napake lahko celo sam [popravi |tracy:open-files-in-ide#toc-demos].
+Čeprav današnji PHP nima funkcije "Ali ste mislili?", lahko [Tracy |tracy:] napakam doda ta stavek. [Takšne napake |tracy:open-files-in-ide#toc-demos] lahko celo [samodejno popravi |tracy:open-files-in-ide#toc-demos].
 
 
 Metode razširitve .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // vrne 'John Doe
+$reflection->getAnnotation('author'); // vrne 'John Doe'
 ```
 
 Od različice PHP 8.0 je mogoče dostopati do metainformacij v obliki atributov:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/sl/staticclass.texy b/utils/sl/staticclass.texy
new file mode 100644
index 0000000000..135be2a633
--- /dev/null
+++ b/utils/sl/staticclass.texy
@@ -0,0 +1,21 @@
+Statični razredi
+****************
+
+.[perex]
+StaticClass se uporablja za označevanje statičnih razredov.
+
+
+Namestitev:
+
+```shell
+composer require nette/utils
+```
+
+Statični razredi, tj. razredi, ki niso namenjeni instanciranju, so lahko označeni z lastnostjo [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/sl/strings.texy b/utils/sl/strings.texy
index 9289376977..48071c53af 100644
--- a/utils/sl/strings.texy
+++ b/utils/sl/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Spremeni niz UTF-8 v obliko, ki se uporablja v naslovu URL, tj. odstrani diakritiko in vse znake razen črk angleške abecede in številk nadomesti s pomišljajem.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 Zahteva razširitev PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Odstrani vse leve in desne presledke (ali znake, posredovane kot drugi argument) iz niza, kodiranega v UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Vrne del niza UTF-8, ki ga določata začetni položaj `$start` in dolžina `$length`. Če je `$start` negativen, se vrnjen niz začne pri `$start`'-tem znaku od konca niza.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Uporabite izvirni `str_contains()`:https://www.php.net/manual/en/function.str-contains.php.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Primerja dva niza UTF-8 ali njune dele, pri čemer ne upošteva velikosti znakov. Če je `$length` nič, se primerjajo celi nizi, če je negativen, se primerja ustrezno število znakov od konca niza, sicer se primerja ustrezno število znakov od začetka.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 V nizu poišče vse pojavitve, ki ustrezajo regularnemu izrazu, in vrne polje polj, ki vsebuje najden izraz in vsak podizraz.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Če je `$lazy` `true` , funkcija namesto polja vrne `Generator`, kar pri delu z velikimi nizi zagotavlja znatne prednosti pri delovanju. Generator omogoča postopno iskanje ujemanj, namesto da bi obdelal celoten niz naenkrat. To omogoča učinkovito obdelavo izjemno velikih vhodnih besedil. Poleg tega lahko obdelavo kadar koli prekinete, če najdete želeno ujemanje, s čimer prihranite računski čas.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/sl/validators.texy b/utils/sl/validators.texy
index 81f2b88709..dbcf38eb54 100644
--- a/utils/sl/validators.texy
+++ b/utils/sl/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Preveri, ali je element `$key` v polju `$array` iz [pričakovanih tipov |#expected types], ločenih s cevjo. V nasprotnem primeru vrže izjemo [api:Nette\Utils\AssertionException]. Niz `item '%' in array` v sporočilu o izjemi je mogoče nadomestiti s parametrom `$label`.
 
diff --git a/utils/tr/@home.texy b/utils/tr/@home.texy
index 45bc74103b..604e0ca525 100644
--- a/utils/tr/@home.texy
+++ b/utils/tr/@home.texy
@@ -13,13 +13,14 @@ Yardımcı Programlar
 | [Yardımcılar |helpers] | Nette\Utils\Helpers
 | [HTML Elemanları |HTML Elements] | Nette\Utils\Html
 | [Görüntüler |Images] | Nette\Utils\Image
+| [Iterables |iterables] | Nette\Utils\Iterables
 | [JSON |JSON] | Nette\Utils\Json
-| [Nesne modeli |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Paginator |paginator] | Nette\Utils\Paginator
 | [PHP |reflection] Yansıması | Nette\Utils\Reflection
 | [PHP Türleri |type] | Nette\Utils\Type
 | [Rastgele Dizeler |random] | Nette\Utils\Random
 | [Dizeler |Strings] | Nette\Utils\Strings
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [Doğrulayıcılar |validators] | Nette\Utils\Validators
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | sürüm | PHP ile uyumlu
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/tr/@left-menu.texy b/utils/tr/@left-menu.texy
index 738761e936..5874ca28a6 100644
--- a/utils/tr/@left-menu.texy
+++ b/utils/tr/@left-menu.texy
@@ -8,13 +8,15 @@ Paket nette/utils
 - [Yardımcılar |helpers]
 - [HTML Öğeleri |HTML Elements]
 - [Görüntüler |Images]
+- [Iterables |iterables]
 - [JSON |JSON]
 - [Paginator |paginator]
 - [Rastgele Dizeler |random]
-- [SmartObject |SmartObject]
 - [PHP Yansıması|reflection]
 - [Dizeler |Strings]
 - [Yüzer |Floats]
+- [SmartObject]
+- [StaticClass]
 - [PHP Türleri |type]
 - [Doğrulayıcılar |validators]
 
diff --git a/utils/tr/arrays.texy b/utils/tr/arrays.texy
index 85e7b2610d..6371a6ccde 100644
--- a/utils/tr/arrays.texy
+++ b/utils/tr/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Diziler .[#toc-arrays]
 ======================
 
-[api:Nette\Utils\Arrays] bir avuç kullanışlı dizi işlevi içeren statik bir sınıftır.
+[api:Nette\Utils\Arrays] bir avuç kullanışlı dizi işlevi içeren statik bir sınıftır. Yineleyiciler için karşılığı [Nette\Utils\Iterables' |iterables]dır.
 
 Aşağıdaki örneklerde, aşağıdaki sınıf takma adının tanımlandığı varsayılmaktadır:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+İşlev, `$array` adresini belirtilen yola göre esnek bir şekilde ilişkisel bir diziye veya nesnelere dönüştürür `$path`. Yol bir dize veya dizi olabilir. Girdi dizisindeki anahtarların adlarından ve '[]', '->', '=' ve '|' gibi operatörlerden oluşur. Yol geçersizse `Nette\InvalidArgumentException` adresini atar.
+
+```php
+// basit bir anahtar kullanarak ilişkisel bir diziye dönüştürme
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// = operatörünü kullanarak bir anahtardan diğerine değer atama
+$result = Arrays::associate($arr, 'name=age'); // veya ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// -> operatörünü kullanarak bir nesne oluşturma
+$result = Arrays::associate($arr, '->name'); // veya ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// | operatörünü kullanarak anahtarları birleştirme
+$result = Arrays::associate($arr, 'name|age'); // veya ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// [] kullanarak bir diziye ekleme
+$result = Arrays::associate($arr, 'name[]'); // veya ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,8 +76,8 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
 Dizideki tüm öğelerin, `function ($value, $key, array $array): bool` imzasına sahip olan sağlanan işlev tarafından uygulanan testi geçip geçmediğini sınar.
 
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 [some() |#some()] işlevine bakın.
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Verilen `$predicate` ile eşleşen tüm anahtar-değer çiftlerini içeren yeni bir dizi döndürür. Geri arama `function ($value, int|string $key, array $array): bool` imzasına sahiptir.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Dizideki ilk öğeyi veya dizi boşsa null döndürür. `reset()` adresinden farklı olarak dahili göstericiyi değiştirmez.
+İlk öğeyi döndürür (verilmişse belirtilen yüklemle eşleşen). Böyle bir öğe yoksa, `$else` çağrısının sonucunu veya null döndürür.
+ `$predicate`, `function ($value, int|string $key, array $array): bool` imzasına sahiptir.
+
+ `reset()` adresinden farklı olarak dahili işaretçiyi değiştirmez. `$predicate` ve `$else` parametreleri 4.0.4 sürümünden beri mevcuttur.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Bkz. [last() |#last()].
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+İlk öğenin anahtarını (verilmişse belirtilen yüklemle eşleşen) veya böyle bir öğe yoksa null döndürür. `$predicate` , `function ($value, int|string $key, array $array): bool` imzasına sahiptir.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+ [lastKey() |#lastKey()] işlevine bakın.
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Geri dönüşler `$array[$key]` öğesi. Eğer mevcut değilse, üçüncü bağımsız değişken olarak varsayılan bir değer ayarlanmadığı sürece `Nette\InvalidArgumentException` adresi atılır.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Son öğeyi döndürür (verilmişse belirtilen yüklemle eşleşen). Böyle bir öğe yoksa, `$else` çağrısının sonucunu veya null döndürür.
+ `$predicate`, `function ($value, int|string $key, array $array): bool` imzasına sahiptir.
+
+ `end()` adresinden farklı olarak dahili işaretçiyi değiştirmez. `$predicate` ve `$else` parametreleri 4.0.4 sürümünden beri mevcuttur.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+[First() |#first()] işlevine bakın.
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Dizideki son öğeyi veya dizi boşsa null döndürür. `end()` adresinden farklı olarak dahili göstericiyi değiştirmez.
+Son öğenin anahtarını (verilmişse belirtilen yüklemle eşleşen) veya böyle bir öğe yoksa null döndürür. `$predicate` , `function ($value, int|string $key, array $array): bool` imzasına sahiptir.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+ [firstKey() |#firstKey()] işlevine bakın.
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Dizideki tüm öğeler üzerinde `$callback` adresini çağırır ve dönüş değerleri dizisini döndürür. Geri arama `function ($value, $key, array $array): bool` imzasına sahiptir.
+Dizideki tüm öğeler üzerinde `$transformer` adresini çağırır ve dönüş değerleri dizisini döndürür. Geri arama `function ($value, $key, array $array): bool` imzasına sahiptir.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Orijinal dizinin değerlerini ve anahtarlarını dönüştürerek yeni bir dizi oluşturur. `$transformer` işlevi `function ($value, $key, array $array): ?array{$newValue, $newKey}` imzasına sahiptir. `$transformer` işlevi `null` döndürürse, eleman atlanır. Tutulan elemanlar için, döndürülen dizinin ilk elemanı yeni anahtar ve ikinci elemanı yeni değer olarak kullanılır.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Bu yöntem, bir dizinin yapısını (hem anahtarları hem de değerleri aynı anda) değiştirmeniz veya dönüştürme sırasında öğeleri filtrelemeniz (istenmeyen öğeler için null döndürerek) gereken durumlarda kullanışlıdır.
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 İkinci dizideki değerler her zaman birinciye eklenir. İkinci diziden `10` değerinin kaybolması biraz kafa karıştırıcı görünebilir. Bu değerin yanı sıra `5` in the first array have the same numeric key `0` değerinin de kaybolduğuna dikkat edilmelidir, bu nedenle ortaya çıkan alanda yalnızca ilk diziden bir öğe vardır.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Diziyi ilişkisel diziye normalleştirir. Sayısal anahtarları değerleriyle değiştirin, yeni değer `$filling` olacaktır.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Bir diziden bir öğenin değerini döndürür ve kaldırır. Mevcut değilse, bir istisna atar veya sağlanmışsa `$default` döndürür.
 
@@ -284,8 +397,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
 Dizideki en az bir öğenin `function ($value, $key, array $array): bool` imzasıyla sağlanan geri arama tarafından uygulanan testi geçip geçmediğini sınar.
 
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Dizinin her bir elemanını dizeye dönüştürür ve `$prefix` ve `$suffix` ile çevreler.
 
diff --git a/utils/tr/datetime.texy b/utils/tr/datetime.texy
index d764a9531f..aadf70a761 100644
--- a/utils/tr/datetime.texy
+++ b/utils/tr/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] işlevini, bir zaman dilimini dize olarak belirtme özelliğiyle genişletir.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create with custom timezone
diff --git a/utils/tr/filesystem.texy b/utils/tr/filesystem.texy
index 8ed0f75b1a..a5c5931d3e 100644
--- a/utils/tr/filesystem.texy
+++ b/utils/tr/filesystem.texy
@@ -2,9 +2,11 @@ Dosya Sistemi İşlevleri
 ***********************
 
 .[perex]
-[api:Nette\Utils\FileSystem] bir dosya sistemi ile çalışmak için yararlı işlevler içeren duruk bir sınıftır. Yerel PHP işlevlerine göre bir avantajı, hata durumunda istisnalar atmasıdır.
+[api:Nette\Utils\FileSystem] bir dosya sistemi ile çalışmak için yararlı işlevler içeren bir sınıftır. Yerel PHP işlevlerine göre bir avantajı, hata durumunda istisnalar atmasıdır.
 
 
+Diskte dosya aramanız gerekiyorsa [Finder |finder]'ı kullanın.
+
 Kurulum:
 
 ```shell
@@ -174,3 +176,26 @@ Eğik çizgileri geçerli platforma özgü karakterlere dönüştürür, yani Wi
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Statik ve Statik Olmayan Yaklaşım .[#toc-static-vs-non-static-approach]
+=======================================================================
+
+Örneğin test amacıyla `FileSystem` sınıfını başka bir sınıfla kolayca değiştirmek için, bunu statik olmayan bir şekilde kullanın:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/tr/finder.texy b/utils/tr/finder.texy
index cd5045c6fb..993fa5c76d 100644
--- a/utils/tr/finder.texy
+++ b/utils/tr/finder.texy
@@ -61,6 +61,8 @@ Statik yöntemlere bir alternatif de `new Finder` adresini kullanarak bir örnek
 
 [Joker karakter |#wildcards] leri `*`, `**` adresinde kullanabilirsiniz, `?` and `[...]` maske içinde. Dizinleri bile belirtebilirsiniz, örneğin `src/*.php`, `src` dizinindeki tüm PHP dosyalarını arayacaktır.
 
+Simbağlar da dizin veya dosya olarak kabul edilir.
+
 
 Nerede Arama Yapmalı? .[#toc-where-to-search]
 ---------------------------------------------
diff --git a/utils/tr/floats.texy b/utils/tr/floats.texy
index 44e716a09c..1ff07cc2d9 100644
--- a/utils/tr/floats.texy
+++ b/utils/tr/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 `NAN` adresini karşılaştırmaya çalışırken `\LogicException` istisnası atar.
 
+.[tip]
+`Floats` sınıfı `1e-10`'dan daha az farkları tolere eder. Daha fazla hassasiyetle çalışmanız gerekiyorsa, bunun yerine BCMath kütüphanesini kullanın.
+
 
 Şamandıra Karşılaştırması .[#toc-float-comparison]
 ==================================================
diff --git a/utils/tr/html-elements.texy b/utils/tr/html-elements.texy
index 1369029391..a8543649d9 100644
--- a/utils/tr/html-elements.texy
+++ b/utils/tr/html-elements.texy
@@ -219,9 +219,9 @@ $el = Html::el('span')
 Yeni bir `Html` düğümü oluşturmanın ve eklemenin başka bir yolu:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('hello');
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
 // <ul><li class="first">hello</li></ul>
 ```
 
diff --git a/utils/tr/images.texy b/utils/tr/images.texy
index c041d8ec49..9d4df34215 100644
--- a/utils/tr/images.texy
+++ b/utils/tr/images.texy
@@ -17,6 +17,8 @@ Aşağıdaki örneklerde, aşağıdaki sınıf takma adının tanımlandığı v
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 İsteğe bağlı olarak bir arka plan rengi belirtebilirsiniz (varsayılan renk siyahtır):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Ya da görüntüyü bir dosyadan yükleriz:
@@ -41,17 +43,6 @@ Ya da görüntüyü bir dosyadan yükleriz:
 $image = Image::fromFile('nette.jpg');
 ```
 
-Desteklenen formatlar JPEG, PNG, GIF, WebP, AVIF ve BMP'dir, ancak PHP sürümünüz de bunları desteklemelidir ( `phpinfo()`, GD bölümünü kontrol edin). Animasyonlar desteklenmez.
-
-Yükleme sırasında görüntü formatını tespit etmeniz mi gerekiyor? Yöntem, ikinci parametrede biçimi döndürür:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF veya Image::BMP ise
-```
-
-Sadece görüntü yüklenmeden algılama `Image::detectTypeFromFile()` tarafından yapılır.
-
 
 Görüntüyü Kaydet .[#toc-save-the-image]
 =======================================
@@ -68,25 +59,45 @@ Sıkıştırma kalitesini JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (
 $image->save('resampled.jpg', 80); // JPEG, kalite %80
 ```
 
-Format dosya uzantısından anlaşılmıyorsa, `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden biriyle belirtilebilir:
+Format dosya uzantısından anlaşılmıyorsa, [sabit |#Formats] ile belirtilebilir:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Görüntü disk yerine bir değişkene yazılabilir:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, kalite %80.
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, kalite %80.
 ```
 
 veya uygun HTTP başlığıyla doğrudan tarayıcıya gönderin `Content-Type`:
 
 ```php
 // başlık gönderir Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Formatlar .[#toc-formats]
+=========================
+
+Desteklenen biçimler JPEG, PNG, GIF, WebP, AVIF ve BMP'dir. Ancak, bunların PHP sürümünüz tarafından da destekleniyor olması gerekir; [isTypeSupported() |#isTypeSupported()] işlevi kullanılarak bu doğrulanabilir. Animasyonlar desteklenmez.
+
+Biçimler `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` ve `ImageType::BMP` sabitleri ile temsil edilir.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Yükleme sırasında bir görüntünün formatını tespit etmeniz mi gerekiyor? Yöntem bunu ikinci parametrede döndürür:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Görüntü yüklenmeden gerçek algılama `Image::detectTypeFromFile()` tarafından gerçekleştirilir.
+
 
 Görüntü Yeniden Boyutlandırma .[#toc-image-resize]
 ==================================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 `cropAuto()` yöntemi, `imagecropauto()` işlevinin bir nesne kapsüllemesidir, daha fazla bilgi için [belgelerine |https://www.php.net/manual/en/function.imagecropauto] bakın.
 
 
+Renkler .[#toc-colors]
+======================
+
+ `ImageColor::rgb()` yöntemi, kırmızı, yeşil ve mavi (RGB) değerlerini kullanarak bir renk tanımlamanıza olanak tanır. İsteğe bağlı olarak, CSS'de olduğu gibi 0 (tamamen saydam) ile 1 (tamamen opak) arasında değişen bir saydamlık değeri de belirtebilirsiniz.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+ `ImageColor::hex()` yöntemi, CSS'ye benzer şekilde onaltılık biçimi kullanarak bir renk tanımlamanıza olanak tanır. `#rgb` , `#rrggbb`, `#rgba` ve `#rrggbbaa` biçimlerini destekler:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Renkler `ellipse()`, `fill()`, vb. gibi diğer yöntemlerde de kullanılabilir.
+
+
 Çizim ve Düzenleme .[#toc-drawing-and-editing]
 ==============================================
 
-Çizebilir, yazabilir, [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php] gibi resimlerle çalışmak için tüm PHP işlevlerini kullanabilirsiniz, ancak nesne stilini kullanarak:
+Çizebilir, yazabilir, resim işleme için tüm PHP işlevlerini kullanabilirsiniz, bkz. [yöntemlere genel bakış |#Overview of methods], ancak nesne yönelimli bir sarmalayıcı içinde:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-[Yöntemlere Genel Bakış |#Overview of Methods] bölümüne bakınız.
+Dikdörtgen çizmek için PHP işlevleri koordinat belirtmek nedeniyle pratik olmadığından, `Image` sınıfı bunların yerine [rectangleWH() |#rectangleWH()] ve [filledRectangleWH() |#filledRectangleWH()] işlevlerini sunar.
 
 
 Birden Fazla Görüntüyü Birleştirme .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ Görüntünün içine kolayca başka bir görüntü yerleştirebilirsiniz:
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // koordinatlar yüzde olarak da ayarlanabilir
 $blank->place($logo, '80%', '80%'); // sağ alt köşeye yakın
@@ -219,53 +250,68 @@ Yöntemlere Genel Bakış .[#toc-overview-of-methods]
 ==================================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Verilen boyutlarda yeni bir gerçek renkli görüntü oluşturur. Varsayılan renk siyahtır.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Dosyadan bir görüntü okur ve türünü `$detectedFormat` olarak döndürür. Desteklenen türler `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP`'dir.
+Dosyadan bir görüntü okur ve [türünü |#Formats] `$detectedFormat` olarak döndürür.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Bir dizeden bir görüntü okur ve türünü `$detectedFormat` olarak döndürür. Desteklenen türler `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP`'dir.
+Bir dizeden bir görüntü okur ve [türünü |#Formats] `$detectedFormat` olarak döndürür.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-`ellipse()`, `fill()` gibi diğer yöntemlerde kullanılabilecek bir renk oluşturur.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Bu özellik `ImageColor` sınıfı ile değiştirilmiştir, bkz. [renkler |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Verilen `Image::XXX` sabiti için dosya uzantısını döndürür.
+Verilen [tür |#Formats] için dosya uzantısını döndürür.
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Verilen `Image::XXX` sabiti için mime türünü döndürür.
+Verilen [tür |#Formats] için mime türünü döndürür.
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Dosya uzantısına göre görüntü türünü sabit `Image::XXX` olarak döndürür.
+Dosya uzantısına göre görüntü [türünü |#Formats] döndürür.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Görüntü dosyasının türünü `Image::XXX` sabiti olarak ve `$width` ve `$height` parametrelerinde de boyutlarını döndürür.
+Görüntü dosyasının [türünü |#Formats] ve `$width` ve `$height` parametrelerinde de boyutlarını döndürür.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Resmin türünü dizeden `Image::XXX` sabiti olarak ve `$width` ve `$height` parametrelerinde de boyutlarını döndürür.
+Dizeden görüntünün [türünü |#Formats] ve `$width` ve `$height` parametrelerinden de boyutlarını döndürür.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Verilen görüntü [türünün |#Formats] desteklenip desteklenmediğini belirler.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Desteklenen görüntü türlerinin bir dizisini döndürür (sabitler `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Metni belirtilen yazı tipi ve boyutta çevreleyen dikdörtgenin boyutlarını hesaplar. `left` , `top`, `width`, `height` anahtarlarını içeren bir ilişkisel dizi döndürür. Metin sola doğru bir çıkıntıyla başlıyorsa, sol kenar boşluğu negatif olabilir.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 İsteğe bağlı bir kırpma alanı kullanarak, afin dönüşümü yapılmış src görüntüsünü içeren bir görüntü döndürür. ([daha fazla |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 İki afin dönüşüm matrisinin birleştirilmesini döndürür; bu, aynı görüntüye tek seferde birden fazla dönüşüm uygulanması gerektiğinde kullanışlıdır. ([daha fazla |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Bir afin dönüşüm matrisi döndürür. ([daha fazla |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ antialias(bool $on): void .[method]
 Şeffaf arka plan rengiyle kenar yumuşatılmış ilkel öğelerin kullanılması bazı beklenmedik sonuçlara yol açabilir. Karışım yöntemi, arka plan rengini diğer renkler gibi kullanır. Alfa bileşeni desteğinin olmaması, alfa tabanlı bir kenar yumuşatma yöntemine izin vermez. ([daha fazla |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Verilen koordinatları merkez alan bir daire yayı çizer. ([daha fazla |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Görüntüdeki `$char` öğesinin ilk karakterini sol üst köşesi `$x`,`$y` (sol üst köşesi 0, 0) olacak şekilde `$color` rengiyle çizer. ([daha fazla |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Verilen görüntü üzerinde belirtilen koordinatta `$char` karakterini dikey olarak çizer. ([daha fazla |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Verilen RGB bileşenlerinden oluşan rengi temsil eden bir renk tanımlayıcısı döndürür. Görüntüde kullanılacak her bir rengi oluşturmak için çağrılmalıdır. ([daha fazla |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Bir görüntü paletindeki renk sayısını döndürür ([daha fazla |https://www.php.net/manual/en/function.imagecolorstotal]).
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Görüntüdeki saydam rengi alır veya ayarlar. ([daha fazla |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Bir görüntüyü verilen dikdörtgen alana kırpar. Boyutlar piksel cinsinden tamsayılar veya yüzde cinsinden dizeler olarak aktarılabilir (örn. `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Bir görüntüyü verilen `$mode` adresine göre otomatik olarak kırpar. ([daha fazla |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Belirtilen koordinatlarda ortalanmış bir elips çizer. ([daha fazla |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Verilen koordinattan başlayarak (sol üst 0, 0'dır) görüntüde verilen `$color` ile bir sel dolgusu gerçekleştirir. ([daha fazla |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Görüntüde belirtilen koordinatı merkez alan kısmi bir yay çizer. ([daha fazla |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Görüntüde belirtilen koordinatı merkez alan bir elips çizer. ([daha fazla |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Resim içinde dolu bir çokgen oluşturur. ([daha fazla |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Görüntüde 1 noktasından başlayıp 2 noktasında biten `$color` ile doldurulmuş bir dikdörtgen oluşturur. 0, 0 görüntünün sol üst köşesidir. ([daha fazla |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Görüntüde `$x1` & `$y1` adresinden başlayıp `$x2` & `$y2` adresinde biten `$color` ile doldurulmuş bir dikdörtgen oluşturur. 0, 0 noktası görüntünün sol üst köşesidir. ([daha fazla |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Görüntüde `$left` & `$top` noktasından başlayarak genişliği `$width` ve yüksekliği `$height` olan `$color` ile doldurulmuş bir dikdörtgen oluşturur. 0, 0 noktası görüntünün sol üst köşesidir.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Kenarlık rengi `$border` tarafından tanımlanan bir taşma dolgusu gerçekleştirir. Dolgu için başlangıç noktası `$x`, `$y` (sol üst 0, 0'dır) ve bölge `$color` rengi ile doldurulur. ([daha fazla |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Verilen `$mode` adresini kullanarak görüntüyü çevirir. ([daha fazla |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-FreeType 2 kullanan yazı tiplerini kullanarak görüntüye metin yazın. ([daha fazla |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Resimdeki metni yazın. ([daha fazla |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Görüntünün genişliğini döndürür.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Geçiş bitini açar veya kapatır. Geçiş biti ayarlanmışsa ve görüntü bir JPEG görüntüsü olarak kullanılıyorsa, görüntü aşamalı bir JPEG olarak oluşturulur. ([daha fazla |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Katmanlama efektlerini kullanmak için alfa karıştırma bayrağını ayarlayın. ([daha fazla |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Verilen iki nokta arasında bir çizgi çizer. ([daha fazla |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Görüntü üzerine açık bir çokgen çizer. `polygon()` 'un aksine, son nokta ile ilk nokta arasında bir çizgi çizilmez. ([daha fazla |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 `$image` adresini `$left` ve `$top` koordinatlarındaki görüntüye kopyalar. Koordinatlar piksel cinsinden tamsayılar veya yüzde cinsinden dizeler olarak aktarılabilir (örn. `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Görüntüde bir çokgen oluşturur. ([daha fazla |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Belirtilen koordinatlardan başlayan bir dikdörtgen oluşturur. ([daha fazla |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Verilen koordinatlarda bir dikdörtgen oluşturur.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Bir görüntüyü ölçeklendirir, [daha fazla bilgi |#Image Resize] için bkz. Boyutlar piksel cinsinden tamsayılar veya yüzde cinsinden dizeler olarak aktarılabilir (örn. `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 DPI (inç başına nokta) cinsinden bir görüntünün çözünürlüğünü ayarlamaya ve almaya izin verir. İsteğe bağlı parametrelerden hiçbiri verilmezse, geçerli çözünürlük indeksli dizi olarak döndürülür. Yalnızca `$resX` adresi verilirse, yatay ve dikey çözünürlük bu değere ayarlanır. Her iki isteğe bağlı parametre de verilirse, yatay ve dikey çözünürlük sırasıyla bu değerlere ayarlanır.
 
 Çözünürlük yalnızca görüntüler bu tür bilgileri destekleyen formatlardan (şu anda PNG ve JPEG) okunduğunda ve bu formatlara yazıldığında meta bilgi olarak kullanılır. Herhangi bir çizim işlemini etkilemez. Yeni görüntüler için varsayılan çözünürlük 96 DPI'dır. ([daha fazla |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ Verilen `$angle` adresini derece cinsinden kullanarak görüntüyü döndürür.
 Paketlenmiş GD uzantısı* gerektirir, bu nedenle her yerde çalışacağından emin değildir.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Bir görüntüyü bir dosyaya kaydeder.
 
-Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Dosya uzantısından tür belli değilse, `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden birini kullanarak belirtebilirsiniz.
+Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Tür dosya uzantısından anlaşılmıyorsa, `ImageType` sabitlerinden birini kullanarak belirtebilirsiniz.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Verilen enterpolasyon algoritmasını kullanarak bir görüntüyü ölçeklendirir. ([daha fazla |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Tarayıcıya bir görüntü çıktısı verir.
 
-Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Tip `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden biridir.
+Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır.
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 `rotate()` ve `affine()` yöntemlerini etkileyen enterpolasyon yöntemini ayarlar. ([daha fazla |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Belirtilen koordinatta bir piksel çizer. ([devamı |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ Görüntüyü biraz keskinleştirir.
 Paketlenmiş GD uzantısı* gerektirir, bu nedenle her yerde çalışacağından emin değiliz.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Verilen koordinatlarda bir dize çizer. ([daha fazla |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Verilen koordinatlarda dikey olarak bir dize çizer. ([daha fazla |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Bir görüntüyü dizeye çıktı olarak verir.
 
-Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Tip `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden biridir.
+Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır.
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Bir gerçek renkli görüntüyü bir palet görüntüsüne dönüştürür. ([daha fazla |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-TrueType yazı tiplerini kullanarak verilen metni görüntüye yazar. ([daha fazla |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Verilen metni resmin içine yazar. ([daha fazla |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/tr/iterables.texy b/utils/tr/iterables.texy
new file mode 100644
index 0000000000..41a1427d08
--- /dev/null
+++ b/utils/tr/iterables.texy
@@ -0,0 +1,170 @@
+Yineleyici İşlevleri
+********************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] yineleyicilerle çalışmak için işlevler içeren statik bir sınıftır. Diziler için karşılığı [Nette\Utils\Arrays' |arrays]dir.
+
+
+Kurulum:
+
+```shell
+composer require nette/utils
+```
+
+Tüm örnekler aşağıdaki takma adın oluşturulduğunu varsayar:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Bir yineleyici içinde verilen bir değeri arar. Bir eşleşme olup olmadığını kontrol etmek için katı karşılaştırma (`===`) kullanır. Değer bulunursa `true`, aksi takdirde `false` döndürür.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Bu yöntem, tüm öğeleri manuel olarak yinelemeden bir yineleyicide belirli bir değerin bulunup bulunmadığını hızlı bir şekilde belirlemeniz gerektiğinde kullanışlıdır.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Bir yineleyici içinde verilen bir anahtarı arar. Bir eşleşme olup olmadığını kontrol etmek için katı karşılaştırma (`===`) kullanır. Anahtar bulunursa `true`, aksi takdirde `false` döndürür.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Yineleyicinin tüm öğelerinin `$predicate` içinde tanımlanan koşulu sağlayıp sağlamadığını kontrol eder. `$predicate` işlevi `function ($value, $key, iterable $iterable): bool` imzasına sahiptir ve `every()` yönteminin `true` döndürmesi için her öğe için `true` döndürmelidir.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Bu yöntem, bir koleksiyondaki tüm öğelerin, tüm sayıların belirli bir değerin altında olup olmadığı gibi belirli bir koşulu karşıladığını doğrulamak için kullanışlıdır.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Orijinal yineleyiciden yalnızca `$predicate` adresinde tanımlanan koşulu sağlayan öğeleri içeren yeni bir yineleyici oluşturur. `$predicate` işlevi `function ($value, $key, iterable $iterable): bool` imzasına sahiptir ve tutulması gereken öğeler için `true` döndürmelidir.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Yöntem bir üreteç kullanır, yani filtreleme yineleme sırasında artımlı olarak gerçekleşir. Bu, bellek açısından verimlidir ve çok büyük koleksiyonların işlenmesine olanak sağlar. Elde edilen yineleyicinin tüm öğeleri boyunca yineleme yapmazsanız, orijinal yineleyicinin tüm öğeleri işlenmediğinden hesaplama çabasından tasarruf edersiniz.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Yineleyicinin ilk öğesini döndürür. `$predicate` sağlanmışsa, verilen koşulu karşılayan ilk öğeyi döndürür. `$predicate` işlevi `function ($value, $key, iterable $iterable): bool` imzasına sahiptir. Eşleşen bir öğe bulunamazsa, `$else` işlevi (sağlanmışsa) çağrılır ve sonucu döndürülür. `$else` sağlanmamışsa, `null` döndürülür.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Bu yöntem, bir koleksiyonun ilk öğesini veya belirli bir koşulu karşılayan ilk öğeyi, tüm koleksiyonda manuel olarak yinelemeden hızlı bir şekilde almanız gerektiğinde kullanışlıdır.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Yineleyicinin ilk öğesinin anahtarını döndürür. `$predicate` sağlanmışsa, verilen koşulu karşılayan ilk öğenin anahtarını döndürür. `$predicate` işlevi `function ($value, $key, iterable $iterable): bool` imzasına sahiptir. Eşleşen bir öğe bulunamazsa, `$else` işlevi (sağlanmışsa) çağrılır ve sonucu döndürülür. `$else` sağlanmamışsa, `null` döndürülür.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Orijinal yineleyicinin her bir öğesine `$transformer` işlevini uygulayarak yeni bir yineleyici oluşturur. `$transformer` işlevi `function ($value, $key, iterable $iterable): mixed` imzasına sahiptir ve geri dönüş değeri öğenin yeni değeri olarak kullanılır.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Yöntem bir üreteç kullanır, yani dönüşüm yineleme sırasında artımlı olarak gerçekleşir. Bu, bellek açısından verimlidir ve çok büyük koleksiyonların işlenmesine olanak sağlar. Elde edilen yineleyicinin tüm öğeleri boyunca yineleme yapmazsanız, orijinal yineleyicinin tüm öğeleri işlenmediğinden hesaplama çabasından tasarruf edersiniz.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Orijinal yineleyicinin değerlerini ve anahtarlarını dönüştürerek yeni bir yineleyici oluşturur. `$transformer` işlevi `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}` imzasına sahiptir. `$transformer` , `null` döndürürse, öğe atlanır. Tutulan elemanlar için, döndürülen dizinin ilk elemanı yeni anahtar ve ikinci elemanı yeni değer olarak kullanılır.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+ `map()` gibi, bu yöntem de artımlı işleme ve bellek verimliliği için bir üreteç kullanır. Bu, büyük koleksiyonlarla çalışmaya ve sonucun yalnızca bir kısmını işleyerek hesaplama çabasından tasarruf etmeye olanak tanır.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Yineleme sırasında anahtarlarını ve değerlerini önbelleğe alan bir yineleyici etrafında bir sarmalayıcı oluşturur. Bu, orijinal veri kaynağını yeniden işlemek zorunda kalmadan veriler üzerinde tekrarlanan yinelemelere olanak tanır.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Bu yöntem, aynı veri kümesi üzerinde birden çok kez yineleme yapmanız gereken, ancak orijinal yineleyicinin yinelemeyi desteklemediği veya yinelemenin maliyetli olacağı durumlarda (örneğin, bir veritabanından veya dosyadan veri okuma) kullanışlıdır.
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Yineleyicinin en az bir öğesinin `$predicate` içinde tanımlanan koşulu sağlayıp sağlamadığını kontrol eder. `$predicate` işlevi `function ($value, $key, iterable $iterable): bool` imzasına sahiptir ve `some()` yönteminin `true` döndürmesi için en az bir öğe için `true` döndürmelidir.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Bu yöntem, bir koleksiyonda belirli bir koşulu karşılayan en az bir öğe olup olmadığını (örneğin, koleksiyonun en az bir çift sayı içerip içermediğini) hızlı bir şekilde doğrulamak için kullanışlıdır.
+
+Bkz. [every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Herhangi bir yinelenebilir nesneyi (dizi, Traversable) bir Iterator'a dönüştürür. Girdi zaten bir Iterator ise, değişmeden döndürülür.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Bu yöntem, girdi veri türünden bağımsız olarak bir Yineleyiciniz olduğundan emin olmanız gerektiğinde kullanışlıdır. Bu, farklı yinelenebilir veri türleriyle çalışan fonksiyonlar oluştururken faydalı olabilir.
diff --git a/utils/tr/json.texy b/utils/tr/json.texy
index 404b3a4601..c5302f4104 100644
--- a/utils/tr/json.texy
+++ b/utils/tr/json.texy
@@ -77,7 +77,7 @@ JSON'u PHP'ye ayrıştırır.
 
 ```php
 Json::decode('{"variable": true}'); // stdClass türünde bir nesne döndürür
-Json::decode('{"variable": true}', forceArray: true); // bir dizi döndürür
+Json::decode('{"variable": true}', forceArrays: true); // bir dizi döndürür
 ```
 
 Hata durumunda bir `Nette\Utils\JsonException` istisnası atar.
diff --git a/utils/tr/smartobject.texy b/utils/tr/smartobject.texy
index 41a488dbaa..b08dcbca57 100644
--- a/utils/tr/smartobject.texy
+++ b/utils/tr/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject ve StaticClass
-**************************
+SmartObject
+***********
 
 .[perex]
-SmartObject PHP sınıflarına *property* desteği ekler. StaticClass statik sınıfları belirtmek için kullanılır.
+SmartObject nesnelerin davranışını birçok yönden düzeltirdi, ancak günümüz PHP'si bu iyileştirmelerin çoğunu zaten yerel olarak içermektedir. Bununla birlikte, hala *property* için destek ekler.
 
 
 Kurulum:
@@ -65,31 +65,16 @@ echo $circle->visible; // isVisible() işlevini çağırır
 Özellikler öncelikle "sözdizimsel şeker"((syntactic sugar)) olup, kodu basitleştirerek programcının hayatını daha tatlı hale getirmeyi amaçlar. Eğer onları istemiyorsanız, kullanmak zorunda değilsiniz.
 
 
-Statik Sınıflar .[#toc-static-classes]
-======================================
+Tarihe Bir Bakış .[#toc-a-glimpse-into-history]
+===============================================
 
-Statik sınıflar, yani örneklenmesi amaçlanmayan sınıflar, `Nette\StaticClass` özelliği ile işaretlenebilir:
+SmartObject, nesnelerin davranışlarını çeşitli şekillerde iyileştirmek için kullanılırdı, ancak bugünün PHP'si bu geliştirmelerin çoğunu zaten yerel olarak içeriyor. Aşağıdaki metin geçmişe nostaljik bir bakıştır ve bize işlerin nasıl geliştiğini hatırlatır.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Bir örnek oluşturmaya çalıştığınızda, sınıfın statik olduğunu belirten `Error` istisnası atılır.
-
-
-Tarihe Bir Bakış .[#toc-a-look-into-the-history]
-================================================
-
-SmartObject eskiden sınıf davranışını birçok yönden geliştirir ve düzeltirdi, ancak PHP'nin evrimi orijinal özelliklerin çoğunu gereksiz hale getirdi. Bu nedenle aşağıda, işlerin nasıl geliştiğinin geçmişine bir bakış yer almaktadır.
-
-PHP nesne modeli en başından beri bir dizi ciddi kusur ve verimsizlikten muzdaripti. Bu eksiklikleri gidermeye ve PHP kullanım deneyimini iyileştirmeye çalışan `Nette\Object` sınıfının (2007'de) yaratılmasının nedeni buydu. Diğer sınıfların bu sınıftan miras alması ve sağladığı avantajlardan yararlanması için yeterliydi. PHP 5.4 trait desteği ile geldiğinde, `Nette\Object` sınıfı `Nette\SmartObject` ile değiştirildi. Böylece artık ortak bir atadan miras almaya gerek kalmamıştı. Ayrıca, trait zaten başka bir sınıftan miras alan sınıflarda da kullanılabiliyordu. `Nette\Object` 'un nihai sonu, sınıfların `Object` olarak adlandırılmasını yasaklayan PHP 7.2 sürümüyle geldi.
+PHP'nin nesne modeli, başlangıcından itibaren sayısız ciddi eksiklik ve yetersizlikten muzdaripti. Bu durum, bu sorunları gidermeyi ve PHP'nin kullanım rahatlığını artırmayı amaçlayan `Nette\Object` sınıfının (2007'de) oluşturulmasına yol açtı. İhtiyaç duyulan tek şey diğer sınıfların bu sınıftan miras almasıydı ve onlar da bu sınıfın sunduğu avantajlardan yararlanabileceklerdi. PHP 5.4 özellikler için destek sunduğunda, `Nette\Object` sınıfının yerini `Nette\SmartObject` özelliği aldı. Bu, ortak bir atadan miras alma ihtiyacını ortadan kaldırdı. Dahası, özellik zaten başka bir sınıftan miras alan sınıflarda kullanılabiliyordu. `Nette\Object` 'un kesin sonu, sınıfların `Object` olarak adlandırılmasını yasaklayan PHP 7.2'nin yayınlanmasıyla geldi.
 
-PHP'nin gelişimi devam ettikçe, nesne modeli ve dil yetenekleri geliştirildi. `SmartObject` sınıfının bireysel işlevleri gereksiz hale geldi. PHP 8.2'nin yayınlanmasından bu yana, PHP'de henüz doğrudan desteklenmeyen tek özellik, sözde [özellikleri |#Properties, Getters and Setters] kullanma yeteneğidir.
+PHP'nin gelişimi devam ettikçe, nesne modeli ve dil yetenekleri de gelişti. `SmartObject` sınıfının çeşitli işlevleri gereksiz hale geldi. PHP 8.2'nin yayınlanmasından bu yana, PHP'de doğrudan desteklenmeyen tek bir özellik kaldı: sözde [özellikleri |#Properties, getters, and setters] kullanma yeteneği.
 
-`Nette\Object` ve `Nette\Object` bir zamanlar hangi özellikleri sunuyordu? İşte genel bir bakış. (Örnekler `Nette\Object` sınıfını kullanmaktadır, ancak özelliklerin çoğu `Nette\SmartObject` özelliği için de geçerlidir).
+ `Nette\Object` ve buna bağlı olarak `Nette\SmartObject` hangi özellikleri sunuyordu? İşte genel bir bakış. (Örneklerde `Nette\Object` sınıfı kullanılmıştır, ancak çoğu özellik `Nette\SmartObject` özelliği için de geçerlidir).
 
 
 Tutarsız Hatalar .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Günümüz PHP'sinde "demek istediniz mi?" gibi bir ifade bulunmayabilir, ancak [Tracy |tracy:] hatalara bu eki ekler. Ve bu tür hataları kendisi bile [düzeltebilir |tracy:open-files-in-ide#toc-demos].
+Günümüz PHP'sinde "demek istediniz mi?" özelliği olmasa da, bu ifade [Tracy |tracy:] tarafından hatalara eklenebilir. Hatta bu [tür hataları otomatik olarak düzeltebilir |tracy:open-files-in-ide#toc-demos].
 
 
 Uzatma yöntemleri .[#toc-extension-methods]
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/tr/staticclass.texy b/utils/tr/staticclass.texy
new file mode 100644
index 0000000000..15fc8950d6
--- /dev/null
+++ b/utils/tr/staticclass.texy
@@ -0,0 +1,21 @@
+Statik Sınıflar
+***************
+
+.[perex]
+StaticClass statik sınıfları belirtmek için kullanılır.
+
+
+Kurulum:
+
+```shell
+composer require nette/utils
+```
+
+Statik sınıflar, yani örneklenmesi amaçlanmayan sınıflar, [api:Nette\StaticClass] özelliği ile işaretlenebilir:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/tr/strings.texy b/utils/tr/strings.texy
index 43579b10ed..179a1c0e41 100644
--- a/utils/tr/strings.texy
+++ b/utils/tr/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 UTF-8 dizesini URL'de kullanılan biçime dönüştürür, yani aksan işaretlerini kaldırır ve İngilizce alfabenin harfleri ve sayılar dışındaki tüm karakterleri tire ile değiştirir.
 
@@ -129,8 +129,8 @@ Strings::webalize('Hello world', null, false); // 'Hello-world'
 PHP uzantısı gerektirir `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 UTF-8 kodlu bir dizeden sol ve sağ taraftaki tüm boşlukları (veya ikinci bağımsız değişken olarak aktarılan karakterleri) kaldırır.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Başlangıç konumu `$start` ve uzunluğu `$length` ile belirtilen UTF-8 dizesinin bir bölümünü döndürür. `$start` negatifse, döndürülen dize dizenin sonundan itibaren `$start`'inci karakterden başlar.
 
@@ -266,8 +266,8 @@ Strings::contains($haystack, $needle); // true
 Yerel `str_contains()`:https://www.php.net/manual/en/function.str-contains.php adresini kullanın.
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Karakter durumunu dikkate almadan iki UTF-8 dizgisini veya parçalarını karşılaştırır. `$length` boşsa, tüm dizgiler karşılaştırılır, negatifse, dizgilerin sonundan itibaren karşılık gelen karakter sayısı karşılaştırılır, aksi takdirde başlangıçtan itibaren uygun karakter sayısı karşılaştırılır.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Dizeyi, düzenli ifadeyle eşleşen tüm oluşumlar için arar ve bulunan ifadeyi ve her bir alt ifadeyi içeren bir dizi dizisi döndürür.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Eğer `$lazy` `true` ise, fonksiyon bir dizi yerine bir `Generator` döndürür, bu da büyük dizelerle çalışırken önemli performans avantajları sağlar. Üreteç, tüm dizeyi bir kerede işlemek yerine eşleşmelerin artımlı olarak bulunmasına olanak tanır. Bu, son derece büyük girdi metinlerinin verimli bir şekilde işlenmesini sağlar. Ayrıca, istediğiniz eşleşmeyi bulduğunuzda işlemeyi istediğiniz zaman kesebilir ve hesaplama süresinden tasarruf edebilirsiniz.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/tr/validators.texy b/utils/tr/validators.texy
index 37daf1a341..72957fef95 100644
--- a/utils/tr/validators.texy
+++ b/utils/tr/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 `$array` dizisindeki `$key` öğesinin boru ile ayrılmış [beklenen türlerden |#expected types] olduğunu doğrular. Değilse, [api:Nette\Utils\AssertionException] istisnasını atar. İstisna mesajındaki `item '%' in array` dizesi `$label` parametresi ile değiştirilebilir.
 
diff --git a/utils/uk/@home.texy b/utils/uk/@home.texy
index da37bd7e7d..1189910bc7 100644
--- a/utils/uk/@home.texy
+++ b/utils/uk/@home.texy
@@ -11,15 +11,16 @@
 | [Генерація випадкових рядків |random] | Nette\Utils\Random
 | [Дата і час |datetime] | Nette\Utils\DateTime
 | [Зображення |images] | Nette\Utils\Image
-| [Модель об'єкта |smartobject] | Nette\SmartObject & Nette\StaticClass
 | [Пагінація |paginator] | Nette\Utils\Paginator
 | [Парсинг і генерація JSON |json] | Nette\Utils\Json
+| [Змінні |iterables] | Nette\Utils\Iterables
 | [Поле |arrays] | Nette\Utils\Arrays
 | [Рядки |strings] | Nette\Utils\Strings
 | [Типи |type] | Nette\Utils\Type
 | [Файлова система |filesystem] | Nette\Utils\FileSystem
 | [Функції-помічники |helpers] | Nette\Utils\Helpers
 | [Елементи HTML |html-elements] | Nette\Utils\Html
+| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass
 | [PHP Відображення |reflection] | Nette\Utils\Reflection
 
 
@@ -34,8 +35,8 @@ composer require nette/utils
 
 | Версія, сумісна з PHP
 |-----------|-------------------
-| Nette Utils 4.0 | PHP 8.0 - 8.2
-| Nette Utils 3.2 | PHP 7.2 - 8.2
+| Nette Utils 4.0 | PHP 8.0 – 8.4
+| Nette Utils 3.2 | PHP 7.2 – 8.3
 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0
 | Nette Utils 2.5 | PHP 5.6 - 8.0
 
diff --git a/utils/uk/@left-menu.texy b/utils/uk/@left-menu.texy
index 6f4022e2d2..66d73a31c6 100644
--- a/utils/uk/@left-menu.texy
+++ b/utils/uk/@left-menu.texy
@@ -8,6 +8,7 @@
 - [Зображення |images]
 - [Зворотні виклики |callback]
 - [Пагінатор |paginator]
+- [Ітерабельні змінні |iterables]
 - [Поле |arrays]
 - [Випадкові рядки |random]
 - [Рядки |strings]
@@ -15,8 +16,9 @@
 - [Файлова система |filesystem]
 - [Функції-помічники |helpers]
 - [Елементи HTML |html-elements]
+- [SmartObject]
+- [StaticClass]
 - [PHP Відображення |reflection]
-- [SmartObject |smartobject]
 
 
 Інші інструменти
diff --git a/utils/uk/arrays.texy b/utils/uk/arrays.texy
index 52b1e384ab..e13c8e2313 100644
--- a/utils/uk/arrays.texy
+++ b/utils/uk/arrays.texy
@@ -15,7 +15,7 @@ composer require nette/utils
 Масиви .[#toc-arrays]
 =====================
 
-[api:Nette\Utils\Arrays] це статичний клас, що містить корисні функції для роботи з масивами.
+[api:Nette\Utils\Arrays] це статичний клас, який містить декілька зручних функцій для роботи з масивами. Його еквівалентом для ітераторів є [Nette\Utils\Iterables |iterables].
 
 У наступних прикладах передбачається, що псевдонім уже створено:
 
@@ -24,6 +24,47 @@ use Nette\Utils\Arrays;
 ```
 
 
+associate(array $array, mixed $path): array|\stdClass .[method]
+---------------------------------------------------------------
+
+Функція гнучко перетворює `$array` в асоціативний масив або об'єкти за вказаним шляхом `$path`. Шлях може бути рядком або масивом. Він складається з імен ключів у вхідному масиві та операторів '[]', '->', '=' і '|'. Якщо шлях невірний, то генерується `Nette\InvalidArgumentException`.
+
+```php
+// перетворення в асоціативний масив з допомогою простого ключа
+$arr = [
+    ['name' => 'John', 'age' => 11],
+    ['name' => 'Mary', 'age' => null],
+    //...
+];
+$result = Arrays::associate($arr, 'name');
+// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// присвоювання значень від одного ключа до іншого за допомогою оператора =
+$result = Arrays::associate($arr, 'name=age'); // або ['name', '=', 'age']
+// $result = ['John' => 11, 'Mary' => null, ...]
+```
+
+```php
+// створення об'єкту з допомогою оператора ->
+$result = Arrays::associate($arr, '->name'); // або ['->', 'name']
+// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
+```
+
+```php
+// об'єднання ключів за допомогою оператора | або
+$result = Arrays::associate($arr, 'name|age'); // або ['name', '|', 'age']
+// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
+```
+
+```php
+// додавання до масиву з використанням [] або []
+$result = Arrays::associate($arr, 'name[]'); // або ['name', '[]']
+// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
+```
+
+
 contains(array $array, $value): bool .[method]
 ----------------------------------------------
 
@@ -35,10 +76,10 @@ Arrays::contains(['1', false], 1); // false
 ```
 
 
-every(iterable $array, callable $callback): bool .[method]
-----------------------------------------------------------
+every(array $array, callable $predicate): bool .[method]
+--------------------------------------------------------
 
-Перевіряє, чи всі елементи в масиві проходять тест, реалізований у `$callback` з сигнатурою `function ($value, $key, array $array): bool`.
+Перевіряє, чи всі елементи в масиві проходять тест, реалізований у `$predicate` з сигнатурою `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 30, 39, 29, 10, 13];
@@ -49,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true
 Див. [some() |#some].
 
 
-first(array $array): mixed .[method]
-------------------------------------
+filter(array $array, callable $predicate): array .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------
+
+Повертає новий масив, що містить всі пари ключ-значення, які відповідають заданому `$predicate`. Зворотний виклик має сигнатуру `function ($value, int|string $key, array $array): bool`.
+
+```php
+Arrays::filter(
+	['a' => 1, 'b' => 2, 'c' => 3],
+	fn($v) => $v < 3,
+);
+// ['a' => 1, 'b' => 2]
+```
+
+
+first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------
 
-Повертає перший запис із масиву або null, якщо масив порожній. Не змінює внутрішній покажчик, на відміну від `reset()`.
+Повертає перший елемент (що відповідає вказаному предикату, якщо він заданий). Якщо такого елемента немає, повертається результат виклику `$else` або нуль.
+Функція `$predicate` має підпис `function ($value, int|string $key, array $array): bool`.
+
+Він не змінює внутрішній вказівник, на відміну від `reset()`. Параметри `$predicate` та `$else` з'явилися починаючи з версії 4.0.4.
+
+```php
+Arrays::first([1, 2, 3]);                   // 1
+Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
+Arrays::first([]);                          // null
+Arrays::first([], else: fn() => false);     // false
+```
+
+Див. [функцію last( |#last()]).
+
+
+firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+------------------------------------------------------------------------------------------------
+
+Повертає ключ першого елемента (що відповідає вказаному предикату, якщо він заданий) або нуль, якщо такого елемента немає. `$predicate` має підпис `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::first([1, 2, 3]); // 1
-Arrays::first([]);        // null
+Arrays::firstKey([1, 2, 3]);                   // 0
+Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
+Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
+Arrays::firstKey([]);                          // null
 ```
 
+Див. функцію [lastKey( |#lastKey()]).
+
 
 flatten(array $array, bool $preserveKeys=false): array .[method]
 ----------------------------------------------------------------
@@ -71,8 +148,8 @@ $array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
 ```
 
 
-get(array $array, string|int|array $key, mixed $default=null): mixed .[method]
-------------------------------------------------------------------------------
+get(array $array, string|int|array $key, ?mixed $default=null): mixed .[method]
+-------------------------------------------------------------------------------
 
 Повертає елемент `$array[$key]`. Якщо він не існує, то або видається виняток `Nette\InvalidArgumentException`, або, якщо задано третій параметр `$default`, то повертається цей параметр.
 
@@ -188,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false
 ```
 
 
-last(array $array): mixed .[method]
------------------------------------
+last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+------------------------------------------------------------------------------------
+
+Повертає останній елемент (що відповідає вказаному предикату, якщо він заданий). Якщо такого елемента немає, повертається результат виклику `$else` або нуль.
+Функція `$predicate` має підпис `function ($value, int|string $key, array $array): bool`.
+
+Він не змінює внутрішній вказівник, на відміну від `end()`. Параметри `$predicate` та `$else` з'явилися починаючи з версії 4.0.4.
+
+```php
+Arrays::last([1, 2, 3]);                   // 3
+Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
+Arrays::last([]);                          // null
+Arrays::last([], else: fn() => false);     // false
+```
+
+Див. [функцію first() |#first()].
+
+
+lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4}
+-----------------------------------------------------------------------------------------------
 
-Повертає останній запис масиву або null, якщо масив порожній. Не змінює внутрішній покажчик, на відміну від `end()`.
+Повертає ключ останнього елемента (який відповідає вказаному предикату, якщо його задано) або нуль, якщо такого елемента не існує. `$predicate` має підпис `function ($value, int|string $key, array $array): bool`.
 
 ```php
-Arrays::last([1, 2, 3]); // 3
-Arrays::last([]);        // null
+Arrays::lastKey([1, 2, 3]);                    // 2
+Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
+Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
+Arrays::lastKey([]);                           // null
 ```
 
+Зверніться до [firstKey( |#firstKey()]).
 
-map(iterable $array, callable $callback): array .[method]
+
+map(array $array, callable $transformer): array .[method]
 ---------------------------------------------------------
 
-Викликає `$callback` на всіх елементах масиву і повертає масив значень, що повертаються. Зворотний виклик має сигнатуру `function ($value, $key, array $array): bool`.
+Викликає `$transformer` на всіх елементах масиву і повертає масив значень, що повертаються. Зворотний виклик має сигнатуру `function ($value, $key, array $array): bool`.
 
 ```php
 $array = ['foo', 'bar', 'baz'];
@@ -211,6 +310,20 @@ $res = Arrays::map($array, fn($value) => $value . $value);
 ```
 
 
+mapWithKeys(array $array, callable $transformer): array .[method]
+-----------------------------------------------------------------
+
+Створює новий масив шляхом перетворення значень і ключів вихідного масиву. Функція `$transformer` має сигнатуру `function ($value, $key, array $array): ?array{$newValue, $newKey}`. Якщо `$transformer` повертає `null`, елемент пропускається. Для збережених елементів перший елемент повернутого масиву використовується як новий ключ, а другий елемент - як нове значення.
+
+```php
+$array = ['a' => 1, 'b' => 2, 'c' => 3];
+$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Цей метод корисний у ситуаціях, коли потрібно змінити структуру масиву (і ключі, і значення одночасно) або відфільтрувати елементи під час перетворення (повертаючи нуль для небажаних елементів).
+
+
 mergeTree(array $array1, array $array2): array .[method]
 --------------------------------------------------------
 
@@ -227,8 +340,8 @@ $array = Arrays::mergeTree($array1, $array2);
 Значення з другого масиву завжди додаються до кінця першого. Зникнення значення `10` з другого поля може здатися трохи незрозумілим. Зверніть увагу, що це значення, як і значення `5` v poli prvním mají přiřazený stejný numerický klíč `0`, тому в результуючий масив потрапляє тільки елемент із першого поля.
 
 
-normalize(array $array, string $filling=null): array .[method]
---------------------------------------------------------------
+normalize(array $array, ?string $filling=null): array .[method]
+---------------------------------------------------------------
 
 Нормалізує масив до асоціативного масиву. Замінює цифрові клавіші їхніми значеннями, нове значення буде `$filling`.
 
@@ -243,8 +356,8 @@ $array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
 ```
 
 
-pick(array &$array, string|int $key, mixed $default=null): mixed .[method]
---------------------------------------------------------------------------
+pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method]
+---------------------------------------------------------------------------
 
 Повертає і видаляє значення елемента з масиву. Якщо він не існує, видає виняток або повертає значення `$default`, якщо воно існує.
 
@@ -284,10 +397,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null
 ```
 
 
-some(iterable $array, callable $callback): bool .[method]
----------------------------------------------------------
+some(array $array, callable $predicate): bool .[method]
+-------------------------------------------------------
 
-Перевіряє, чи проходить хоча б один елемент у масиві тест, реалізований у `$callback` із сигнатурою `function ($value, $key, array $array): bool`.
+Перевіряє, чи проходить хоча б один елемент у масиві тест, реалізований у `$predicate` із сигнатурою `function ($value, $key, array $array): bool`.
 
 ```php
 $array = [1, 2, 3, 4];
@@ -321,8 +434,8 @@ Arrays::toObject($array, $obj); // додаємо $obj->foo = 1; $obj->bar = 2;
 ```
 
 
-wrap(iterable $array, string $prefix='', string $suffix=''): array .[method]
-----------------------------------------------------------------------------
+wrap(array $array, string $prefix='', string $suffix=''): array .[method]
+-------------------------------------------------------------------------
 
 Виводить кожен елемент масиву в рядок і обертає його префіксом `$prefix` і суфіксом `$suffix`.
 
diff --git a/utils/uk/datetime.texy b/utils/uk/datetime.texy
index 8649d1600d..ef85c044f3 100644
--- a/utils/uk/datetime.texy
+++ b/utils/uk/datetime.texy
@@ -38,8 +38,8 @@ DateTime::fromParts(1994, 2, 26, 4, 15, 32);
 ```
 
 
-static createFromFormat(string $format, string $time, string|\DateTimeZone $timezone=null): DateTime|false .[method]
---------------------------------------------------------------------------------------------------------------------
+static createFromFormat(string $format, string $time, ?string|\DateTimeZone $timezone=null): DateTime|false .[method]
+---------------------------------------------------------------------------------------------------------------------
 Розширює [DateTime::createFromFormat() |https://www.php.net/manual/en/datetime.createfromformat.php] можливістю введення часового поясу у вигляді рядка.
 ```php
 DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
diff --git a/utils/uk/filesystem.texy b/utils/uk/filesystem.texy
index 1940925dfb..cd1d667c15 100644
--- a/utils/uk/filesystem.texy
+++ b/utils/uk/filesystem.texy
@@ -2,9 +2,11 @@
 ************************
 
 .[perex]
-[api:Nette\Utils\FileSystem] це статичний клас, який містить корисні функції для роботи з файловою системою. Однією з переваг над нативними функціями PHP є те, що вони генерують виключення у випадку помилок.
+[api:Nette\Utils\FileSystem] це клас, який містить корисні функції для роботи з файловою системою. Однією з переваг перед нативними функціями PHP є те, що вони генерують виключення у випадку помилок.
 
 
+Якщо вам потрібно знайти файли на диску, скористайтеся [Finder |finder].
+
 Встановлення:
 
 ```shell
@@ -174,3 +176,26 @@ platformSlashes(string $path): string .[method]
 ```php
 $path = FileSystem::platformSlashes($path);
 ```
+
+
+Статичний vs нестатичний підхід .[#toc-static-vs-non-static-approach]
+=====================================================================
+
+Щоб легко замінити клас `FileSystem` іншим класом, наприклад, для тестування, використовуйте його нестатично:
+
+```php
+class AnyClassUsingFileSystem
+{
+	public function __construct(
+		private FileSystem $fileSystem,
+	) {
+	}
+
+	public function readConfig(): string
+	{
+		return $this->fileSystem->read(/* ... */);
+	}
+
+	...
+}
+```
diff --git a/utils/uk/finder.texy b/utils/uk/finder.texy
index 7ed58e04f4..33cdeefa2f 100644
--- a/utils/uk/finder.texy
+++ b/utils/uk/finder.texy
@@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // все каталоги
 
 Ви можете використовувати [підстановні знаки |#wildcards] `*`, `**`, `?` and `[...]` у масці. Можна навіть вказувати в каталогах, наприклад, `src/*.php` буде шукати всі файли PHP в каталозі `src`.
 
+Симпосилання також вважаються каталогами або файлами.
+
 
 Де шукати? .[#toc-where-to-search]
 ----------------------------------
diff --git a/utils/uk/floats.texy b/utils/uk/floats.texy
index 8ef3c63555..916e0348a1 100644
--- a/utils/uk/floats.texy
+++ b/utils/uk/floats.texy
@@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
 
 При спробі порівняти `NAN` виникає виняток `\LogicException`.
 
+.[tip]
+Клас `Floats` менш толерантний до відмінностей, ніж `1e-10`. Якщо вам потрібно працювати з більшою точністю, використовуйте замість нього бібліотеку BCMath.
+
 
 Порівняння плаваючих значень .[#toc-float-comparison]
 =====================================================
diff --git a/utils/uk/html-elements.texy b/utils/uk/html-elements.texy
index 5c3a642887..bd9d76912c 100644
--- a/utils/uk/html-elements.texy
+++ b/utils/uk/html-elements.texy
@@ -219,10 +219,10 @@ $el = Html::el('span')
 Інший спосіб створення та вставки нового вузла `Html`:
 
 ```php
-$el = Html::el('ul')
-	->create('li', ['class' => 'first'])
-		->setText('první');
-// <ul><li class="first">první</li></ul>
+$ul = Html::el('ul');
+$ul->create('li', ['class' => 'first'])
+	->setText('hello');
+// <ul><li class="first">hello</li></ul>
 ```
 
 Ви можете працювати з вузлами так, як якщо б вони були масивами. Тобто, звертайтеся до кожного з них за допомогою квадратних дужок, рахуйте їх за допомогою `count()` і виконуйте ітерації:
diff --git a/utils/uk/images.texy b/utils/uk/images.texy
index 33392a2839..8cb7116d16 100644
--- a/utils/uk/images.texy
+++ b/utils/uk/images.texy
@@ -17,6 +17,8 @@ composer require nette/utils
 
 ```php
 use Nette\Utils\Image;
+use Nette\Utils\ImageColor;
+use Nette\Utils\ImageType;
 ```
 
 
@@ -32,7 +34,7 @@ $image = Image::fromBlank(100, 200);
 За бажанням можна вказати колір фону (за замовчуванням чорний):
 
 ```php
-$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
+$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0));
 ```
 
 Або завантажте зображення з файлу:
@@ -41,17 +43,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0));
 $image = Image::fromFile('nette.jpg');
 ```
 
-Підтримуються формати JPEG, PNG, GIF, WebP, AVIF і BMP, але ваша версія PHP також повинна їх підтримувати (перевірте `phpinfo()`, розділ GD). Анімація не підтримується.
-
-Чи потрібно визначати формат зображення під час завантаження? Метод повертає його в другому параметрі:
-
-```php
-$image = Image::fromFile('nette.jpg', $type);
-// $type є Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF або Image::BMP
-```
-
-За допомогою `Image::detectTypeFromFile()` виконується лише детектування без завантаження зображення.
-
 
 Збереження зображення .[#toc-save-the-image]
 ============================================
@@ -68,25 +59,45 @@ $image->save('resampled.jpg');
 $image->save('resampled.jpg', 80); // JPEG, 80% якості
 ```
 
-Якщо формат не очевидний з розширення файлу, його можна вказати за допомогою однієї з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`:
+Якщо формат не очевидний з розширення файлу, його можна вказати за допомогою [константи |#Formats]:
 
 ```php
-$image->save('resampled.tmp', null, Image::JPEG);
+$image->save('resampled.tmp', null, ImageType::JPEG);
 ```
 
 Зображення може бути записано не на диск, а у змінну:
 
 ```php
-$data = $image->toString(Image::JPEG, 80); // JPEG, 80% якості
+$data = $image->toString(ImageType::JPEG, 80); // JPEG, 80% якості
 ```
 
 або надсилається безпосередньо в браузер із відповідним HTTP-заголовком `Content-Type`:
 
 ```php
 // відправляє заголовок Content-Type: image/png
-$image->send(Image::PNG);
+$image->send(ImageType::PNG);
+```
+
+
+Формати .[#toc-formats]
+=======================
+
+Підтримуються формати JPEG, PNG, GIF, WebP, AVIF і BMP. Однак вони також повинні підтримуватися вашою версією PHP, що можна перевірити за допомогою функції [isTypeSupported( |#isTypeSupported()] ). Анімація не підтримується.
+
+Формати представлені константами `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` і `ImageType::BMP`.
+
+```php
+$supported = Image::isTypeSupported(ImageType::JPEG);
 ```
 
+Потрібно визначити формат зображення при завантаженні? Метод повертає його у другому параметрі:
+
+```php
+$image = Image::fromFile('nette.jpg', $type);
+```
+
+Власне визначення без завантаження зображення виконується за допомогою `Image::detectTypeFromFile()`.
+
 
 Змінити розмір .[#toc-image-resize]
 ===================================
@@ -181,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK);
 Метод `cropAuto()` є об'єктною заміною функції `imagecropauto()`, більш детальну інформацію див. у [документації до неї |https://www.php.net/manual/en/function.imagecropauto].
 
 
+Кольори .[#toc-colors]
+======================
+
+Метод `ImageColor::rgb()` дозволяє визначити колір за допомогою значень червоного, зеленого та синього (RGB). За бажанням, ви також можете вказати значення прозорості в діапазоні від 0 (повністю прозорий) до 1 (повністю непрозорий), так само, як і в CSS.
+
+```php
+$color = ImageColor::rgb(255, 0, 0); // Red
+$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue
+```
+
+Метод `ImageColor::hex()` дозволяє визначити колір за допомогою шістнадцяткового формату, подібно до CSS. Він підтримує формати `#rgb`, `#rrggbb`, `#rgba` і `#rrggbbaa`:
+
+```php
+$color = ImageColor::hex("#F00"); // Red
+$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green
+```
+
+Кольори можна використовувати і в інших методах, таких як `ellipse()`, `fill()` тощо.
+
+
 Малювання та редагування .[#toc-drawing-and-editing]
 ====================================================
 
-Ви можете малювати, можете писати, але не рвіть сторінки. Усі функції PHP для роботи із зображеннями, такі як [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], доступні вам, але в об'єктно-орієнтованому образі:
+Ви можете малювати, можете писати, можете використовувати всі функції PHP для маніпулювання зображеннями, див. [Огляд методів |#Overview of methods], але в об'єктно-орієнтованій обгортці:
 
 ```php
-$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
+$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0));
 ```
 
-Див. розділ [Огляд методів |#Overview-of-Methods].
+Оскільки функції PHP для малювання прямокутників непрактичні через необхідність вказувати координати, клас `Image` пропонує їх заміну у вигляді функцій [rectangleWH( |#rectangleWH()] ) і [filledRectangleWH( |#filledRectangleWH()]).
 
 
 Об'єднання декількох зображень .[#toc-merge-multiple-images]
@@ -200,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63));
 
 ```php
 $logo = Image::fromFile('logo.png');
-$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210));
+$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210));
 
 // координати можуть бути знову задані у відсотках
 $blank->place($logo, '80%', '80%'); // вставте в правий нижній кут
@@ -219,53 +250,68 @@ $blank->place($image, '80%', '80%', 25); // прозорість станови
 =========================================
 
 
-static fromBlank(int $width, int $height, array $color=null): Image .[method]
------------------------------------------------------------------------------
+static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[method]
+-----------------------------------------------------------------------------------
 Створює нове істинно кольорове зображення заданих розмірів. За замовчуванням використовується чорний колір.
 
 
 static fromFile(string $file, int &$detectedFormat=null): Image .[method]
 -------------------------------------------------------------------------
-Читає зображення з файлу і повертає його тип у `$detectedFormat`. Підтримуються типи `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` і `Image::BMP`.
+Читає зображення з файлу і повертає його [тип |#Formats] в `$detectedFormat`.
 
 
 static fromString(string $s, int &$detectedFormat=null): Image .[method]
 ------------------------------------------------------------------------
-Читає зображення з рядка і повертає його тип у вигляді `$detectedFormat`. Підтримуються типи `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`.
+Читає зображення з рядка і повертає його [тип |#Formats] в `$detectedFormat`.
 
 
-static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method]
----------------------------------------------------------------------------------
-Створює колір, який може бути використаний в інших методах, таких як `ellipse()`, `fill()` тощо.
+static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated]
+---------------------------------------------------------------------------------------------
+Ця функція була замінена на клас `ImageColor`, див. [кольори |#Colors].
 
 
 static typeToExtension(int $type): string .[method]
 ---------------------------------------------------
-Повертає розширення файлу для заданої константи `Image::XXX`.
+Повертає розширення файлу для заданого [типу |#Formats].
 
 
 static typeToMimeType(int $type): string .[method]
 --------------------------------------------------
-Повертає тип mime для заданої константи `Image::XXX`.
+Повертає тип mime для заданого [типу |#Formats].
 
 
 static extensionToType(string $extension): int .[method]
 --------------------------------------------------------
-Повертає тип зображення у вигляді константи `Image::XXX` відповідно до розширення файлу.
+Повертає [тип |#Formats] зображення відповідно до розширення файлу.
 
 
 static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method]
 --------------------------------------------------------------------------------------------
-Повертає тип зображення у вигляді константи `Image::XXX`, а також його розміри в параметрах `$width` і `$height`.
+Повертає [тип |#Formats] файлу зображення, а в параметрах `$width` та `$height` також його розміри.
 
 
 static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method]
 -------------------------------------------------------------------------------------------
-Повертає тип зображення з рядка у вигляді константи `Image::XXX` і його розміри в параметрах `$width` і `$height`.
+Повертає [тип |#Formats] зображення з рядка, а в параметрах `$width` та `$height` також його розміри.
 
 
-affine(array $affine, array $clip=null): Image .[method]
---------------------------------------------------------
+static isTypeSupported(int $type): bool .[method]
+-------------------------------------------------
+Визначає, чи підтримується даний [тип |#Formats] зображення.
+
+
+static getSupportedTypes(): array .[method]{data-version:4.0.4}
+---------------------------------------------------------------
+Повертає масив підтримуваних типів зображень (константи `ImageType::XXX`).
+
+
+static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method]
+------------------------------------------------------------------------------------------------------------------------
+Обчислює розміри прямокутника, який охоплює текст заданого шрифту та розміру. Повертає асоціативний масив, що містить ключі `left`, `top`, `width`, `height`. Ліве поле може бути від'ємним, якщо текст починається з лівого відступу.
+
+
+affine(array $affine, ?array $clip=null): Image .[method]
+---------------------------------------------------------
 Повертає зображення, що містить афінно-трансформоване зображення src з використанням необов'язкової області обрізання. ([докладніше |https://www.php.net/manual/en/function.imageaffine]).
 
 
@@ -274,8 +320,8 @@ affineMatrixConcat(array $m1, array $m2): array .[method]
 Повертає конкатенацію двох матриць афінного перетворення, що корисно, якщо до одного зображення необхідно застосувати одразу кілька перетворень. ([докладніше |https://www.php.net/manual/en/function.imageaffinematrixconcat])
 
 
-affineMatrixGet(int $type, mixed $options=null): array .[method]
-----------------------------------------------------------------
+affineMatrixGet(int $type, ?mixed $options=null): array .[method]
+-----------------------------------------------------------------
 Повертає матрицю перетворення матриці. ([докладніше |https://www.php.net/manual/en/function.imageaffinematrixget])
 
 
@@ -291,21 +337,11 @@ antialias(bool $on): void .[method]
 Використання згладженого примітиву з прозорим кольором фону може призвести до несподіваних результатів. Метод змішування використовує колір фону як будь-який інший колір. ([докладніше |https://www.php.net/manual/en/function.imageantialias])
 
 
-arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method]
--------------------------------------------------------------------------------------
+arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method]
+---------------------------------------------------------------------------------------------------------------------------
 Малює дугу кола з центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagearc])
 
 
-char(int $font, int $x, int $y, string $char, int $color): void .[method]
--------------------------------------------------------------------------
-Намалює перший символ `$char` у зображенні з лівим верхнім кутом `$x`, `$y` (лівий верхній кут дорівнює 0, 0) кольором `$color`. ([докладніше |https://www.php.net/manual/en/function.imagechar])
-
-
-charUp(int $font, int $x, int $y, string $char, int $color): void .[method]
----------------------------------------------------------------------------
-Малює символ `$char` вертикально за вказаною координатою в заданому зображенні. ([докладніше |https://www.php.net/manual/en/function.imagecharup])
-
-
 colorAllocate(int $red, int $green, int $blue): int .[method]
 -------------------------------------------------------------
 Повертає ідентифікатор кольору, що представляє колір, який складається із заданих компонентів RGB. Повинен бути викликаний для створення кожного кольору, який буде використовуватися в зображенні. ([докладніше |https://www.php.net/manual/en/function.imagecolorallocate])
@@ -381,8 +417,8 @@ colorsTotal(): int .[method]
 Повертає кількість кольорів у палітрі зображення. ([докладніше |https://www.php.net/manual/en/function.imagecolorstotal])
 
 
-colorTransparent(int $color=null): int .[method]
-------------------------------------------------
+colorTransparent(?int $color=null): int .[method]
+-------------------------------------------------
 Отримує або встановлює прозорий колір зображення. ([докладніше |https://www.php.net/manual/en/function.imagecolortransparent])
 
 
@@ -432,43 +468,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height):
 Обрізає зображення до заданої прямокутної області. Розміри можуть бути вказані як цілі числа в пікселях або рядки у відсотках (наприклад, `'50%'`).
 
 
-cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method]
----------------------------------------------------------------------------
+cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method]
+-------------------------------------------------------------------------------------
 Автоматичне кадрування зображення відповідно до заданого `$mode`. ([докладніше |https://www.php.net/manual/en/function.imagecropauto])
 
 
-ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------
+ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------
 Малює еліпс із центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imageellipse])
 
 
-fill(int $x, int $y, int $color): void .[method]
-------------------------------------------------
+fill(int $x, int $y, ImageColor $color): void .[method]
+-------------------------------------------------------
 Заповнює область, що починається в заданій координаті (зліва вгорі 0, 0), заданим `$color`. ([докладніше |https://www.php.net/manual/en/function.imagefill])
 
 
-filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method]
----------------------------------------------------------------------------------------------------
+filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method]
+---------------------------------------------------------------------------------------------------------------------------------------------
 Малює неповну дугу з центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagefilledarc])
 
 
-filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method]
----------------------------------------------------------------------------
+filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method]
+-----------------------------------------------------------------------------------------------------
 Малює еліпс із центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagefilledellipse])
 
 
-filledPolygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------------
+filledPolygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------------
 Створює заповнений багатокутник на зображенні. ([докладніше |https://www.php.net/manual/en/function.imagefilledpolygon])
 
 
-filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
--------------------------------------------------------------------------------
-Створює прямокутник, заповнений `$color` на зображенні, починаючи з точки 1 і закінчуючи точкою 2. Точка 0, 0 - лівий верхній кут зображення. ([докладніше |https://www.php.net/manual/en/function.imagefilledrectangle])
+filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------
+Створює прямокутник, заповнений `$color` на зображенні, що починається з `$x1` та `$y1` і закінчується `$x2` та `$y2`. Точка 0, 0 є верхнім лівим кутом зображення. ([докладніше |https://www.php.net/manual/en/function.imagefilledrectangle])
 
 
-fillToBorder(int $x, int $y, int $border, int $color): void .[method]
----------------------------------------------------------------------
+filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------------
+Створює на зображенні прямокутник, заповнений `$color`, починаючи з точок `$left` та `$top` з шириною `$width` та висотою `$height`. Точка 0, 0 є верхнім лівим кутом зображення.
+
+
+fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method]
+----------------------------------------------------------------------------
 Створює заливку, колір межі якої визначається `$border`. Початкова точка заливки - `$x`, `$y` (лівий верхній кут - 0, 0), а область заливається кольором `$color`. ([докладніше |https://www.php.net/manual/en/function.imagefilltoborder])
 
 
@@ -482,9 +523,9 @@ flip(int $mode): void .[method]
 Інвертує зображення за заданою адресою `$mode`. ([докладніше |https://www.php.net/manual/en/function.imageflip])
 
 
-ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method]
--------------------------------------------------------------------------------------------------------------------------------
-Пишіть текст на зображенні, використовуючи шрифти FreeType 2. ([докладніше |https://www.php.net/manual/en/function.imagefttext])
+ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+----------------------------------------------------------------------------------------------------------------------------------------
+Напишіть текст на картинці. ([більше |https://www.php.net/manual/en/function.imagefttext])
 
 
 gammaCorrect(float $inputgamma, float $outputgamma): void .[method]
@@ -512,8 +553,8 @@ getWidth(): int .[method]
 Повертає ширину зображення.
 
 
-interlace(int $interlace=null): int .[method]
----------------------------------------------
+interlace(?int $interlace=null): int .[method]
+----------------------------------------------
 Увімкнення або вимкнення режиму черезрядкової розгортки. Якщо встановлено черезрядковий режим і зображення зберігається у форматі JPEG, воно буде збережено як прогресивний JPEG. ([докладніше |https://www.php.net/manual/en/function.imageinterlace])
 
 
@@ -527,13 +568,13 @@ layerEffect(int $effect): void .[method]
 Встановіть прапор альфа-змішання для використання ефектів нашарування. ([докладніше |https://www.php.net/manual/en/function.imagelayereffect])
 
 
-line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method]
---------------------------------------------------------------------
+line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+---------------------------------------------------------------------------
 Проводить лінію між двома заданими точками. ([докладніше |https://www.php.net/manual/en/function.imageline])
 
 
-openPolygon(array $points, int $numPoints, int $color): void .[method]
-----------------------------------------------------------------------
+openPolygon(array $points, ImageColor $color): void .[method]
+-------------------------------------------------------------
 Малює відкритий багатокутник на зображенні. На відміну від `polygon()`, між останньою і першою точкою не проводиться лінія. ([докладніше |https://www.php.net/manual/en/function.imageopenpolygon])
 
 
@@ -552,23 +593,28 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im
 Копіює `$image` у зображення за координатами `$left` і `$top`. Координати можуть бути вказані як цілі числа в пікселях або рядки у відсотках (наприклад, `'50%'`).
 
 
-polygon(array $points, int $numPoints, int $color): void .[method]
-------------------------------------------------------------------
+polygon(array $points, ImageColor $color): void .[method]
+---------------------------------------------------------
 Створює багатокутник на зображенні. ([докладніше |https://www.php.net/manual/en/function.imagepolygon])
 
 
-rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method]
------------------------------------------------------------------------
+rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------
 Створює прямокутник за заданими координатами. ([докладніше |https://www.php.net/manual/en/function.imagerectangle])
 
 
+rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method]
+--------------------------------------------------------------------------------------------
+Створює прямокутник за заданими координатами.
+
+
 resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method]
 -------------------------------------------------------------------------------------------
 Зміна розмірів зображення, [додаткова інформація |#Image-Resize]. Розміри можуть бути вказані як цілі числа в пікселях або рядки у відсотках (наприклад, `'50%'`).
 
 
-resolution(int $resX=null, int $resY=null): mixed .[method]
------------------------------------------------------------
+resolution(?int $resX=null, ?int $resY=null): mixed .[method]
+-------------------------------------------------------------
 Встановлює або повертає роздільну здатність зображення в DPI (точках на дюйм). Якщо жоден із додаткових параметрів не вказано, поточну роздільну здатність повертають у вигляді індексованого поля. Якщо вказано тільки `$resX`, то горизонтальна і вертикальна роздільна здатність встановлюється на це значення. Якщо вказано обидва додаткові параметри, горизонтальну та вертикальну роздільну здатність встановлюють на ці значення.
 
 Роздільна здатність використовується як метаінформація тільки під час читання і запису зображень у формати, що підтримують таку інформацію (наразі це PNG і JPEG). Це не впливає ні на які операції малювання. Роздільна здатність нових зображень за замовчуванням становить 96 DPI. ([докладніше |https://www.php.net/manual/en/function.imageresolution])
@@ -582,11 +628,11 @@ rotate(float $angle, int $backgroundColor): Image .[method]
 Вимагає наявності *Bundled GD extension*, тому може працювати не скрізь.
 
 
-save(string $file, int $quality=null, int $type=null): void .[method]
----------------------------------------------------------------------
+save(string $file, ?int $quality=null, ?int $type=null): void .[method]
+-----------------------------------------------------------------------
 Зберігає зображення у файл.
 
-Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Якщо тип не очевидний з розширення файлу, ви можете вказати його за допомогою однієї з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`.
+Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Якщо тип не очевидний з розширення файлу, ви можете вказати його за допомогою однієї з констант `ImageType`.
 
 
 saveAlpha(bool $saveflag): void .[method]
@@ -601,11 +647,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m
 Масштабування зображення з використанням заданого алгоритму інтерполяції. ([докладніше |https://www.php.net/manual/en/function.imagescale])
 
 
-send(int $type=Image::JPEG, int $quality=null): void .[method]
---------------------------------------------------------------
+send(int $type=ImageType::JPEG, ?int $quality=null): void .[method]
+-------------------------------------------------------------------
 Виводить зображення в браузер.
 
-Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Тип - одна з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`.
+Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9).
 
 
 setBrush(Image $brush): void .[method]
@@ -623,8 +669,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method]
 Задає метод інтерполяції, який впливає на методи `rotate()` і `affine()`. ([докладніше |https://www.php.net/manual/en/function.imagesetinterpolation])
 
 
-setPixel(int $x, int $y, int $color): void .[method]
-----------------------------------------------------
+setPixel(int $x, int $y, ImageColor $color): void .[method]
+-----------------------------------------------------------
 Малює піксель у вказаній координаті. ([докладніше |https://www.php.net/manual/en/function.imagesetpixel])
 
 
@@ -653,21 +699,11 @@ sharpen(): Image .[method]
 Вимагає наявності *Bundled GD extension*, тому може працювати не скрізь.
 
 
-string(int $font, int $x, int $y, string $str, int $col): void .[method]
-------------------------------------------------------------------------
-Виводить рядок за заданими координатами. ([докладніше |https://www.php.net/manual/en/function.imagestring])
-
-
-stringUp(int $font, int $x, int $y, string $s, int $col): void .[method]
-------------------------------------------------------------------------
-Виводить рядок по вертикалі в заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagestringup])
-
-
-toString(int $type=Image::JPEG, int $quality=null): string .[method]
---------------------------------------------------------------------
+toString(int $type=ImageType::JPEG, ?int $quality=null): string .[method]
+-------------------------------------------------------------------------
 Зберігає зображення в рядку.
 
-Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Тип - одна з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`.
+Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9).
 
 
 trueColorToPalette(bool $dither, int $ncolors): void .[method]
@@ -675,6 +711,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method]
 Перетворює truecolor зображення в палітру. ([докладніше |https://www.php.net/manual/en/function.imagetruecolortopalette])
 
 
-ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method]
------------------------------------------------------------------------------------------------------------
-Друкує заданий текст у зображення з використанням шрифтів TrueType. ([докладніше |https://www.php.net/manual/en/function.imagettftext])
+ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method]
+-----------------------------------------------------------------------------------------------------------------------------------------
+Записує заданий текст у зображення. ([докладніше |https://www.php.net/manual/en/function.imagettftext])
diff --git a/utils/uk/iterables.texy b/utils/uk/iterables.texy
new file mode 100644
index 0000000000..a9009c63ad
--- /dev/null
+++ b/utils/uk/iterables.texy
@@ -0,0 +1,170 @@
+Функції ітератора
+*****************
+
+.[perex]{data-version:4.0.4}
+[api:Nette\Utils\Iterables] статичний клас з функціями для роботи з ітераторами. Його аналогом для масивів є [Nette\Utils\Arrays |arrays].
+
+
+Встановлення:
+
+```shell
+composer require nette/utils
+```
+
+У всіх прикладах передбачається, що створено наступний псевдонім:
+
+```php
+use Nette\Utils\Iterables;
+```
+
+
+contains(iterable $iterable, $value): bool .[method]
+----------------------------------------------------
+
+Шукає задане значення в ітераторі. Використовує строге порівняння (`===`) для перевірки на збіг. Повертає `true`, якщо значення знайдено, інакше `false`.
+
+```php
+Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
+Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false
+```
+
+Цей метод корисний, коли вам потрібно швидко визначити, чи присутнє певне значення в ітераторі без ручного перебору всіх елементів.
+
+
+containsKey(iterable $iterable, $key): bool .[method]
+-----------------------------------------------------
+
+Шукає заданий ключ в ітераторі. Використовує строге порівняння (`===`) для перевірки на збіг. Повертає `true`, якщо ключ знайдено, інакше `false`.
+
+```php
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0);  // true
+Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4);  // false
+```
+
+
+every(iterable $iterable, callable $predicate): bool .[method]
+--------------------------------------------------------------
+
+Перевіряє, чи всі елементи ітератора задовольняють умову, визначену в `$predicate`. Функція `$predicate` має сигнатуру `function ($value, $key, iterable $iterable): bool` і повинна повертати `true` для кожного елементу, щоб метод `every()` повертав `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isBelowThreshold = fn($value) => $value < 40;
+$res = Iterables::every($iterator, $isBelowThreshold); // true
+```
+
+Цей метод корисний для перевірки того, що всі елементи колекції задовольняють певну умову, наприклад, чи всі числа є меншими за певне значення.
+
+
+filter(iterable $iterable, callable $predicate): Generator .[method]
+--------------------------------------------------------------------
+
+Створює новий ітератор, який містить тільки ті елементи з початкового ітератора, які задовольняють умову, визначену в `$predicate`. Функція `$predicate` має сигнатуру `function ($value, $key, iterable $iterable): bool` і повинна повернути `true` для елементів, які слід зберегти.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
+// 1, 2
+```
+
+Метод використовує генератор, що означає, що фільтрація відбувається інкрементно під час ітерації. Це ефективно використовує пам'ять і дозволяє обробляти дуже великі колекції. Якщо ви не перебираєте всі елементи результуючого ітератора, ви економите обчислювальні зусилля, оскільки не всі елементи початкового ітератора обробляються.
+
+
+first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+-------------------------------------------------------------------------------------------
+
+Повертає перший елемент ітератора. Якщо вказано `$predicate`, повертається перший елемент, який задовольняє задану умову. Функція `$predicate` має сигнатуру `function ($value, $key, iterable $iterable): bool`. Якщо відповідного елемента не знайдено, викликається функція `$else` (якщо вона задана) і повертається її результат. Якщо `$else` не задано, повертається `null`.
+
+```php
+Iterables::first(new ArrayIterator([1, 2, 3]));                   // 1
+Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
+Iterables::first(new ArrayIterator([]));                          // null
+Iterables::first(new ArrayIterator([]), else: fn() => false);     // false
+```
+
+Цей метод корисний, коли потрібно швидко отримати перший елемент колекції або перший елемент, який задовольняє певну умову, без ручного перебору всієї колекції.
+
+
+firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method]
+----------------------------------------------------------------------------------------------
+
+Повертає ключ першого елемента ітератора. Якщо вказано `$predicate`, повертає ключ першого елемента, який задовольняє задану умову. Функція `$predicate` має сигнатуру `function ($value, $key, iterable $iterable): bool`. Якщо відповідного елемента не знайдено, викликається функція `$else` (якщо вона передбачена) і повертається її результат. Якщо `$else` не задано, повертається `null`.
+
+```php
+Iterables::firstKey(new ArrayIterator([1, 2, 3]));                   // 0
+Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
+Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2]));        // 'a'
+Iterables::firstKey(new ArrayIterator([]));                          // null
+```
+
+
+map(iterable $iterable, callable $transformer): Generator .[method]
+-------------------------------------------------------------------
+
+Створює новий ітератор шляхом застосування функції `$transformer` до кожного елемента початкового ітератора. Функція `$transformer` має сигнатуру `function ($value, $key, iterable $iterable): mixed` і її значення, що повертається, використовується як нове значення елемента.
+
+```php
+$iterator = new ArrayIterator([1, 2, 3]);
+$iterator = Iterables::map($iterator, fn($v) => $v * 2);
+// 2, 4, 6
+```
+
+Метод використовує генератор, що означає, що перетворення відбувається інкрементно під час ітерації. Це ефективно використовує пам'ять і дозволяє працювати з дуже великими колекціями. Якщо ви не перебираєте всі елементи результуючого ітератора, ви економите обчислювальні зусилля, оскільки не всі елементи початкового ітератора обробляються.
+
+
+mapWithKeys(iterable $iterable, callable $transformer): Generator .[method]
+---------------------------------------------------------------------------
+
+Створює новий ітератор шляхом перетворення значень і ключів вихідного ітератора. Функція `$transformer` має сигнатуру `function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}`. Якщо `$transformer` повертає `null`, елемент пропускається. Для збережених елементів перший елемент повернутого масиву використовується як новий ключ, а другий елемент - як нове значення.
+
+```php
+$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
+$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
+// [4 => 'B']
+```
+
+Як і `map()`, цей метод використовує генератор для інкрементної обробки та ефективності використання пам'яті. Це дозволяє працювати з великими колекціями та економити обчислювальні зусилля, обробляючи лише частину результату.
+
+
+memoize(iterable $iterable): IteratorAggregate .[method]
+--------------------------------------------------------
+
+Створює обгортку навколо ітератора, яка кешує його ключі та значення під час ітерації. Це дозволяє повторювати ітерації над даними без необхідності переробляти початкове джерело даних.
+
+```php
+$iterator = /* data that cannot be iterated multiple times */
+$memoized = Iterables::memoize($iterator);
+// Now you can iterate $memoized multiple times without data loss
+```
+
+Цей метод корисний у ситуаціях, коли вам потрібно повторювати один і той самий набір даних кілька разів, але оригінальний ітератор не підтримує повторні ітерації або повторні ітерації були б дорогими (наприклад, читання даних з бази даних або файлу).
+
+
+some(iterable $iterable, callable $predicate): bool .[method]
+-------------------------------------------------------------
+
+Перевіряє, чи хоча б один елемент ітератора задовольняє умову, визначену в `$predicate`. Функція `$predicate` має сигнатуру `function ($value, $key, iterable $iterable): bool` і повинна повернути `true` для хоча б одного елементу, щоб метод `some()` повернув `true`.
+
+```php
+$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
+$isEven = fn($value) => $value % 2 === 0;
+$res = Iterables::some($iterator, $isEven); // true
+```
+
+Цей метод корисний для швидкої перевірки, чи є в колекції хоча б один елемент, який задовольняє певній умові, наприклад, чи містить колекція хоча б одне парне число.
+
+Див. опис [методу every() |#every()].
+
+
+toIterator(iterable $iterable): Iterator .[method]
+--------------------------------------------------
+
+Перетворює будь-який ітерований об'єкт (масив, Traversable) в ітератор. Якщо на вході вже є ітератор, він повертається без змін.
+
+```php
+$array = [1, 2, 3];
+$iterator = Iterables::toIterator($array);
+// Now you have an Iterator instead of an array
+```
+
+Цей метод корисний, коли вам потрібно переконатися, що у вас є ітератор, незалежно від типу вхідних даних. Це може бути корисно при створенні функцій, які працюють з різними типами даних, що повторюються.
diff --git a/utils/uk/json.texy b/utils/uk/json.texy
index 63cea39d9e..c216332b20 100644
--- a/utils/uk/json.texy
+++ b/utils/uk/json.texy
@@ -77,7 +77,7 @@ decode(string $json, bool $forceArray=false): mixed .[method]
 
 ```php
 Json::decode('{"variable": true}'); // повертає об'єкт типу stdClass
-Json::decode('{"variable": true}', forceArray: true); // повертає масив
+Json::decode('{"variable": true}', forceArrays: true); // повертає масив
 ```
 
 При виникненні помилки викидається виняток `Nette\Utils\JsonException`.
diff --git a/utils/uk/smartobject.texy b/utils/uk/smartobject.texy
index 4695c2fde2..446738b83e 100644
--- a/utils/uk/smartobject.texy
+++ b/utils/uk/smartobject.texy
@@ -1,8 +1,8 @@
-SmartObject і StaticClass
-*************************
+SmartObject
+***********
 
 .[perex]
-SmartObject додає підтримку *властивостей* у класи PHP. StaticClass використовується для позначення статичних класів.
+Раніше SmartObject виправляв поведінку об'єктів багатьма способами, але сьогоднішній PHP вже містить більшість з цих покращень вбудовано. Проте, він все ще додає підтримку *property*.
 
 
 Встановлення:
@@ -65,31 +65,16 @@ echo $circle->visible; // викликаємо isVisible()
 Властивості - це насамперед "синтаксичний цукор"((syntactic sugar)), який покликаний зробити життя програміста солодшим за рахунок спрощення коду. Якщо вони вам не потрібні, ви не зобов'язані їх використовувати.
 
 
-Статичні класи .[#toc-static-classes]
-=====================================
+Погляд в історію .[#toc-a-glimpse-into-history]
+===============================================
 
-Статичні класи, тобто класи, які не призначені для інстанціювання, можуть бути позначені ознакою `Nette\StaticClass`:
+SmartObject використовувався для покращення поведінки об'єктів багатьма способами, але сьогоднішній PHP вже включає в себе більшість з цих покращень нативно. Наступний текст - це ностальгічний погляд в історію, що нагадує нам про те, як все розвивалося.
 
-```php
-class Strings
-{
-	use Nette\StaticClass;
-}
-```
-
-Коли ви намагаєтеся створити екземпляр, виникає виняток `Error`, який вказує на те, що клас є статичним.
-
-
-Погляд в історію .[#toc-a-look-into-the-history]
-================================================
-
-SmartObject використовували для поліпшення і виправлення поведінки класу в багатьох відношеннях, але розвиток PHP зробив більшість початкових функцій зайвими. Тому нижче ми розглянемо історію розвитку цих функцій.
-
-Від самого початку об'єктна модель PHP страждала від низки серйозних недоліків і неефективності. Це стало причиною створення класу `Nette\Object` (у 2007 році), який спробував усунути їх і поліпшити досвід використання PHP. Цього виявилося достатньо, щоб інші класи успадкували від нього і отримали ті переваги, які він приніс. Коли в PHP 5.4 з'явилася підтримка трейтів, клас `Nette\Object` було замінено на `Nette\SmartObject`. Таким чином, більше не було необхідності успадковуватися від спільного предка. Крім того, trait можна було використовувати в класах, які вже успадковувалися від іншого класу. Остаточний кінець `Nette\Object` настав з виходом PHP 7.2, в якому було заборонено давати класам імена `Object`.
+Від самого початку об'єктна модель PHP страждала від безлічі серйозних недоліків і недоробок. Це призвело до створення класу `Nette\Object` (у 2007 році), який мав на меті виправити ці проблеми та підвищити комфорт використання PHP. Все, що було потрібно - це щоб інші класи успадковували його, і вони отримували переваги, які він пропонував. Коли в PHP 5.4 було введено підтримку трейтів, клас `Nette\Object` було замінено на трейт `Nette\SmartObject`. Це усунуло необхідність успадковувати від спільного предка. Крім того, ознаку можна було використовувати в класах, які вже були успадковані від іншого класу. Остаточний кінець `Nette\Object` настав з виходом PHP 7.2, який заборонив класам називатися `Object`.
 
-У міру розвитку PHP об'єктна модель і можливості мови вдосконалювалися. Окремі функції класу `SmartObject` стали зайвими. Після виходу PHP 8.2 єдиною функцією, яка поки що не підтримується в PHP безпосередньо, залишилася можливість використовувати так звані [властивості |#Properties, getters and setters].
+З розвитком PHP його об'єктна модель і можливості мови покращувалися. Різні функції класу `SmartObject` стали надлишковими. З виходом PHP 8.2 залишилася лише одна функція, яка не підтримується безпосередньо в PHP: можливість використання так званих [властивостей |#Properties, getters, and setters].
 
-Які функції пропонували `Nette\Object` і `Nette\Object`? Ось огляд. (У прикладах використовується клас `Nette\Object`, але більшість властивостей може бути застосована і до ознаки `Nette\SmartObject` ).
+Які ж можливості пропонували `Nette\Object` і, відповідно, `Nette\SmartObject`? Ось короткий огляд. (У прикладах використовується клас `Nette\Object`, але більшість можливостей також застосовні до властивості `Nette\SmartObject` ).
 
 
 Непослідовні помилки .[#toc-inconsistent-errors]
@@ -129,7 +114,7 @@ $foo = Foo::form($var);
 // "Call to undefined static method Foo::form(), did you mean from()?"
 ```
 
-Сучасний PHP, можливо, не має форми "Ви мали на увазі?", але [Tracy |tracy:] додає це доповнення до помилок. І він навіть може сам [виправляти |tracy:open-files-in-ide#toc-demos] такі помилки.
+Хоча сучасний PHP не має функції "ви мали на увазі?", цю фразу можна додати до помилок за допомогою [Трейсі |tracy:]. Він навіть може [автоматично виправляти такі помилки |tracy:open-files-in-ide#toc-demos].
 
 
 Методи розширення .[#toc-extension-methods]
@@ -173,7 +158,7 @@ class Foo extends Nette\Object
 
 $obj = new Foo;
 $reflection = $obj->getReflection();
-$reflection->getAnnotation('author'); // повертає 'John Doe
+$reflection->getAnnotation('author'); // повертає 'John Doe'
 ```
 
 Починаючи з PHP 8.0, з'явилася можливість доступу до мета-інформації у вигляді атрибутів:
@@ -231,7 +216,7 @@ class Circle extends Nette\Object
 	public function setRadius(float $radius): void
 	{
 		$this->onChange($this, $radius);
-		$this->radius = $radius
+		$this->radius = $radius;
 	}
 }
 ```
diff --git a/utils/uk/staticclass.texy b/utils/uk/staticclass.texy
new file mode 100644
index 0000000000..585730463f
--- /dev/null
+++ b/utils/uk/staticclass.texy
@@ -0,0 +1,21 @@
+Статичні класи
+**************
+
+.[perex]
+StaticClass використовується для позначення статичних класів.
+
+
+Встановлення:
+
+```shell
+composer require nette/utils
+```
+
+Статичні класи, тобто класи, які не призначені для екземплярів, можна позначити ознакою [api:Nette\StaticClass]:
+
+```php
+class Strings
+{
+	use Nette\StaticClass;
+}
+```
diff --git a/utils/uk/strings.texy b/utils/uk/strings.texy
index d0bb35d4b0..03cabcbb8b 100644
--- a/utils/uk/strings.texy
+++ b/utils/uk/strings.texy
@@ -104,8 +104,8 @@ $platformLines = Strings::platformNewLines($string);
 ```
 
 
-webalize(string $s, string $charlist=null, bool $lower=true): string .[method]
-------------------------------------------------------------------------------
+webalize(string $s, ?string $charlist=null, bool $lower=true): string .[method]
+-------------------------------------------------------------------------------
 
 Змінює рядок UTF-8 до формату, використовуваного в URL, тобто видаляє діакритичні знаки та замінює всі символи, окрім букв англійського алфавіту та цифр, на дефіс.
 
@@ -129,8 +129,8 @@ Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
 Потрібне розширення PHP `intl`.
 
 
-trim(string $s, string $charlist=null): string .[method]
---------------------------------------------------------
+trim(string $s, ?string $charlist=null): string .[method]
+---------------------------------------------------------
 
 Обрізає пробіли (або інші символи, зазначені другим параметром) з початку і кінця рядка UTF-8.
 
@@ -186,8 +186,8 @@ Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
 ```
 
 
-substring(string $s, int $start, int $length=null): string .[method]
---------------------------------------------------------------------
+substring(string $s, int $start, ?int $length=null): string .[method]
+---------------------------------------------------------------------
 
 Повертає частину рядка UTF-8 `$s`, задану початковою позицією `$start` і довжиною `$length`. Якщо `$start` від'ємний, то рядок, що повертається, починатиметься з символу -`$start` символу з кінця.
 
@@ -266,8 +266,8 @@ Strings::length('červená'); // 7
 \--
 
 
-compare(string $left, string $right, int $length=null): bool .[method]
-----------------------------------------------------------------------
+compare(string $left, string $right, ?int $length=null): bool .[method]
+-----------------------------------------------------------------------
 
 Порівняння двох рядків UTF-8 або частин рядків без урахування регістру. Якщо `$length` містить null, то порівнюються цілі рядки, якщо від'ємно, то порівнюється відповідна кількість символів з кінця рядків, інакше порівнюється відповідна кількість символів з початку.
 
@@ -483,8 +483,8 @@ Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
 ```
 
 
-matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false): array .[method]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+matchAll(string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator .[method]
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 Шукає в рядку всі входження, що відповідають регулярному виразу, і повертає масив масивів, що містять знайдений вираз і кожен підвираз.
 
@@ -550,6 +550,16 @@ Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
 ] */
 ```
 
+Якщо `$lazy` є `true`, функція повертає `Generator` замість масиву, що дає значні переваги у продуктивності при роботі з великими рядками. Генератор дозволяє шукати збіги поступово, а не обробляти весь рядок одразу. Це дозволяє ефективно працювати з дуже великими вхідними текстами. Крім того, ви можете перервати обробку в будь-який момент, якщо знайдете потрібний збіг, заощадивши час обчислень.
+
+```php
+$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
+foreach ($matches as $match) {
+    echo "Found: $match[0]\n";
+    // Processing can be interrupted at any time
+}
+```
+
 
 replace(string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false): string .[method]
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/utils/uk/validators.texy b/utils/uk/validators.texy
index 3af96283f4..6b4583fd64 100644
--- a/utils/uk/validators.texy
+++ b/utils/uk/validators.texy
@@ -120,8 +120,8 @@ Validators::assert('Lorem ipsum dolor sit', 'string:78');
 ```
 
 
-assertField(array $array, string|int $key, string $expected=null, string $label=null): void .[method]
------------------------------------------------------------------------------------------------------
+assertField(array $array, string|int $key, ?string $expected=null, ?string $label=null): void .[method]
+-------------------------------------------------------------------------------------------------------
 
 Перевіряє, що елемент під ключем `$key` у полі `$array` є одним з [очікуваних типів |#Expected-Types], розділених зірочкою. Якщо ні, то викидається виняток [api:Nette\Utils\AssertionException]. Рядок `item '%' in array` у тексті виключення може бути замінено іншим параметром `$label`.
 
diff --git a/www/bg/10-reasons-why-nette.texy b/www/bg/10-reasons-why-nette.texy
index 76fa90b28c..22806ab98c 100644
--- a/www/bg/10-reasons-why-nette.texy
+++ b/www/bg/10-reasons-why-nette.texy
@@ -16,8 +16,8 @@
 Nette внася комфорт и ефективност в света на уеб разработчиците чрез иновативни инструменти и техники. Кои са основните характеристики, които правят Nette уникална и съществена част от инструментариума на разработчика? Нека да разгледаме!
 
 
-#№1 Nette ви глези
-------------------
+#1 Nette ви глези
+-----------------
 
 Когато преди двадесет години започна да се оформя рамката Nette, тя се въртеше около една единствена цел: Как да създаваме уебсайтове възможно най-удобно? Как да направим живота на програмистите възможно най-лесен? Как да направим уеб разработката секси?
 
diff --git a/www/fr/10-reasons-why-nette.texy b/www/fr/10-reasons-why-nette.texy
index 428ae08fa7..43a6208026 100644
--- a/www/fr/10-reasons-why-nette.texy
+++ b/www/fr/10-reasons-why-nette.texy
@@ -52,7 +52,7 @@ Avec Nette, vous construisez des pages à partir de composants d'interface utili
 Cette caractéristique unique distingue Nette de tous les autres acteurs importants du marché. Elle vous permet de créer et de maintenir efficacement des applications web. Avec Nette, travailler avec l'interface utilisateur devient une expérience fluide et agréable.
 
 
-Ensemble de forfaits flexibles #5
+#5 Ensemble de forfaits flexibles
 ---------------------------------
 
 Nette est un ensemble de [paquets autonomes |www:packages]. Ils comprennent l'[outil de débogage Tracy |tracy:], le [système de templates Latte de nouvelle génération |latte:], l'[excellent conteneur d'injection de dépendances |dependency-injection:], des [formulaires |forms:], et bien d'autres choses encore. Chaque paquet a une documentation détaillée lisible et réside dans un dépôt séparé sur GitHub.
diff --git a/www/pt/10-reasons-why-nette.texy b/www/pt/10-reasons-why-nette.texy
index d4f10518e6..75a704b013 100644
--- a/www/pt/10-reasons-why-nette.texy
+++ b/www/pt/10-reasons-why-nette.texy
@@ -52,7 +52,7 @@ Com Nette, você constrói páginas a partir de componentes UI reutilizáveis. 
 Esta característica única distingue a Nette de todos os outros players significativos no mercado. Ela permite criar e manter aplicações web de forma eficiente. Com Nette, trabalhar com a UI se torna uma experiência suave e agradável.
 
 
-Conjunto de Pacotes Flexíveis #5
+#5 Conjunto de Pacotes Flexíveis
 --------------------------------
 
 Nette é um conjunto de [pacotes autônomos |www:packages]. Eles incluem a [ferramenta |tracy:] viciante [de depuração Tracy |tracy:], o [sistema de última geração de modelos Latte |latte:], o [excelente Recipiente de Injeção de Dependência |dependency-injection:], [formulários |forms:] e muito mais. Cada pacote tem uma documentação detalhada legível e reside em um repositório separado no GitHub.
diff --git a/www/tr/10-reasons-why-nette.texy b/www/tr/10-reasons-why-nette.texy
index 404d140fff..6cfb0fef8b 100644
--- a/www/tr/10-reasons-why-nette.texy
+++ b/www/tr/10-reasons-why-nette.texy
@@ -34,7 +34,7 @@ Nette örnek olarak liderlik eder. İyi alışkanlıklar öğreten ve kanıtlanm
 Nette topluluğu, şu anda başarılı ve önemli projelerin arkasında olan bir dizi şahsiyeti yetiştirmiştir. Binlerce programcı için Nette, profesyonel gelişim yolunda bir akıl hocası haline geldi. Siz de katılın ve Nette'in kodunuzun ve uygulamalarınızın kalitesini nasıl olumlu yönde etkileyeceğini keşfedin.
 
 
-#Uygulamalarınızın 3 Numaralı Güvenilir Koruyucusu
+#3 Uygulamalarınızın Numaralı Güvenilir Koruyucusu
 --------------------------------------------------
 
 Nette uygulamalarınızı korur. Yıllar içinde, güvenliği son derece ciddiye alan bir araç olarak ün kazanmıştır. Güvenlik açıklarına karşı ustaca koruma sağlayarak, geliştiricilerin güvenlikten ödün vermeden çalışmalarını her zaman kolaylaştırır.